已合并
[Ubse] #feat# 支持获取当前部署环境, 若为仿真则不启用hcom主备倒换能力 #1496
[Ubse] #feat# 支持获取当前部署环境, 若为仿真则不启用hcom主备倒换能力 #1496
已合并
朱程成创建于 1 天前
6 个文件变更+240-17
Msrc/adapter_plugins/mti/smbios/ubse_smbios.cpp+31-0
@@ -22,6 +22,9 @@ namespace ubse::adapter_plugins::smbios {
22using namespace ubse::common::def;22using namespace ubse::common::def;
23using namespace ubse::log;23using namespace ubse::log;
24 24 
25+// QEMU虚拟机(仿真环境)的系统制造商标识,小写形式用于大小写不敏感匹配
26+const std::string QEMU_MANUFACTURER = "qemu";
27+ 
25UBSE_DEFINE_THIS_MODULE("ubse");28UBSE_DEFINE_THIS_MODULE("ubse");
26 29 
27UbseResult UbseSmbios::GetMeshType(UbseMeshType& meshType)30UbseResult UbseSmbios::GetMeshType(UbseMeshType& meshType)
@@ -47,6 +50,34 @@ bool UbseSmbios::IsClosType()
47 return meshType == UbseMeshType::CLOS;50 return meshType == UbseMeshType::CLOS;
48}51}
49 52 
53+UbseResult UbseSmbios::GetSystemManufacturer(std::string& manufacturer)
54+{
55+ auto sysInfo = impl::UbseSmbiosImpl::GetInstance().GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>();
56+ if (sysInfo == nullptr) {
57+ UBSE_LOG_ERROR << "Get system information failed";
58+ return UBSE_ERROR;
59+ }
60+ if (sysInfo->manufacturer.empty()) {
61+ UBSE_LOG_ERROR << "SMBIOS system manufacturer is empty";
62+ return UBSE_ERROR;
63+ }
64+ manufacturer = sysInfo->manufacturer;
65+ return UBSE_OK;
66+}
67+ 
68+// 判断是否为QEMU虚拟机(仿真环境),获取失败时默认为非QEMU,即默认返回false
69+bool UbseSmbios::IsQemuVm()
70+{
71+ std::string manufacturer;
72+ if (GetSystemManufacturer(manufacturer) != UBSE_OK) {
73+ UBSE_LOG_ERROR << "Failed to get system manufacturer for QEMU check";
74+ return false;
75+ }
76+ std::transform(manufacturer.begin(), manufacturer.end(), manufacturer.begin(),
77+ [](unsigned char ch) { return static_cast<char>(std::tolower(ch)); });
78+ return manufacturer == QEMU_MANUFACTURER;
79+}
80+ 
50bool UbseSmbios::Is1650V100Cpu()81bool UbseSmbios::Is1650V100Cpu()
51{82{
52 auto cpuInfo = impl::UbseSmbiosImpl::GetInstance().GetSmbiosTypeInfo<UbseSmbiosType::TYPE_4>();83 auto cpuInfo = impl::UbseSmbiosImpl::GetInstance().GetSmbiosTypeInfo<UbseSmbiosType::TYPE_4>();
Msrc/adapter_plugins/mti/smbios/ubse_smbios_def.cpp+40-2
@@ -164,7 +164,7 @@ inline SmbiosOffset QWORD(uint8_t* buf)
164 164 
165void SmbiosStructureType1::LogSmbiosStructTypeInfo()165void SmbiosStructureType1::LogSmbiosStructTypeInfo()
166{166{
167- UBSE_LOG_WARN << "Smbios structure type 1 info not supported";167+ UBSE_LOG_INFO << "Smbios system information: manufacturer=" << manufacturer;
168}168}
169 169 
170void SmbiosStructureType4::LogSmbiosStructTypeInfo()170void SmbiosStructureType4::LogSmbiosStructTypeInfo()
@@ -204,7 +204,45 @@ void SmbiosHeader::FillHeaderFromBuf(uint8_t* buf)
204 204 
205UbseResult SmbiosStructureType1::FillSmbiosStructFromBuf()205UbseResult SmbiosStructureType1::FillSmbiosStructFromBuf()
206{206{
207- return UBSE_ERR_NOT_SUPPORTED;207+ constexpr size_t MANUFACTURER_OFFSET = 0x04;
208+ if (header.data == nullptr) {
209+ UBSE_LOG_ERROR << "SMBIOS system information data is null";
210+ return UBSE_ERROR_NULLPTR;
211+ }
212+ if (header.length <= MANUFACTURER_OFFSET) {
213+ UBSE_LOG_ERROR << "SMBIOS system information is too short, length=" << static_cast<uint32_t>(header.length);
214+ return UBSE_ERROR_INVAL;
215+ }
216+ /*
217+ * SMBIOS Type 1由格式化区域和紧随其后的字符串表组成,Manufacturer字段与Manufacturer字符串位于不同区域。
218+ * 以下示例假设header.length为0x1B
219+ *
220+ * 1. 格式化区域:[header.data, header.data + header.length)
221+ * +--------+------+------------------------------+
222+ * | 偏移 | 值 | 含义 |
223+ * +--------+------+------------------------------+
224+ * | 0x04 | 0x01 | Manufacturer引用字符串表第1项 |
225+ * +--------+------+------------------------------+
226+ *
227+ * 2. 字符串表:从header.data + header.length开始
228+ * +------+-------------------+--------------------+
229+ * | 编号 | 字符串 | 含义 |
230+ * +------+-------------------+--------------------+
231+ * | 1 | "QEMU\0" | 第1项,即厂商 |
232+ * | 2 | "Standard PC\0" | 第2项 |
233+ * | 结束 | "\0" | 结束字符串表 |
234+ * +------+-------------------+--------------------+
235+ *
236+ * 映射关系:格式化区域Manufacturer值0x01 -> 字符串表编号1 -> "QEMU"
237+ */
238+ const uint8_t manufacturerStringNumber = header.data[MANUFACTURER_OFFSET];
239+ const auto ret = GetSmbiosString(manufacturerStringNumber, manufacturer);
240+ if (ret != UBSE_OK) {
241+ UBSE_LOG_ERROR << "Failed to get SMBIOS system manufacturer, ret=" << ret;
242+ return ret;
243+ }
244+ LogSmbiosStructTypeInfo();
245+ return UBSE_OK;
208}246}
209 247 
210UbseResult SmbiosStructure::GetSmbiosString(uint8_t stringNumber, std::string& value) const248UbseResult SmbiosStructure::GetSmbiosString(uint8_t stringNumber, std::string& value) const
Msrc/adapter_plugins/mti/smbios/ubse_smbios_def.h+1-1
@@ -116,7 +116,7 @@ public:
116 void LogSmbiosStructTypeInfo() override;116 void LogSmbiosStructTypeInfo() override;
117 117 
118public:118public:
119- std::array<char, TYPE_1_MAX_LEN> manufacturer;119+ std::string manufacturer;
120 std::array<char, PRODUCT_NAME_MAX_LEN> productName;120 std::array<char, PRODUCT_NAME_MAX_LEN> productName;
121 std::array<char, TYPE_1_MAX_LEN> version;121 std::array<char, TYPE_1_MAX_LEN> version;
122 std::array<char, TYPE_1_MAX_LEN> serialNumber;122 std::array<char, TYPE_1_MAX_LEN> serialNumber;
Msrc/framework/com/engine/ubse_com_engine.cpp+14-1
@@ -603,7 +603,20 @@ void UbseComEngine::InitEngineOptions()
603 hcomNetService_->SetMaxConnectionCount(NO_500);603 hcomNetService_->SetMaxConnectionCount(NO_500);
604 hcomNetService_->SetEnableMrCache(true);604 hcomNetService_->SetEnableMrCache(true);
605 hcomNetService_->SetCtxStoreCapacity(NO_2048);605 hcomNetService_->SetCtxStoreCapacity(NO_2048);
606- hcomNetService_->SetActiveBackup(false);606+ // 仿真环境(QEMU虚拟机)不支持hcom主备倒换;物理环境默认开启主备倒换。
607+ // 注意:制造商信息获取失败与仿真环境分开处理,失败时打WARN便于现场区分高可用降级原因。
608+ std::string manufacturer;
609+ auto ret = UbseSmbios::GetInstance().GetSystemManufacturer(manufacturer);
610+ if (ret != UBSE_OK) {
611+ UBSE_LOG_WARN << "get system manufacturer failed, close hcom backup.";
612+ hcomNetService_->SetActiveBackup(false);
613+ } else if (UbseSmbios::GetInstance().IsQemuVm()) {
614+ UBSE_LOG_INFO << "current system manufacturer is " << manufacturer << ", simulation env, close hcom backup.";
615+ hcomNetService_->SetActiveBackup(false);
616+ } else {
617+ UBSE_LOG_INFO << "current system manufacturer is " << manufacturer << ", active hcom backup.";
618+ hcomNetService_->SetActiveBackup(true);
619+ }
607}620}
608 621 
609void UbseComEngine::RegisterEngineHandlers()622void UbseComEngine::RegisterEngineHandlers()
Msrc/include/adapter_plugins/mti/ubse_smbios.h+16-0
@@ -14,6 +14,7 @@
14#define UBSE_SMBIOS_H14#define UBSE_SMBIOS_H
15 15 
16#include <cstdint>16#include <cstdint>
17+#include <string>
17enum class UbseMeshType18enum class UbseMeshType
18{19{
19 FULL_MESH = 0x80,20 FULL_MESH = 0x80,
@@ -43,6 +44,21 @@ public:
43 */44 */
44 bool IsClosType();45 bool IsClosType();
45 46 
47+ /**
48+ * @brief 获取系统制造商名称
49+ * @param manufacturer 系统制造商(来自SMBIOS Type 1结构的Manufacturer字段,QEMU虚拟机上为"QEMU"
50+ * @return UBSE_OK 标识成功
51+ * @return UBSE_ERROR 表示失败
52+ */
53+ uint32_t GetSystemManufacturer(std::string& manufacturer);
54+ 
55+ /**
56+ * @brief 判断当前是否运行在QEMU虚拟机(仿真环境)
57+ * @return true 表示系统制造商为QEMU(大小写不敏感)
58+ * @return false 表示非QEMU或制造商信息获取失败
59+ */
60+ bool IsQemuVm();
61+ 
46 /**62 /**
47 * @brief 判断CPU是否为支持EID共享的1650v100型号63 * @brief 判断CPU是否为支持EID共享的1650v100型号
48 */64 */
Mtest/UT/adapter_plugins/mti/smbios/test_ubse_smbios.cpp+138-13
@@ -29,11 +29,6 @@ using namespace ubse::log;
29// ==================== Test helpers ====================29// ==================== Test helpers ====================
30 30 
31// Expose protected members for unit testing31// Expose protected members for unit testing
32-class TestableSmbiosStructureType1 : public SmbiosStructureType1 {
33-public:
34- using SmbiosStructureType1::FillSmbiosStructFromBuf;
35-};
36- 
37class TestableSmbiosStructureType4 : public SmbiosStructureType4 {32class TestableSmbiosStructureType4 : public SmbiosStructureType4 {
38public:33public:
39 using SmbiosStructure::DecodeDmiTable;34 using SmbiosStructure::DecodeDmiTable;
@@ -135,6 +130,24 @@ static std::vector<uint8_t> MakeProcessorInfo(uint8_t versionStringNumber, const
135 return buf;130 return buf;
136}131}
137 132 
133+// Build a type-1 (System Information) struct; manufacturer string number sits at offset 0x04
134+static std::vector<uint8_t> MakeSystemInfo(uint8_t manufacturerStringNumber, const std::vector<std::string>& strings)
135+{
136+ constexpr uint8_t systemInfoLength = 0x1B;
137+ constexpr size_t manufacturerOffset = 0x04;
138+ std::vector<uint8_t> buf(systemInfoLength, 0);
139+ buf[0] = static_cast<uint8_t>(UbseSmbiosType::TYPE_1);
140+ buf[1] = systemInfoLength;
141+ buf[2] = 0x01;
142+ buf[manufacturerOffset] = manufacturerStringNumber;
143+ for (const auto& value : strings) {
144+ buf.insert(buf.end(), value.begin(), value.end());
145+ buf.push_back('\0');
146+ }
147+ buf.push_back('\0');
148+ return buf;
149+}
150+ 
138// Setup header on TestableSmbiosSuperPodBasicInfo for FillSmbiosStructFromBuf151// Setup header on TestableSmbiosSuperPodBasicInfo for FillSmbiosStructFromBuf
139static void SetupSuperPodHeader(TestableSmbiosSuperPodBasicInfo& info, uint8_t* buf, size_t bufSize, uint8_t length)152static void SetupSuperPodHeader(TestableSmbiosSuperPodBasicInfo& info, uint8_t* buf, size_t bufSize, uint8_t length)
140{153{
@@ -215,21 +228,133 @@ TEST_F(TestUbseSmbios, FillHeaderFromBuf_EndOfTableType)
215 228 
216// ==================== SmbiosStructureType1 ====================229// ==================== SmbiosStructureType1 ====================
217 230 
218-TEST_F(TestUbseSmbios, Type1_FillSmbiosStructFromBuf_ReturnsNotSupported)
219-{
220- EXPECT_EQ(TestableSmbiosStructureType1().FillSmbiosStructFromBuf(), UBSE_ERR_NOT_SUPPORTED);
221-}
222- 
223TEST_F(TestUbseSmbios, Type1_LogAndDefaults)231TEST_F(TestUbseSmbios, Type1_LogAndDefaults)
224{232{
225 SmbiosStructureType1 t;233 SmbiosStructureType1 t;
226 EXPECT_NO_THROW(t.LogSmbiosStructTypeInfo());234 EXPECT_NO_THROW(t.LogSmbiosStructTypeInfo());
227- EXPECT_EQ(t.manufacturer.size(), 32u);235+ EXPECT_TRUE(t.manufacturer.empty());
228 EXPECT_EQ(t.productName.size(), 64u);236 EXPECT_EQ(t.productName.size(), 64u);
229 EXPECT_EQ(t.serialNumber.size(), 32u);237 EXPECT_EQ(t.serialNumber.size(), 32u);
230 EXPECT_EQ(SmbiosStructureType1::type, UbseSmbiosType::TYPE_1);238 EXPECT_EQ(SmbiosStructureType1::type, UbseSmbiosType::TYPE_1);
231}239}
232 240 
241+TEST_F(TestUbseSmbios, Type1_DecodeManufacturer)
242+{
243+ SmbiosStructureType1 info;
244+ auto dmi = MakeSystemInfo(1, {"QEMU", "Standard PC"});
245+ 
246+ EXPECT_EQ(info.DecodeDmiTable(dmi, FLAG_STOP_AT_EOT, UbseSmbiosType::TYPE_1), UBSE_OK);
247+ EXPECT_EQ(info.manufacturer, "QEMU");
248+}
249+ 
250+TEST_F(TestUbseSmbios, Type1_DecodeManufacturerSecondString)
251+{
252+ SmbiosStructureType1 info;
253+ auto dmi = MakeSystemInfo(2, {"Prefix", "QEMU"});
254+ 
255+ EXPECT_EQ(info.DecodeDmiTable(dmi, FLAG_STOP_AT_EOT, UbseSmbiosType::TYPE_1), UBSE_OK);
256+ EXPECT_EQ(info.manufacturer, "QEMU");
257+}
258+ 
259+TEST_F(TestUbseSmbios, Type1_RejectsEmptyManufacturerStringNumber)
260+{
261+ SmbiosStructureType1 info;
262+ auto dmi = MakeSystemInfo(0, {"QEMU"});
263+ 
264+ EXPECT_NE(info.DecodeDmiTable(dmi, FLAG_STOP_AT_EOT, UbseSmbiosType::TYPE_1), UBSE_OK);
265+}
266+ 
267+TEST_F(TestUbseSmbios, Type1_RejectsMissingManufacturerString)
268+{
269+ SmbiosStructureType1 info;
270+ auto dmi = MakeSystemInfo(2, {"QEMU"});
271+ 
272+ EXPECT_NE(info.DecodeDmiTable(dmi, FLAG_STOP_AT_EOT, UbseSmbiosType::TYPE_1), UBSE_OK);
273+}
274+ 
275+TEST_F(TestUbseSmbios, Type1_RejectsShortStructure)
276+{
277+ SmbiosStructureType1 info;
278+ // header.length = 4 (header only), shorter than manufacturer offset 0x04
279+ std::vector<uint8_t> dmi = {0x01, 0x04, 0x00, 0x00, 0x00, 0x00};
280+ 
281+ EXPECT_NE(info.DecodeDmiTable(dmi, FLAG_STOP_AT_EOT, UbseSmbiosType::TYPE_1), UBSE_OK);
282+}
283+ 
284+TEST_F(TestUbseSmbios, GetSystemManufacturer_Success)
285+{
286+ auto sys = std::make_shared<SmbiosStructureType1>();
287+ sys->manufacturer = "QEMU";
288+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
289+ 
290+ std::string manufacturer;
291+ EXPECT_EQ(UbseSmbios::GetInstance().GetSystemManufacturer(manufacturer), UBSE_OK);
292+ EXPECT_EQ(manufacturer, "QEMU");
293+}
294+ 
295+TEST_F(TestUbseSmbios, GetSystemManufacturer_FailsWhenInfoMissing)
296+{
297+ std::shared_ptr<SmbiosStructureType1> nullInfo;
298+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(nullInfo));
299+ 
300+ std::string manufacturer;
301+ EXPECT_NE(UbseSmbios::GetInstance().GetSystemManufacturer(manufacturer), UBSE_OK);
302+}
303+ 
304+TEST_F(TestUbseSmbios, GetSystemManufacturer_FailsWhenManufacturerEmpty)
305+{
306+ auto sys = std::make_shared<SmbiosStructureType1>();
307+ sys->manufacturer = "";
308+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
309+ 
310+ std::string manufacturer;
311+ EXPECT_NE(UbseSmbios::GetInstance().GetSystemManufacturer(manufacturer), UBSE_OK);
312+}
313+ 
314+TEST_F(TestUbseSmbios, IsQemuVm_TrueWhenManufacturerIsQemu)
315+{
316+ auto sys = std::make_shared<SmbiosStructureType1>();
317+ sys->manufacturer = "QEMU";
318+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
319+ 
320+ EXPECT_TRUE(UbseSmbios::GetInstance().IsQemuVm());
321+}
322+ 
323+TEST_F(TestUbseSmbios, IsQemuVm_TrueWhenManufacturerCaseInsensitive)
324+{
325+ auto sys = std::make_shared<SmbiosStructureType1>();
326+ sys->manufacturer = "qemu";
327+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
328+ 
329+ EXPECT_TRUE(UbseSmbios::GetInstance().IsQemuVm());
330+}
331+ 
332+TEST_F(TestUbseSmbios, IsQemuVm_FalseWhenManufacturerIsHuawei)
333+{
334+ auto sys = std::make_shared<SmbiosStructureType1>();
335+ sys->manufacturer = "Huawei";
336+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
337+ 
338+ EXPECT_FALSE(UbseSmbios::GetInstance().IsQemuVm());
339+}
340+ 
341+TEST_F(TestUbseSmbios, IsQemuVm_FalseWhenInfoMissing)
342+{
343+ std::shared_ptr<SmbiosStructureType1> nullInfo;
344+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(nullInfo));
345+ 
346+ EXPECT_FALSE(UbseSmbios::GetInstance().IsQemuVm());
347+}
348+ 
349+TEST_F(TestUbseSmbios, IsQemuVm_FalseWhenManufacturerEmpty)
350+{
351+ auto sys = std::make_shared<SmbiosStructureType1>();
352+ sys->manufacturer = "";
353+ MOCKER_CPP(&impl::UbseSmbiosImpl::GetSmbiosTypeInfo<UbseSmbiosType::TYPE_1>).stubs().will(returnValue(sys));
354+ 
355+ EXPECT_FALSE(UbseSmbios::GetInstance().IsQemuVm());
356+}
357+ 
233// ==================== SmbiosStructureType4 ====================358// ==================== SmbiosStructureType4 ====================
234 359 
235TEST_F(TestUbseSmbios, Type4_DecodeProcessorVersion)360TEST_F(TestUbseSmbios, Type4_DecodeProcessorVersion)
@@ -396,12 +521,12 @@ TEST_F(TestUbseSmbios, DecodeDmiTable_StopAtEndOfTable)
396 EXPECT_NE(info.DecodeDmiTable(buf, 0, UbseSmbiosType::SUPER_POD_BASIC_INFO_T), UBSE_OK);521 EXPECT_NE(info.DecodeDmiTable(buf, 0, UbseSmbiosType::SUPER_POD_BASIC_INFO_T), UBSE_OK);
397}522}
398 523 
399-TEST_F(TestUbseSmbios, DecodeDmiTable_Type1_ReturnsNotSupported)524+TEST_F(TestUbseSmbios, DecodeDmiTable_Type1_RejectsZeroManufacturerStringNumber)
400{525{
401 SmbiosStructureType1 t;526 SmbiosStructureType1 t;
402 auto buf = MakeDmiBuf(6, {0x00, 0x00});527 auto buf = MakeDmiBuf(6, {0x00, 0x00});
403 buf[0] = 0x01; // change type to 1528 buf[0] = 0x01; // change type to 1
404- EXPECT_EQ(t.DecodeDmiTable(buf, 0, UbseSmbiosType::TYPE_1), UBSE_ERR_NOT_SUPPORTED);529+ EXPECT_EQ(t.DecodeDmiTable(buf, 0, UbseSmbiosType::TYPE_1), UBSE_ERROR_INVAL);
405}530}
406 531 
407TEST_F(TestUbseSmbios, DecodeDmiTable_StructureLengthExceedsBuffer)532TEST_F(TestUbseSmbios, DecodeDmiTable_StructureLengthExceedsBuffer)