已合并
iBMA停止后恢复带外获取的信息 #381
iBMA停止后恢复带外获取的信息 #381
已合并
fantao创建于 3月21日
25 个文件变更+9068-6600
@@ -1,5 +1,8 @@
1# Changelog1# Changelog
2All notable changes to this project will be documented in this file.2All notable changes to this project will be documented in this file.
3+## [1.90.53] - 2026-03-20
4+iBMA停止后恢复带外获取的信息
5+ 
3## [1.90.52] - 2026-03-206## [1.90.52] - 2026-03-20
4修复权限问题7修复权限问题
5 8 
@@ -1,6 +1,6 @@
1{1{
2 "name": "network_adapter",2 "name": "network_adapter",
3- "version": "1.90.52",3+ "version": "1.90.53",
4 "type": "application",4 "type": "application",
5 "deployConfig": "hardware.service",5 "deployConfig": "hardware.service",
6 "author": "Huawei",6 "author": "Huawei",
@@ -22,6 +22,7 @@ local json_null = json.null
22local c_network_bridge = require 'device.class.network_bridge'22local c_network_bridge = require 'device.class.network_bridge'
23local c_network_bonding = require 'device.class.network_bonding'23local c_network_bonding = require 'device.class.network_bonding'
24local port_mgmt = require 'device.class.nic_mgmt.port_mgmt'24local port_mgmt = require 'device.class.nic_mgmt.port_mgmt'
25+local card_mgmt = require 'device.class.nic_mgmt.card_mgmt'
25 26 
26local is_na = c_handler_base.is_na27local is_na = c_handler_base.is_na
27local get_oem_huawei = c_handler_base.get_oem_huawei28local get_oem_huawei = c_handler_base.get_oem_huawei
@@ -374,6 +375,17 @@ local function get_port_parent_card(port)
374 return c_network_adapter.collection:find({NodeId = parent.NodeId})375 return c_network_adapter.collection:find({NodeId = parent.NodeId})
375end376end
376 377 
378+local function update_firmware_version_from_bma(na, oem_huawei)
379+ if oem_huawei.FirmwareVersion == nil then
380+ return
381+ end
382+ na.FirmwareVersion = update_if_not_config(na.FirmwareVersion,
383+ default_na(oem_huawei.FirmwareVersion))
384+ pcall(function()
385+ card_mgmt.get_instance():update_firmware_version_to_device_obj(na, na.FirmwareVersion)
386+ end)
387+end
388+ 
377-- bma上报更新bmc的以太网卡(LOM、MEZZ、PCIE)属性,BMC能预配置的不从BMA更新389-- bma上报更新bmc的以太网卡(LOM、MEZZ、PCIE)属性,BMC能预配置的不从BMA更新
378function c_handler_eth:update_network_card(port, data, oem_huawei)390function c_handler_eth:update_network_card(port, data, oem_huawei)
379 if port.Type == BUSINESSPORT_CARD_TYPE_VIR or port.WorkloadType == 1 then391 if port.Type == BUSINESSPORT_CARD_TYPE_VIR or port.WorkloadType == 1 then
@@ -395,8 +407,7 @@ function c_handler_eth:update_network_card(port, data, oem_huawei)
395 na.DisplayName = update_if_not_config(na.DisplayName, default_na(oem_huawei.NICName))407 na.DisplayName = update_if_not_config(na.DisplayName, default_na(oem_huawei.NICName))
396 408 
397 -- 更新OS侧网卡固件版本409 -- 更新OS侧网卡固件版本
398- na.FirmwareVersion = update_if_not_config(na.FirmwareVersion,410+ update_firmware_version_from_bma(na, oem_huawei)
399- default_na(oem_huawei.FirmwareVersion))
400 411 
401 -- 更新OS侧网卡驱动名称412 -- 更新OS侧网卡驱动名称
402 if oem_huawei.DriverInfo ~= nil and oem_huawei.DriverInfo.DriverName ~= nil and413 if oem_huawei.DriverInfo ~= nil and oem_huawei.DriverInfo.DriverName ~= nil and
@@ -444,6 +455,9 @@ function c_handler_eth:update_network_port_bdf(port, data, oem_huawei)
444 -- team/bridge采用NICName作为索引455 -- team/bridge采用NICName作为索引
445 port.BDF = default_na(oem_huawei.NICName)456 port.BDF = default_na(oem_huawei.NICName)
446 end457 end
458+ pcall(function()
459+ port_mgmt.get_instance():update_bdf_to_device_obj(port, port.BDF)
460+ end)
447end461end
448 462 
449function c_handler_eth:update_ip_addresses(port, ip_class, addresses)463function c_handler_eth:update_ip_addresses(port, ip_class, addresses)
@@ -527,6 +541,48 @@ local function update_link_status_to_device_obj(port, link_status)
527 end)541 end)
528end542end
529 543 
544+local function update_full_duplex_from_bma(port, data)
545+ if data.FullDuplex == nil then
546+ return
547+ end
548+ if data.FullDuplex == json.null then
549+ port.FullDuplex = 255
550+ else
551+ port.FullDuplex = data.FullDuplex and 1 or 0
552+ end
553+ pcall(function()
554+ port_mgmt.get_instance():update_full_duplex_to_device_obj(port, port.FullDuplex)
555+ end)
556+end
557+ 
558+local function update_speed_mbps_from_bma(port, data)
559+ if data.SpeedMbps == nil then
560+ return
561+ end
562+ if data.SpeedMbps == json_null then
563+ port.SpeedMbps = 4294967295
564+ else
565+ port.SpeedMbps = update_if_valid(port.SpeedMbps, data.SpeedMbps)
566+ end
567+ pcall(function()
568+ port_mgmt.get_instance():update_speed_mbps_to_device_obj(port, port.SpeedMbps)
569+ end)
570+end
571+ 
572+local function update_auto_negotiation_from_bma(port, data)
573+ if data.AutoNeg == nil then
574+ return
575+ end
576+ if data.AutoNeg == json.null then
577+ port.AutoSpeedNegotiation = 255
578+ else
579+ port.AutoSpeedNegotiation = data.AutoNeg and 1 or 0
580+ end
581+ pcall(function()
582+ port_mgmt.get_instance():update_auto_negotiation_to_device_obj(port, port.AutoSpeedNegotiation)
583+ end)
584+end
585+ 
530function c_handler_eth:update_network_port(port, data, oem_huawei)586function c_handler_eth:update_network_port(port, data, oem_huawei)
531 if port and port.WorkloadType and port.WorkloadType == 1 then587 if port and port.WorkloadType and port.WorkloadType == 1 then
532 return588 return
@@ -547,28 +603,16 @@ function c_handler_eth:update_network_port(port, data, oem_huawei)
547 port.AgentID = update_if_valid(port.AgentID, get_odata_id(data))603 port.AgentID = update_if_valid(port.AgentID, get_odata_id(data))
548 604 
549 -- 更新BMA FullDuplex信息605 -- 更新BMA FullDuplex信息
550- if data.FullDuplex == nil or data.FullDuplex == json.null then606+ update_full_duplex_from_bma(port, data)
551- port.FullDuplex = 255
552- else
553- port.FullDuplex = data.FullDuplex and 1 or 0
554- end
555 607 
556 -- 更新BMA MTUSize信息608 -- 更新BMA MTUSize信息
557 port.MTUSize = update_if_valid(port.MTUSize, data.MTUSize)609 port.MTUSize = update_if_valid(port.MTUSize, data.MTUSize)
558 610 
559 -- 更新OS侧网口速率611 -- 更新OS侧网口速率
560- if data.SpeedMbps == json_null then612+ update_speed_mbps_from_bma(port, data)
561- port.SpeedMbps = 4294967295
562- else
563- port.SpeedMbps = update_if_valid(port.SpeedMbps, data.SpeedMbps)
564- end
565 613 
566 -- 更新OS侧自协商模式614 -- 更新OS侧自协商模式
567- if data.AutoNeg == nil or data.AutoNeg == json.null then615+ update_auto_negotiation_from_bma(port, data)
568- port.AutoSpeedNegotiation = 255
569- else
570- port.AutoSpeedNegotiation = data.AutoNeg and 1 or 0
571- end
572 616 
573 -- 更新OS侧网口IPv4信息617 -- 更新OS侧网口IPv4信息
574 local ipv4_address = prepare_ipv4_address(data.IPv4Addresses)618 local ipv4_address = prepare_ipv4_address(data.IPv4Addresses)
@@ -17,6 +17,7 @@ local singleton = require 'mc.singleton'
17local optical_module_mgmt = require 'device.class.nic_mgmt.om_mgmt'17local optical_module_mgmt = require 'device.class.nic_mgmt.om_mgmt'
18local json = require 'cjson'18local json = require 'cjson'
19local json_null = json.null19local json_null = json.null
20+local om_mgmt = require 'device.class.nic_mgmt.om_mgmt'
20 21 
21local get_odata_id = c_handler_base.get_odata_id22local get_odata_id = c_handler_base.get_odata_id
22local get_value_to_update = c_handler_base.get_value_to_update23local get_value_to_update = c_handler_base.get_value_to_update
@@ -172,6 +173,56 @@ local function set_power_state_to_device_obj(op, power_state)
172 end)173 end)
173end174end
174 175 
176+local function update_manufacturer_from_bma(op, data, default_str)
177+ if data.VendorName == nil then
178+ return
179+ end
180+ op.Manufacturer = get_value_to_update(op.Manufacturer, data.VendorName, default_str)
181+ pcall(function()
182+ om_mgmt.get_instance():update_manufacturer_to_device_obj(op, op.Manufacturer)
183+ end)
184+end
185+ 
186+local function update_part_number_from_bma(op, data, default_str)
187+ if data.PartNumber == nil then
188+ return
189+ end
190+ op.PartNumber = get_value_to_update(op.PartNumber, data.PartNumber, default_str)
191+ pcall(function()
192+ om_mgmt.get_instance():update_part_number_to_device_obj(op, op.PartNumber)
193+ end)
194+end
195+ 
196+local function update_serial_number_from_bma(op, data, default_str)
197+ if data.SerialNumber == nil then
198+ return
199+ end
200+ op.SerialNumber = get_value_to_update(op.SerialNumber, data.SerialNumber, default_str)
201+ pcall(function()
202+ om_mgmt.get_instance():update_serial_number_to_device_obj(op, op.SerialNumber)
203+ end)
204+end
205+ 
206+local function update_production_date_from_bma(op, data, default_str)
207+ if data.ManufactureDate == nil then
208+ return
209+ end
210+ op.ProductionDate = parser_manufacture_date(data.ManufactureDate, default_str)
211+ pcall(function()
212+ om_mgmt.get_instance():update_production_date_to_device_obj(op, op.ProductionDate)
213+ end)
214+end
215+ 
216+local function update_wave_length_nanometer_from_bma(op, data, default_str)
217+ if data.Wavelength == nil then
218+ return
219+ end
220+ op.WaveLengthNanometer = get_value_to_update(op.WaveLengthNanometer, data.Wavelength, default_str)
221+ pcall(function()
222+ om_mgmt.get_instance():update_wave_length_nanometer_to_device_obj(op, op.WaveLengthNanometer)
223+ end)
224+end
225+ 
175c_handler_optical.update_presence = update_presence226c_handler_optical.update_presence = update_presence
176c_handler_optical.set_presence_to_device_obj = set_presence_to_device_obj227c_handler_optical.set_presence_to_device_obj = set_presence_to_device_obj
177 228 
@@ -181,14 +232,12 @@ function c_handler_optical:update_optical(op, data)
181 end232 end
182 local default_str = ""233 local default_str = ""
183 local default_num = 0234 local default_num = 0
184- op.Manufacturer = get_value_to_update(op.Manufacturer, data.VendorName, default_str)235+ update_manufacturer_from_bma(op, data, default_str)
185- op.PartNumber = get_value_to_update(op.PartNumber, data.PartNumber, default_str)236+ update_part_number_from_bma(op, data, default_str)
186- op.SerialNumber = get_value_to_update(op.SerialNumber, data.SerialNumber, default_str)237+ update_serial_number_from_bma(op, data, default_str)
187- if data.ManufactureDate ~= nil then238+ update_production_date_from_bma(op, data, default_str)
188- op.ProductionDate = parser_manufacture_date(data.ManufactureDate, default_str)
189- end
190 op.TransceiverType = get_value_to_update(op.TransceiverType, data.TransceiverType, default_str)239 op.TransceiverType = get_value_to_update(op.TransceiverType, data.TransceiverType, default_str)
191- op.WaveLengthNanometer = get_value_to_update(op.WaveLengthNanometer, data.Wavelength, default_str)240+ update_wave_length_nanometer_from_bma(op, data, default_str)
192 op.FiberConnectionType = get_value_to_update(op.FiberConnectionType, data.MediumMode, default_str)241 op.FiberConnectionType = get_value_to_update(op.FiberConnectionType, data.MediumMode, default_str)
193 if data.speed ~= nil then242 if data.speed ~= nil then
194 op.SupportedSpeedsMbps = parser_speed_array(data.speed)243 op.SupportedSpeedsMbps = parser_speed_array(data.speed)
@@ -91,27 +91,132 @@ local function set_voltage_upper_threshold_critical_to_device_obj(op, voltage)
91 end)91 end)
92end92end
93 93 
94-local function set_bias_current_upper_threshold_critical_to_device_obj(op, value)94+local function update_temperature_upper_threshold_critical_from_bma(op, data, default)
95- if not value then95+ if data.TempHighAlarmCelsius == nil then
96 return96 return
97 end97 end
98- if value == json_null then98+ op.TemperatureUpperThresholdCritical = get_value_to_update(op.TemperatureUpperThresholdCritical,
99- value = 6553599+ data.TempHighAlarmCelsius, default)
100- end100+ pcall(function()
101- pcall(function ()101+ optical_module_mgmt.get_instance():set_temperature_upper_threshold_critical_to_device_obj(
102- optical_module_mgmt.get_instance():set_bias_current_upper_threshold_critical_to_device_obj(op, value)102+ op, op.TemperatureUpperThresholdCritical)
103 end)103 end)
104end104end
105 105 
106-local function set_bias_current_lower_threshold_critical_to_device_obj(op, value)106+local function update_temperature_lower_threshold_critical_from_bma(op, data, default)
107- if not value then107+ if data.TempLowAlarmCelsius == nil then
108 return108 return
109 end109 end
110- if value == json_null then110+ op.TemperatureLowerThresholdCritical = get_value_to_update(op.TemperatureLowerThresholdCritical,
111- value = 65535111+ data.TempLowAlarmCelsius, default)
112+ pcall(function()
113+ optical_module_mgmt.get_instance():set_temperature_lower_threshold_critical_to_device_obj(
114+ op, op.TemperatureLowerThresholdCritical)
115+ end)
116+end
117+ 
118+local function update_tx_bias_current_milli_amps_from_bma(op, data, default_arr)
119+ if data.TxBiasCurrentMilliampere == nil then
120+ return
112 end121 end
113- pcall(function ()122+ op.TXBiasCurrentMilliAmps = get_value_to_update(op.TXBiasCurrentMilliAmps,
114- optical_module_mgmt.get_instance():set_bias_current_lower_threshold_critical_to_device_obj(op, value)123+ data.TxBiasCurrentMilliampere, default_arr)
124+ pcall(function()
125+ optical_module_mgmt.get_instance():set_tx_bias_current_milli_amps_to_device_obj(op, op.TXBiasCurrentMilliAmps)
126+ end)
127+end
128+ 
129+local function update_bc_tx_upper_threshold_critical_from_bma(op, data, default)
130+ if data.TxBiasHighAlarmMilliampere == nil then
131+ return
132+ end
133+ op.BC_TXUpperThresholdCritical = get_value_to_update(op.BC_TXUpperThresholdCritical,
134+ data.TxBiasHighAlarmMilliampere, default)
135+ pcall(function()
136+ optical_module_mgmt.get_instance():set_bias_current_upper_threshold_critical_to_device_obj(
137+ op, op.BC_TXUpperThresholdCritical)
138+ end)
139+end
140+ 
141+local function update_bc_tx_lower_threshold_critical_from_bma(op, data, default)
142+ if data.TxBiasLowAlarmMilliampere == nil then
143+ return
144+ end
145+ op.BC_TXLowerThresholdCritical = get_value_to_update(op.BC_TXLowerThresholdCritical,
146+ data.TxBiasLowAlarmMilliampere, default)
147+ pcall(function()
148+ optical_module_mgmt.get_instance():set_bias_current_lower_threshold_critical_to_device_obj(
149+ op, op.BC_TXLowerThresholdCritical)
150+ end)
151+end
152+ 
153+local function update_tx_output_power_milli_watts_from_bma(op, data, default_arr)
154+ if data.TxPowerCurrentMilliwatt == nil then
155+ return
156+ end
157+ op.TXOutputPowerMilliWatts = get_value_to_update(op.TXOutputPowerMilliWatts,
158+ data.TxPowerCurrentMilliwatt, default_arr)
159+ pcall(function()
160+ optical_module_mgmt.get_instance():set_tx_output_power_milli_watts_to_device_obj(op, op.TXOutputPowerMilliWatts)
161+ end)
162+end
163+ 
164+local function update_power_tx_upper_threshold_critical_from_bma(op, data, default)
165+ if data.TxPowerHighAlarmMilliwatt == nil then
166+ return
167+ end
168+ op.Power_TXUpperThresholdCritical = get_value_to_update(op.Power_TXUpperThresholdCritical,
169+ data.TxPowerHighAlarmMilliwatt, default)
170+ pcall(function()
171+ optical_module_mgmt.get_instance():set_tx_power_upper_threshold_critical_to_device_obj(
172+ op, op.Power_TXUpperThresholdCritical)
173+ end)
174+end
175+ 
176+local function update_power_tx_lower_threshold_critical_from_bma(op, data, default)
177+ if data.TxPowerLowAlarmMilliwatt == nil then
178+ return
179+ end
180+ op.Power_TXLowerThresholdCritical = get_value_to_update(op.Power_TXLowerThresholdCritical,
181+ data.TxPowerLowAlarmMilliwatt, default)
182+ pcall(function()
183+ optical_module_mgmt.get_instance():set_tx_power_lower_threshold_critical_to_device_obj(
184+ op, op.Power_TXLowerThresholdCritical)
185+ end)
186+end
187+ 
188+local function update_rx_input_power_milli_watts_from_bma(op, data, default_arr)
189+ if data.RxPowerCurrentMilliwatt == nil then
190+ return
191+ end
192+ op.RXInputPowerMilliWatts = get_value_to_update(op.RXInputPowerMilliWatts,
193+ data.RxPowerCurrentMilliwatt, default_arr)
194+ pcall(function()
195+ optical_module_mgmt.get_instance():set_rx_input_power_milli_watts_to_device_obj(op, op.RXInputPowerMilliWatts)
196+ end)
197+end
198+ 
199+local function update_rx_upper_threshold_critical_from_bma(op, data, default)
200+ if data.RxPowerHighAlarmMilliwatt == nil then
201+ return
202+ end
203+ op.RXUpperThresholdCritical = get_value_to_update(op.RXUpperThresholdCritical,
204+ data.RxPowerHighAlarmMilliwatt, default)
205+ pcall(function()
206+ optical_module_mgmt.get_instance():set_rx_power_upper_threshold_critical_to_device_obj(
207+ op, op.RXUpperThresholdCritical)
208+ end)
209+end
210+ 
211+local function update_rx_lower_threshold_critical_from_bma(op, data, default)
212+ if data.RxPowerLowAlarmMilliwatt == nil then
213+ return
214+ end
215+ op.RXLowerThresholdCritical = get_value_to_update(op.RXLowerThresholdCritical,
216+ data.RxPowerLowAlarmMilliwatt, default)
217+ pcall(function()
218+ optical_module_mgmt.get_instance():set_rx_power_lower_threshold_critical_to_device_obj(
219+ op, op.RXLowerThresholdCritical)
115 end)220 end)
116end221end
117 222 
@@ -126,10 +231,8 @@ function c_handler_optical_diag:update_optical_diag(op, data)
126 -- bmc.kepler.Systems.OpticalModule.Temperature231 -- bmc.kepler.Systems.OpticalModule.Temperature
127 op.ReadingCelsius = get_value_to_update(op.ReadingCelsius, data.TempCurrentCelsius, default)232 op.ReadingCelsius = get_value_to_update(op.ReadingCelsius, data.TempCurrentCelsius, default)
128 set_temperature_to_device_obj(op, data.TempCurrentCelsius)233 set_temperature_to_device_obj(op, data.TempCurrentCelsius)
129- op.TemperatureUpperThresholdCritical = get_value_to_update(op.TemperatureUpperThresholdCritical,234+ update_temperature_upper_threshold_critical_from_bma(op, data, default)
130- data.TempHighAlarmCelsius, default)235+ update_temperature_lower_threshold_critical_from_bma(op, data, default)
131- op.TemperatureLowerThresholdCritical = get_value_to_update(op.TemperatureLowerThresholdCritical,
132- data.TempLowAlarmCelsius, default)
133 236 
134 -- bmc.kepler.Systems.OpticalModule.Voltage237 -- bmc.kepler.Systems.OpticalModule.Voltage
135 op.SupplyVoltage = get_value_to_update(op.SupplyVoltage, data.VccCurrentVolts, default)238 op.SupplyVoltage = get_value_to_update(op.SupplyVoltage, data.VccCurrentVolts, default)
@@ -142,28 +245,17 @@ function c_handler_optical_diag:update_optical_diag(op, data)
142 set_voltage_lower_threshold_critical_to_device_obj(op, data.VccLowAlarmVolts)245 set_voltage_lower_threshold_critical_to_device_obj(op, data.VccLowAlarmVolts)
143 246 
144 -- bmc.kepler.Systems.OpticalModule.BiasCurrent247 -- bmc.kepler.Systems.OpticalModule.BiasCurrent
145- op.TXBiasCurrentMilliAmps = get_value_to_update(op.TXBiasCurrentMilliAmps,248+ update_tx_bias_current_milli_amps_from_bma(op, data, default_arr)
146- data.TxBiasCurrentMilliampere, default_arr)249+ update_bc_tx_upper_threshold_critical_from_bma(op, data, default)
147- op.BC_TXUpperThresholdCritical = get_value_to_update(op.BC_TXUpperThresholdCritical,250+ update_bc_tx_lower_threshold_critical_from_bma(op, data, default)
148- data.TxBiasHighAlarmMilliampere, default)
149- op.BC_TXLowerThresholdCritical = get_value_to_update(op.BC_TXLowerThresholdCritical,
150- data.TxBiasLowAlarmMilliampere, default)
151- set_bias_current_upper_threshold_critical_to_device_obj(op, data.TxBiasHighAlarmMilliampere)
152- set_bias_current_lower_threshold_critical_to_device_obj(op, data.TxBiasLowAlarmMilliampere)
153 251 
154 -- bmc.kepler.Systems.OpticalModule.Power252 -- bmc.kepler.Systems.OpticalModule.Power
155- op.TXOutputPowerMilliWatts = get_value_to_update(op.TXOutputPowerMilliWatts,253+ update_tx_output_power_milli_watts_from_bma(op, data, default_arr)
156- data.TxPowerCurrentMilliwatt, default_arr)254+ update_power_tx_upper_threshold_critical_from_bma(op, data, default)
157- op.Power_TXUpperThresholdCritical = get_value_to_update(op.Power_TXUpperThresholdCritical,255+ update_power_tx_lower_threshold_critical_from_bma(op, data, default)
158- data.TxPowerHighAlarmMilliwatt, default)256+ update_rx_input_power_milli_watts_from_bma(op, data, default_arr)
159- op.Power_TXLowerThresholdCritical = get_value_to_update(op.Power_TXLowerThresholdCritical,257+ update_rx_upper_threshold_critical_from_bma(op, data, default)
160- data.TxPowerLowAlarmMilliwatt, default)258+ update_rx_lower_threshold_critical_from_bma(op, data, default)
161- op.RXInputPowerMilliWatts = get_value_to_update(op.RXInputPowerMilliWatts,
162- data.RxPowerCurrentMilliwatt, default_arr)
163- op.RXUpperThresholdCritical = get_value_to_update(op.RXUpperThresholdCritical,
164- data.RxPowerHighAlarmMilliwatt, default)
165- op.RXLowerThresholdCritical = get_value_to_update(op.RXLowerThresholdCritical,
166- data.RxPowerLowAlarmMilliwatt, default)
167 op.Presence = update_presence(op.Presence, data.IsSffExist, default_num)259 op.Presence = update_presence(op.Presence, data.IsSffExist, default_num)
168 set_presence_to_device_obj(op, data.IsSffExist)260 set_presence_to_device_obj(op, data.IsSffExist)
169end261end
@@ -1078,6 +1078,7 @@ function c_network_adapter:update_port_link_status_by_pldm(port_id, ports)
1078 port:set_link_status(data.LinkStatus)1078 port:set_link_status(data.LinkStatus)
1079 port:set_link_status_numeric(data.LinkStatus)1079 port:set_link_status_numeric(data.LinkStatus)
1080 port.SpeedMbps = data.SpeedMbps1080 port.SpeedMbps = data.SpeedMbps
1081+ port.t_prop_without_bma.SpeedMbps = data.SpeedMbps
1081 port.SpeedGbps = data.SpeedGbps1082 port.SpeedGbps = data.SpeedGbps
1082 port.get_properties_res.LinkStatusFromPldm = true1083 port.get_properties_res.LinkStatusFromPldm = true
1083 end1084 end
@@ -1111,6 +1112,7 @@ function c_network_adapter:update_fw_version_by_pldm()
1111 return1112 return
1112 end1113 end
1113 self.FirmwareVersion = fw_version1114 self.FirmwareVersion = fw_version
1115+ self.t_prop_without_bma.FirmwareVersion = fw_version
1114 end)1116 end)
1115 table.insert(self.pldm_schedulers, s)1117 table.insert(self.pldm_schedulers, s)
1116 s:start()1118 s:start()
@@ -1455,6 +1457,7 @@ function c_network_adapter:update_1822_port_bdf(ports)
1455 self.NodeId, port.PortID, val)1457 self.NodeId, port.PortID, val)
1456 if port.WorkloadType ~= 1 then1458 if port.WorkloadType ~= 1 then
1457 port.BDF = val1459 port.BDF = val
1460+ port.t_prop_without_bma.BDF = val
1458 end1461 end
1459 count = count + 11462 count = count + 1
1460 end1463 end
@@ -1516,6 +1519,7 @@ function c_network_adapter:update_port_bdf(ports)
1516 if ret and ok and port.BDF == '' then1519 if ret and ok and port.BDF == '' then
1517 if port.WorkloadType ~= 1 then1520 if port.WorkloadType ~= 1 then
1518 port.BDF = val1521 port.BDF = val
1522+ port.t_prop_without_bma.BDF = val
1519 end1523 end
1520 count = count + 11524 count = count + 1
1521 end1525 end
@@ -1682,6 +1686,7 @@ function c_network_adapter:update_fw_ver_on_data_change(data, ports)
1682 self.update_fw_ver_abnormal = false1686 self.update_fw_ver_abnormal = false
1683 end1687 end
1684 self.FirmwareVersion = data1688 self.FirmwareVersion = data
1689+ self.t_prop_without_bma.FirmwareVersion = data
1685 for _, port in pairs(ports) do1690 for _, port in pairs(ports) do
1686 port:set_firmware_version(data)1691 port:set_firmware_version(data)
1687 end1692 end
@@ -1883,6 +1888,7 @@ function c_network_adapter:update_oem_smbus_info_power_off(ports)
1883 for _, port in pairs(ports) do1888 for _, port in pairs(ports) do
1884 for k, v in pairs(t_port_prop_default) do1889 for k, v in pairs(t_port_prop_default) do
1885 port:set_properties(k, v)1890 port:set_properties(k, v)
1891+ t.t_prop_without_bma[k] = v
1886 end1892 end
1887 port:set_op_temp(0xffff)1893 port:set_op_temp(0xffff)
1888 end1894 end
@@ -1982,6 +1988,7 @@ function c_network_adapter:update_oem_smbus_port_properties_power_on(ports, port
1982 port_properties = self:safe_get_oem_smbus_info(self.oem_smbus_config_obj, 'GetFirmwareVersion')1988 port_properties = self:safe_get_oem_smbus_info(self.oem_smbus_config_obj, 'GetFirmwareVersion')
1983 update_oem_smbus_info(port_properties, ports, 'FirmwareVersion', update_oem_smbus_firmware_version)1989 update_oem_smbus_info(port_properties, ports, 'FirmwareVersion', update_oem_smbus_firmware_version)
1984 self.FirmwareVersion = (ports and #ports ~= 0) and ports[1].FirmwareVersion or self.FirmwareVersion1990 self.FirmwareVersion = (ports and #ports ~= 0) and ports[1].FirmwareVersion or self.FirmwareVersion
1991+ self.t_prop_without_bma.FirmwareVersion = self.FirmwareVersion
1985 1992 
1986 -- 更新光模块在位1993 -- 更新光模块在位
1987 port_properties = self:safe_get_oem_smbus_info(self.oem_smbus_config_obj, 'GetOpticalPresence')1994 port_properties = self:safe_get_oem_smbus_info(self.oem_smbus_config_obj, 'GetOpticalPresence')
@@ -2035,6 +2042,7 @@ function c_network_adapter:update_oem_smbus_port_bdf(ports)
2035 if ret and ok then2042 if ret and ok then
2036 if port.WorkloadType ~= 1 then2043 if port.WorkloadType ~= 1 then
2037 port.BDF = val2044 port.BDF = val
2045+ port.t_prop_without_bma.BDF = val
2038 end2046 end
2039 count = count + 12047 count = count + 1
2040 end2048 end
@@ -2070,6 +2078,7 @@ function c_network_adapter:update_ncsi_firmware(ports)
2070 end2078 end
2071 2079 
2072 self.FirmwareVersion = firmware.FirmwareVersion2080 self.FirmwareVersion = firmware.FirmwareVersion
2081+ self.t_prop_without_bma.FirmwareVersion = firmware.FirmwareVersion
2073 2082 
2074 -- 仅在四元组无法从CSR获取时使用mctp上报的四元组信息2083 -- 仅在四元组无法从CSR获取时使用mctp上报的四元组信息
2075 if self.VendorID == '' then2084 if self.VendorID == '' then
@@ -2359,15 +2368,40 @@ function c_network_adapter:synchronize_port_node_id(_, value)
2359 end2368 end
2360end2369end
2361 2370 
2371+function c_network_adapter:restore_firmware_version_after_bma_stop()
2372+ if self.t_prop_without_bma.FirmwareVersion then
2373+ self.FirmwareVersion = self.t_prop_without_bma.FirmwareVersion
2374+ log:notice('%s restore firmware version to %s', self.NodeId, self.t_prop_without_bma.FirmwareVersion)
2375+ else
2376+ self.FirmwareVersion = ''
2377+ log:notice('%s restore firmware version to empty', self.NodeId)
2378+ end
2379+end
2380+ 
2362function c_network_adapter:reset_bma_info()2381function c_network_adapter:reset_bma_info()
2382+ log:notice('%s reset bma info', self.NodeId)
2363 self.DisplayName = ''2383 self.DisplayName = ''
2364 self.DriverName = ''2384 self.DriverName = ''
2365 self.DriverVersion = ''2385 self.DriverVersion = ''
2366- if not self.SupportedMctp or not next(self.ncsi_config_obj) or not self.ncsi_config_obj.VendorID then2386+ if self.CreatedByDeviceObject then
2367- -- 从t_adapter_prop_without_bma表中获取FirmwareVersion2387+ local bus = c_object_manage.get_instance().bus
2368- self.FirmwareVersion = self.t_adapter_prop_without_bma.FirmwareVersion2388+ local device_obj = comm_fun.get_device_obj_by_path_interface(bus, self.device_path,
2389+ comm_defs.NETWORK_ADAPTER_OEM_INTERFACE)
2390+ if not device_obj then
2391+ log:notice('%s reset_bma_info failed', self.NodeId)
2392+ return
2393+ end
2394+ local ok = pcall(function()
2395+ return device_obj:call_method('RestorePropAfterBmaStop', '')
2396+ end)
2397+ if not ok then
2398+ log:error('%s reset_bma_info failed', self.NodeId)
2399+ return
2400+ end
2401+ else
2402+ self:restore_firmware_version_after_bma_stop()
2369 end2403 end
2370- log:debug('NetworkAdapter(%s) reset from bma complete', self.NodeId)2404+ log:notice('%s reset_bma_info complete', self.NodeId)
2371end2405end
2372 2406 
2373local function is_virtual_port(type)2407local function is_virtual_port(type)
@@ -3417,8 +3451,8 @@ function c_network_adapter:ctor()
3417 self.parent = {}3451 self.parent = {}
3418 self.device_path = ''3452 self.device_path = ''
3419 self.get_properties_res = {}3453 self.get_properties_res = {}
3420- -- 此表用于临时保存非bma获取的属性,用于bma断开后恢复,当前仅FirmwareVersion使用3454+ -- 此表用于保存带外获取的属性,用于bma断开后恢复成带外获取的值
3421- self.t_adapter_prop_without_bma = {}3455+ self.t_prop_without_bma = {}
3422 3456 
3423 self.register_firmware_info_flag = false3457 self.register_firmware_info_flag = false
3424end3458end
@@ -3553,9 +3587,6 @@ function c_network_adapter:init_id()
3553 self.NodeId = string.gsub(self.Position, '%s+', '') ..3587 self.NodeId = string.gsub(self.Position, '%s+', '') ..
3554 string.gsub(self.DeviceLocator, '%s+', '')3588 string.gsub(self.DeviceLocator, '%s+', '')
3555 end3589 end
3556- self.t_adapter_prop_without_bma = {
3557- FirmwareVersion = ''
3558- }
3559 self:register_mdb_objects()3590 self:register_mdb_objects()
3560 self:properties_synchronizer()3591 self:properties_synchronizer()
3561end3592end
@@ -27,6 +27,8 @@ local c_optical_module = require 'device.class.optical_module'
27local log_netcard_info = require 'device.class.log_netcard_info'27local log_netcard_info = require 'device.class.log_netcard_info'
28local common_def = require 'common.common_def'28local common_def = require 'common.common_def'
29local common_func = require 'common.common_func'29local common_func = require 'common.common_func'
30+local device_comm_fun = require 'device.class.nic_mgmt.comm_fun'
31+local device_comm_defs = require 'device.class.nic_mgmt.comm_defs'
30 32 
31local str_hash = utils_core.str_hash33local str_hash = utils_core.str_hash
32local BUSINESSPORT_CARD_TYPE_VIR<const> = 634local BUSINESSPORT_CARD_TYPE_VIR<const> = 6
@@ -97,10 +99,51 @@ local default_lldp_receive_data<const> = {
97 ManagementVlanId = 099 ManagementVlanId = 0
98}100}
99 101 
100-function c_network_port:reset_port_prop_without_bma()102+function c_network_port:restore_port_prop_without_bma()
101- for k, v in pairs(self.t_port_prop_without_bma) do103+ self:restore_speed_mbps_after_bma_stop()
102- -- 当前表中仅有LinkStatus,后续拓展需判空104+ self:restore_auto_speed_negotiation_after_bma_stop()
103- self[k] = v105+ self:restore_full_duplex_after_bma_stop()
106+ self:restore_bdf_after_bma_stop()
107+ self:restore_firmware_version_after_bma_stop()
108+end
109+ 
110+function c_network_port:restore_speed_mbps_after_bma_stop()
111+ if self.t_prop_without_bma.SpeedMbps then
112+ self.SpeedMbps = self.t_prop_without_bma.SpeedMbps
113+ else
114+ self.SpeedMbps = 4294967295
115+ end
116+end
117+ 
118+function c_network_port:restore_auto_speed_negotiation_after_bma_stop()
119+ if self.t_prop_without_bma.AutoSpeedNegotiation then
120+ self.AutoSpeedNegotiation = self.t_prop_without_bma.AutoSpeedNegotiation
121+ else
122+ self.AutoSpeedNegotiation = 255
123+ end
124+end
125+ 
126+function c_network_port:restore_full_duplex_after_bma_stop()
127+ if self.t_prop_without_bma.FullDuplex then
128+ self.FullDuplex = self.t_prop_without_bma.FullDuplex
129+ else
130+ self.FullDuplex = 255
131+ end
132+end
133+ 
134+function c_network_port:restore_bdf_after_bma_stop()
135+ if self.t_prop_without_bma.BDF then
136+ self.BDF = self.t_prop_without_bma.BDF
137+ else
138+ self.BDF = ''
139+ end
140+end
141+ 
142+function c_network_port:restore_firmware_version_after_bma_stop()
143+ if self.t_prop_without_bma.FirmwareVersion then
144+ self.FirmwareVersion = self.t_prop_without_bma.FirmwareVersion
145+ else
146+ self.FirmwareVersion = ''
104 end147 end
105end148end
106 149 
@@ -203,14 +246,17 @@ end
203 246 
204function c_network_port:set_full_duplex(duplex_mode)247function c_network_port:set_full_duplex(duplex_mode)
205 self.FullDuplex = duplex_mode == nil and 255 or (duplex_mode and 1 or 0)248 self.FullDuplex = duplex_mode == nil and 255 or (duplex_mode and 1 or 0)
249+ self.t_prop_without_bma.FullDuplex = self.FullDuplex
206end250end
207 251 
208function c_network_port:set_auto_speednegotiation(negotiation_flag)252function c_network_port:set_auto_speednegotiation(negotiation_flag)
209 self.AutoSpeedNegotiation = negotiation_flag == nil and 255 or (negotiation_flag and 1 or 0)253 self.AutoSpeedNegotiation = negotiation_flag == nil and 255 or (negotiation_flag and 1 or 0)
254+ self.t_prop_without_bma.AutoSpeedNegotiation = self.AutoSpeedNegotiation
210end255end
211 256 
212function c_network_port:set_speed(speed)257function c_network_port:set_speed(speed)
213 self.SpeedMbps = speed258 self.SpeedMbps = speed
259+ self.t_prop_without_bma.SpeedMbps = speed
214end260end
215 261 
216function c_network_port:set_medium_type(medium_type)262function c_network_port:set_medium_type(medium_type)
@@ -219,6 +265,7 @@ end
219 265 
220function c_network_port:set_firmware_version(firmware_version)266function c_network_port:set_firmware_version(firmware_version)
221 self.FirmwareVersion = firmware_version267 self.FirmwareVersion = firmware_version
268+ self.t_prop_without_bma.FirmwareVersion = firmware_version
222end269end
223 270 
224function c_network_port:get_firmware_version()271function c_network_port:get_firmware_version()
@@ -262,7 +309,7 @@ function c_network_port:set_link_status(status)
262 if not self:is_linkstatus_from_bma(self.LinkStatus) then309 if not self:is_linkstatus_from_bma(self.LinkStatus) then
263 self.LinkStatus = status310 self.LinkStatus = status
264 end311 end
265- self.t_port_prop_without_bma.LinkStatus = status -- 用于重置bma时恢复为其他途径获取的状态312+ self.t_prop_without_bma.LinkStatus = status -- 用于重置bma时恢复为其他途径获取的状态
266end313end
267 314 
268function c_network_port:send_cmd(command_code, bin_data)315function c_network_port:send_cmd(command_code, bin_data)
@@ -311,8 +358,11 @@ function c_network_port:update_ncsi_link_status()
311 self:set_link_status(data.LinkStatus)358 self:set_link_status(data.LinkStatus)
312 self:set_link_status_numeric(data.LinkStatus)359 self:set_link_status_numeric(data.LinkStatus)
313 self.SpeedMbps = data.SpeedMbps360 self.SpeedMbps = data.SpeedMbps
361+ self.t_prop_without_bma.SpeedMbps = data.SpeedMbps
314 self.AutoSpeedNegotiation = data.AutoSpeedNegotiation362 self.AutoSpeedNegotiation = data.AutoSpeedNegotiation
363+ self.t_prop_without_bma.AutoSpeedNegotiation = data.AutoSpeedNegotiation
315 self.FullDuplex = data.FullDuplex364 self.FullDuplex = data.FullDuplex
365+ self.t_prop_without_bma.FullDuplex = data.FullDuplex
316 self.ncsi_get_linkstatus_retry_count = 0366 self.ncsi_get_linkstatus_retry_count = 0
317 ncsi_failed_count = 0 -- 成功时重置计数367 ncsi_failed_count = 0 -- 成功时重置计数
318 368 
@@ -343,8 +393,11 @@ function c_network_port:update_ncsi_link_status()
343 self:set_link_status(INVALID_DATA_STRING)393 self:set_link_status(INVALID_DATA_STRING)
344 self:set_link_status_numeric(INVALID_DATA_STRING)394 self:set_link_status_numeric(INVALID_DATA_STRING)
345 self.SpeedMbps = 0395 self.SpeedMbps = 0
396+ self.t_prop_without_bma.SpeedMbps = 0
346 self.AutoSpeedNegotiation = 255397 self.AutoSpeedNegotiation = 255
398+ self.t_prop_without_bma.AutoSpeedNegotiation = 255
347 self.FullDuplex = 255399 self.FullDuplex = 255
400+ self.t_prop_without_bma.FullDuplex = 255
348 self.ncsi_get_linkstatus_retry_count = 0401 self.ncsi_get_linkstatus_retry_count = 0
349 end402 end
350 end)403 end)
@@ -382,6 +435,7 @@ function c_network_port:update_BDF_by_ncsi()
382 }):value()435 }):value()
383 if s and (s.bus ~= 0 or s.device ~= 0 or s.func ~= 0) and self.WorkloadType ~= 1 then436 if s and (s.bus ~= 0 or s.device ~= 0 or s.func ~= 0) and self.WorkloadType ~= 1 then
384 self.BDF = string.format('%04x:%02x:%02x.%01x', 0, s.bus, s.device, s.func)437 self.BDF = string.format('%04x:%02x:%02x.%01x', 0, s.bus, s.device, s.func)
438+ self.t_prop_without_bma.BDF = self.BDF
385 log:notice('update_BDF_by_ncsi %s bdf:%s', self.NodeId, self.BDF)439 log:notice('update_BDF_by_ncsi %s bdf:%s', self.NodeId, self.BDF)
386 break440 break
387 end441 end
@@ -761,24 +815,19 @@ function c_network_port:update_ipv6_default_gateway(ipv6_addresses)
761end815end
762 816 
763function c_network_port:reset_bma_info()817function c_network_port:reset_bma_info()
764- self:reset_port_prop_without_bma()818+ log:notice('%sPort%s reset bma info', self.NetworkAdapterId, self.PortID)
765 self.OSLinkStatus = ''819 self.OSLinkStatus = ''
766 self.Name = ''820 self.Name = ''
767 self.WorkMode = 'NonLoop'821 self.WorkMode = 'NonLoop'
768 self.DriverName = ''822 self.DriverName = ''
769 self.DriverVersion = ''823 self.DriverVersion = ''
770- if not next(self.ncsi_config_obj) or not self.ncsi_config_obj.LinkStatus then824+ 
771- self.SpeedMbps = 0
772- self.AutoSpeedNegotiation = 255
773- end
774 if self.PermanentMACAddress and self.PermanentMACAddress ~= MAC_ADDR_DEFAULT and825 if self.PermanentMACAddress and self.PermanentMACAddress ~= MAC_ADDR_DEFAULT and
775 self.PermanentMACAddress ~= INVALID_DATA_STRING then826 self.PermanentMACAddress ~= INVALID_DATA_STRING then
776 log:notice('NetworkPort(%sPort%s) macaddr reset from permanent mac(%s) complete',827 log:notice('NetworkPort(%sPort%s) macaddr reset from permanent mac(%s) complete',
777 self.NetworkAdapterId, self.PortID, self.PermanentMACAddress)828 self.NetworkAdapterId, self.PortID, self.PermanentMACAddress)
778 self.MACAddress = self.PermanentMACAddress829 self.MACAddress = self.PermanentMACAddress
779 end830 end
780- log:debug('NetworkPort(%sPort%s) reset from bma complete', self.NetworkAdapterId, self.PortID)
781- 
782 -- FC卡相关属性831 -- FC卡相关属性
783 if self.FCId and #self.FCId > 0 then832 if self.FCId and #self.FCId > 0 then
784 self.WWPN = ''833 self.WWPN = ''
@@ -787,6 +836,26 @@ function c_network_port:reset_bma_info()
787 self.FCId = ''836 self.FCId = ''
788 self.FirmwareVersion = ''837 self.FirmwareVersion = ''
789 end838 end
839+ -- 恢复非bma途径获取的属性
840+ if self.CreatedByDeviceObject then
841+ local bus = c_object_manage.get_instance().bus
842+ local device_obj = device_comm_fun.get_device_obj_by_path_interface(bus, self.device_path,
843+ device_comm_defs.NETWORK_PORT_OEM_INTERFACE)
844+ if not device_obj then
845+ log:notice('%sPort%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
846+ return
847+ end
848+ local ok = pcall(function()
849+ return device_obj:call_method('RestorePropAfterBmaStop', '')
850+ end)
851+ if not ok then
852+ log:notice('%sPort%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
853+ return
854+ end
855+ else
856+ self:restore_firmware_version_after_bma_stop()
857+ end
858+ log:notice('%sPort%s reset bma info complete', self.NetworkAdapterId, self.PortID)
790end859end
791 860 
792function c_network_port:reset_bma_stats()861function c_network_port:reset_bma_stats()
@@ -966,7 +1035,7 @@ function c_network_port:ctor()
966 self.npu_ipv4_info = {}1035 self.npu_ipv4_info = {}
967 self.npu_ipv4_obj = false1036 self.npu_ipv4_obj = false
968 -- 此表用于临时保存非bma获取的属性,用于bma断开后恢复,当前仅LinkStatus使用1037 -- 此表用于临时保存非bma获取的属性,用于bma断开后恢复,当前仅LinkStatus使用
969- self.t_port_prop_without_bma = {}1038+ self.t_prop_without_bma = {}
970 self.ncsi_get_linkstatus_retry_count = 01039 self.ncsi_get_linkstatus_retry_count = 0
971 self.is_npu_heartbeat_loss = false1040 self.is_npu_heartbeat_loss = false
972 self.is_dmp_status_ready = false1041 self.is_dmp_status_ready = false
@@ -1060,7 +1129,7 @@ function c_network_port:init_id()
1060 end1129 end
1061 self.NetworkAdapterId = parent.NodeId1130 self.NetworkAdapterId = parent.NodeId
1062 self.NodeId = parent.NodeId .. (self.PortID + 1)1131 self.NodeId = parent.NodeId .. (self.PortID + 1)
1063- self.t_port_prop_without_bma = {1132+ self.t_prop_without_bma = {
1064 LinkStatus = INVALID_DATA_STRING1133 LinkStatus = INVALID_DATA_STRING
1065 }1134 }
1066 self:register_mdb_objects()1135 self:register_mdb_objects()
@@ -271,7 +271,6 @@ local function handle_special_property_mapping(interface, prop, orm_obj, value,
271 end271 end
272 if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE and prop == 'FirmwareVersion' then272 if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE and prop == 'FirmwareVersion' then
273 orm_obj['FirmwareVersion'] = value273 orm_obj['FirmwareVersion'] = value
274- orm_obj.t_adapter_prop_without_bma.FirmwareVersion = value
275 -- 网卡版本更新后,同步到该网卡的所有网口274 -- 网卡版本更新后,同步到该网卡的所有网口
276 local ports = orm_obj.children275 local ports = orm_obj.children
277 for _, port in pairs(ports) do276 for _, port in pairs(ports) do
@@ -579,6 +578,27 @@ function card_mgmt:register_children(port_orm_obj, card_orm_obj)
579 end578 end
580end579end
581 580 
581+function card_mgmt:update_firmware_version(card_orm_obj, firmware_version)
582+ if not card_orm_obj.CreatedByDeviceObject then
583+ return
584+ end
585+ log:notice('%s update_firmware_version start, value is %s', card_orm_obj.NodeId, firmware_version)
586+ local card_device_path = card_orm_obj.device_path
587+ if not card_device_path or card_device_path == '' then
588+ log:error('%s update_firmware_version failed, because port_device_path is nil or empty', card_orm_obj.NodeId)
589+ return
590+ end
591+ local card_device_obj = comm_fun.get_device_obj_by_path_interface(self.bus, card_device_path,
592+ comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE)
593+ if not card_device_obj then
594+ log:error('%s update_firmware_version failed, because card_device_obj is nil, card_device_path is %s',
595+ card_orm_obj.NodeId, card_device_path)
596+ return
597+ end
598+ card_device_obj.FirmwareVersion = firmware_version
599+ log:notice('%s update_firmware_version success, value is %s', card_orm_obj.NodeId, firmware_version)
600+end
601+ 
582function card_mgmt:get_orm_obj_by_device_path(card_device_path)602function card_mgmt:get_orm_obj_by_device_path(card_device_path)
583 local card_orm_obj = self.objects[card_device_path]603 local card_orm_obj = self.objects[card_device_path]
584 if not card_orm_obj then604 if not card_orm_obj then
@@ -42,6 +42,7 @@ comm_defs.NETWORK_PORT_LLDP_RECEIVE_INTERFACE = 'bmc.dev.NetworkPort.LLDPReceive
42comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE = 'bmc.dev.NetworkPort.LinkInfo'42comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE = 'bmc.dev.NetworkPort.LinkInfo'
43comm_defs.NETWORK_PORT_METRICS_INTERFACE = 'bmc.dev.NetworkPort.Metrics'43comm_defs.NETWORK_PORT_METRICS_INTERFACE = 'bmc.dev.NetworkPort.Metrics'
44comm_defs.NETWORK_PORT_FIBRE_CHANNEL_INTERFACE = 'bmc.dev.NetworkPort.FibreChannel'44comm_defs.NETWORK_PORT_FIBRE_CHANNEL_INTERFACE = 'bmc.dev.NetworkPort.FibreChannel'
45+comm_defs.NETWORK_PORT_OEM_INTERFACE = 'bmc.dev.NetworkPort.Oem'
45 46 
46-- 光模块相关设备树接口47-- 光模块相关设备树接口
47comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE = 'bmc.dev.OpticalModule'48comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE = 'bmc.dev.OpticalModule'
@@ -52,10 +53,12 @@ comm_defs.OPTICAL_MODULE_DIAGNOSE_INTERFACE = 'bmc.dev.OpticalModule.Diagnose'
52comm_defs.OPTICAL_MODULE_VOLTAGE_INTERFACE = 'bmc.dev.OpticalModule.Voltage'53comm_defs.OPTICAL_MODULE_VOLTAGE_INTERFACE = 'bmc.dev.OpticalModule.Voltage'
53comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE = 'bmc.dev.OpticalModule.Current'54comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE = 'bmc.dev.OpticalModule.Current'
54comm_defs.OPTICAL_MODULE_CHANNEL_INTERFACE = 'bmc.dev.OpticalModule.Channel'55comm_defs.OPTICAL_MODULE_CHANNEL_INTERFACE = 'bmc.dev.OpticalModule.Channel'
56+comm_defs.OPTICAL_MODULE_OEM_INTERFACE = 'bmc.dev.OpticalModule.Oem'
55 57 
56comm_defs.COMMON_PROPERTIES_INTERFACE = 'bmc.kepler.Object.Properties'58comm_defs.COMMON_PROPERTIES_INTERFACE = 'bmc.kepler.Object.Properties'
57comm_defs.ORG_PROPERTIES_INTERFACE = 'org.freedesktop.DBus.Properties'59comm_defs.ORG_PROPERTIES_INTERFACE = 'org.freedesktop.DBus.Properties'
58 60 
61+-- 新增「同步到设备树」的逻辑时,勿漏此项(键名与设备树接口 property 名一致)。
59comm_defs.INTERFACE_REGISTER_TABLE = {62comm_defs.INTERFACE_REGISTER_TABLE = {
60 [comm_defs.NETWORK_ADAPTER_OEM_INTERFACE] = {63 [comm_defs.NETWORK_ADAPTER_OEM_INTERFACE] = {
61 OSPowerState = {'y', nil, false, nil, false},64 OSPowerState = {'y', nil, false, nil, false},
@@ -68,17 +71,33 @@ comm_defs.INTERFACE_REGISTER_TABLE = {
68 [comm_defs.PCIE_DEVICE_INTERFACE] = {71 [comm_defs.PCIE_DEVICE_INTERFACE] = {
69 DeviceName = {'s', nil, true, nil, false}72 DeviceName = {'s', nil, true, nil, false}
70 },73 },
74+ [comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE] = {
75+ FirmwareVersion = {'s', nil, false, nil, false}
76+ },
77+ [comm_defs.NETWORK_PORT_DEVICE_INTERFACE] = {
78+ BDF = {'s', nil, false, nil, false}
79+ },
71 [comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE] = {80 [comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE] = {
72- LinkStatus = {'y', nil, false, nil, false}81+ LinkStatus = {'y', nil, false, nil, false},
82+ SpeedMbps = {'u', nil, false, nil, false},
83+ FullDuplex = {'y', nil, false, nil, false},
84+ AutoSpeedNegotiationEnabled = {'y', nil, false, nil, false}
73 },85 },
74 [comm_defs.NETWORK_PORT_METRICS_INTERFACE] = {86 [comm_defs.NETWORK_PORT_METRICS_INTERFACE] = {
75 BandwidthPercent = {'d', nil, false, nil, false}87 BandwidthPercent = {'d', nil, false, nil, false}
76 },88 },
77 [comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE] = {89 [comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE] = {
78- Presence = {'y', nil, false, nil, false}90+ Presence = {'y', nil, false, nil, false},
91+ Manufacturer = {'s', nil, false, nil, false},
92+ PartNumber = {'s', nil, false, nil, false},
93+ SerialNumber = {'s', nil, false, nil, false},
94+ ProductionDate = {'s', nil, false, nil, false},
95+ WaveLengthNanometer = {'s', nil, false, nil, false}
79 },96 },
80 [comm_defs.OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE] = {97 [comm_defs.OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE] = {
81- TemperatureCelsius = {'d', nil, false, nil, false}98+ TemperatureCelsius = {'d', nil, false, nil, false},
99+ TemperatureUpperThresholdCritical = {'d', nil, false, nil, false},
100+ TemperatureLowerThresholdCritical = {'d', nil, false, nil, false}
82 },101 },
83 [comm_defs.OPTICAL_MODULE_STATUS_INTERFACE] = {102 [comm_defs.OPTICAL_MODULE_STATUS_INTERFACE] = {
84 TypeMatch = {'b', nil, false, nil, false},103 TypeMatch = {'b', nil, false, nil, false},
@@ -91,7 +110,16 @@ comm_defs.INTERFACE_REGISTER_TABLE = {
91 VoltageLowerThresholdCritical = {'d', nil, false, nil, false},110 VoltageLowerThresholdCritical = {'d', nil, false, nil, false},
92 VoltageUpperThresholdCritical = {'d', nil, false, nil, false}111 VoltageUpperThresholdCritical = {'d', nil, false, nil, false}
93 },112 },
113+ [comm_defs.OPTICAL_MODULE_POWER_INTERFACE] = {
114+ RXInputPowerMilliWatts = {'ad', nil, false, nil, false},
115+ TXOutputPowerMilliWatts = {'ad', nil, false, nil, false},
116+ RXPowerUpperThresholdCritical = {'d', nil, false, nil, false},
117+ RXPowerLowerThresholdCritical = {'d', nil, false, nil, false},
118+ TXPowerUpperThresholdCritical = {'d', nil, false, nil, false},
119+ TXPowerLowerThresholdCritical = {'d', nil, false, nil, false}
120+ },
94 [comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE] = {121 [comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE] = {
122+ TXBiasCurrentMilliAmps = {'ad', nil, false, nil, false},
95 TXBiasCurrentLowerThresholdCritical = {'d', nil, false, nil, false},123 TXBiasCurrentLowerThresholdCritical = {'d', nil, false, nil, false},
96 TXBiasCurrentUpperThresholdCritical = {'d', nil, false, nil, false}124 TXBiasCurrentUpperThresholdCritical = {'d', nil, false, nil, false}
97 },125 },
@@ -47,13 +47,10 @@ local prop_table = {
47 HostSNR = 'HostSNR',47 HostSNR = 'HostSNR',
48 MediaSNR = 'MediaSNR',48 MediaSNR = 'MediaSNR',
49 Accessible = 'Accessible',49 Accessible = 'Accessible',
50- RXInputPowerMilliWatts = 'RXInputPowerMilliWatts',
51 RXPowerUpperThresholdCritical = 'RXUpperThresholdCritical',50 RXPowerUpperThresholdCritical = 'RXUpperThresholdCritical',
52 RXPowerLowerThresholdCritical = 'RXLowerThresholdCritical',51 RXPowerLowerThresholdCritical = 'RXLowerThresholdCritical',
53- TXOutputPowerMilliWatts = 'TXOutputPowerMilliWatts',
54 TXPowerUpperThresholdCritical = 'Power_TXUpperThresholdCritical',52 TXPowerUpperThresholdCritical = 'Power_TXUpperThresholdCritical',
55 TXPowerLowerThresholdCritical = 'Power_TXLowerThresholdCritical',53 TXPowerLowerThresholdCritical = 'Power_TXLowerThresholdCritical',
56- TXBiasCurrentMilliAmps = 'TXBiasCurrentMilliAmps',
57 TXBiasCurrentUpperThresholdCritical = 'BC_TXUpperThresholdCritical',54 TXBiasCurrentUpperThresholdCritical = 'BC_TXUpperThresholdCritical',
58 TXBiasCurrentLowerThresholdCritical = 'BC_TXLowerThresholdCritical',55 TXBiasCurrentLowerThresholdCritical = 'BC_TXLowerThresholdCritical',
59 TemperatureCelsius = 'ReadingCelsius',56 TemperatureCelsius = 'ReadingCelsius',
@@ -88,10 +85,29 @@ local function handle_special_property_mapping(interface, prop, orm_obj, value)
88 if prop == 'TransmissionDistance' and interface == comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE then85 if prop == 'TransmissionDistance' and interface == comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE then
89 orm_obj['TransmissionDistance'] = tostring(value)86 orm_obj['TransmissionDistance'] = tostring(value)
90 end87 end
88+ -- TXBiasCurrentMilliAmps/RXInputPowerMilliWatts/TXOutputPowerMilliWatts 从BMA获取到多通道数据时,优先以BMA为准
89+ if prop == 'TXBiasCurrentMilliAmps' and interface == comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE then
90+ if (orm_obj.TXBiasCurrentMilliAmps and #orm_obj.TXBiasCurrentMilliAmps <= 1) or
91+ not orm_obj.get_diagnostic_by_ibma_success then
92+ orm_obj.TXBiasCurrentMilliAmps = value
93+ end
94+ end
95+ if prop == 'RXInputPowerMilliWatts' and interface == comm_defs.OPTICAL_MODULE_POWER_INTERFACE then
96+ if (orm_obj.RXInputPowerMilliWatts and #orm_obj.RXInputPowerMilliWatts <= 1) or
97+ not orm_obj.get_diagnostic_by_ibma_success then
98+ orm_obj.RXInputPowerMilliWatts = value
99+ end
100+ end
101+ if prop == 'TXOutputPowerMilliWatts' and interface == comm_defs.OPTICAL_MODULE_POWER_INTERFACE then
102+ if (orm_obj.TXOutputPowerMilliWatts and #orm_obj.TXOutputPowerMilliWatts <= 1) or
103+ not orm_obj.get_diagnostic_by_ibma_success then
104+ orm_obj.TXOutputPowerMilliWatts = value
105+ end
106+ end
91end107end
92 108 
93local function listen_device_obj_property_change(bus, sig_slot, device_path, orm_obj)109local function listen_device_obj_property_change(bus, sig_slot, device_path, orm_obj)
94- log:notice('listen_device_obj_property_change start, optical_device_path is %s', device_path)110+ log:notice('listen_device_obj_property_change start, optical_device_path is %s', device_path)
95 local property_changed_sig = match_rule.signal(property_changed.name, property_changed.interface):with_path(111 local property_changed_sig = match_rule.signal(property_changed.name, property_changed.interface):with_path(
96 device_path)112 device_path)
97 sig_slot[#sig_slot + 1] = bus:match(property_changed_sig, function(msg)113 sig_slot[#sig_slot + 1] = bus:match(property_changed_sig, function(msg)
@@ -214,6 +230,32 @@ function optical_module_mgmt:set_presence_to_device_obj(optical_orm_obj, value)
214 comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')230 comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
215end231end
216 232 
233+-- BMA 更新资源树后,同步厂商/部件号/序列号/生产日期/波长到设备树 bmc.dev.OpticalModule
234+function optical_module_mgmt:update_manufacturer_to_device_obj(optical_orm_obj, value)
235+ self:set_property_to_device_obj(optical_orm_obj, 'Manufacturer',
236+ comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
237+end
238+ 
239+function optical_module_mgmt:update_part_number_to_device_obj(optical_orm_obj, value)
240+ self:set_property_to_device_obj(optical_orm_obj, 'PartNumber',
241+ comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
242+end
243+ 
244+function optical_module_mgmt:update_serial_number_to_device_obj(optical_orm_obj, value)
245+ self:set_property_to_device_obj(optical_orm_obj, 'SerialNumber',
246+ comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
247+end
248+ 
249+function optical_module_mgmt:update_production_date_to_device_obj(optical_orm_obj, value)
250+ self:set_property_to_device_obj(optical_orm_obj, 'ProductionDate',
251+ comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
252+end
253+ 
254+function optical_module_mgmt:update_wave_length_nanometer_to_device_obj(optical_orm_obj, value)
255+ self:set_property_to_device_obj(optical_orm_obj, 'WaveLengthNanometer',
256+ comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE, value, 'notice')
257+end
258+ 
217-- 速率匹配更新后,同步更新到设备树对象(用于iBMA获取到速率匹配的场景)259-- 速率匹配更新后,同步更新到设备树对象(用于iBMA获取到速率匹配的场景)
218function optical_module_mgmt:set_speed_match_to_device_obj(optical_orm_obj, value)260function optical_module_mgmt:set_speed_match_to_device_obj(optical_orm_obj, value)
219 self:set_property_to_device_obj(optical_orm_obj, 'SpeedMatch',261 self:set_property_to_device_obj(optical_orm_obj, 'SpeedMatch',
@@ -268,6 +310,51 @@ function optical_module_mgmt:set_bias_current_lower_threshold_critical_to_device
268 comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE, value, 'notice')310 comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE, value, 'notice')
269end311end
270 312 
313+function optical_module_mgmt:set_temperature_upper_threshold_critical_to_device_obj(optical_orm_obj, value)
314+ self:set_property_to_device_obj(optical_orm_obj, 'TemperatureUpperThresholdCritical',
315+ comm_defs.OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE, value, 'notice')
316+end
317+ 
318+function optical_module_mgmt:set_temperature_lower_threshold_critical_to_device_obj(optical_orm_obj, value)
319+ self:set_property_to_device_obj(optical_orm_obj, 'TemperatureLowerThresholdCritical',
320+ comm_defs.OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE, value, 'notice')
321+end
322+ 
323+function optical_module_mgmt:set_tx_bias_current_milli_amps_to_device_obj(optical_orm_obj, value)
324+ self:set_property_to_device_obj(optical_orm_obj, 'TXBiasCurrentMilliAmps',
325+ comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE, value, 'info')
326+end
327+ 
328+function optical_module_mgmt:set_tx_output_power_milli_watts_to_device_obj(optical_orm_obj, value)
329+ self:set_property_to_device_obj(optical_orm_obj, 'TXOutputPowerMilliWatts',
330+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'info')
331+end
332+ 
333+function optical_module_mgmt:set_rx_input_power_milli_watts_to_device_obj(optical_orm_obj, value)
334+ self:set_property_to_device_obj(optical_orm_obj, 'RXInputPowerMilliWatts',
335+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'info')
336+end
337+ 
338+function optical_module_mgmt:set_rx_power_upper_threshold_critical_to_device_obj(optical_orm_obj, value)
339+ self:set_property_to_device_obj(optical_orm_obj, 'RXPowerUpperThresholdCritical',
340+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'notice')
341+end
342+ 
343+function optical_module_mgmt:set_rx_power_lower_threshold_critical_to_device_obj(optical_orm_obj, value)
344+ self:set_property_to_device_obj(optical_orm_obj, 'RXPowerLowerThresholdCritical',
345+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'notice')
346+end
347+ 
348+function optical_module_mgmt:set_tx_power_upper_threshold_critical_to_device_obj(optical_orm_obj, value)
349+ self:set_property_to_device_obj(optical_orm_obj, 'TXPowerUpperThresholdCritical',
350+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'notice')
351+end
352+ 
353+function optical_module_mgmt:set_tx_power_lower_threshold_critical_to_device_obj(optical_orm_obj, value)
354+ self:set_property_to_device_obj(optical_orm_obj, 'TXPowerLowerThresholdCritical',
355+ comm_defs.OPTICAL_MODULE_POWER_INTERFACE, value, 'notice')
356+end
357+ 
271function optical_module_mgmt:on_add_optical_device_obj()358function optical_module_mgmt:on_add_optical_device_obj()
272 log:notice('on_add_optical_device_obj start')359 log:notice('on_add_optical_device_obj start')
273 local self_instance = self360 local self_instance = self
@@ -39,7 +39,7 @@ function port_init.init(orm_obj, bus)
39 if parent and string.find(parent.NodeId, 'ROH') then39 if parent and string.find(parent.NodeId, 'ROH') then
40 return40 return
41 end41 end
42- orm_obj.t_port_prop_without_bma = {42+ orm_obj.t_prop_without_bma = {
43 LinkStatus = port_defs.INVALID_DATA_STRING43 LinkStatus = port_defs.INVALID_DATA_STRING
44 }44 }
45 if parent and parent.Model == port_defs.NPU_MODEL then45 if parent and parent.Model == port_defs.NPU_MODEL then
@@ -114,7 +114,7 @@ local function handle_special_property_mapping(interface, prop, orm_obj, value)
114 local link_status = link_status_table[value] or 'N/A'114 local link_status = link_status_table[value] or 'N/A'
115 orm_obj:set_link_status(link_status)115 orm_obj:set_link_status(link_status)
116 orm_obj:set_link_status_numeric(link_status)116 orm_obj:set_link_status_numeric(link_status)
117- orm_obj.t_port_prop_without_bma.LinkStatus = link_status117+ orm_obj.t_prop_without_bma.LinkStatus = link_status
118 end118 end
119end119end
120 120 
@@ -249,21 +249,24 @@ function port_mgmt:set_link_status_to_device_obj(port_orm_obj, value)
249 if not port_orm_obj.CreatedByDeviceObject then249 if not port_orm_obj.CreatedByDeviceObject then
250 return250 return
251 end251 end
252- log:notice('%s set_link_status_to_device_obj start, value is %s', port_orm_obj.NodeId, value)252+ log:notice('%sPort%s set_link_status_to_device_obj start, value is %s',
253+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
253 local port_device_path = port_orm_obj.device_path254 local port_device_path = port_orm_obj.device_path
254 if not port_device_path or port_device_path == '' then255 if not port_device_path or port_device_path == '' then
255- log:error('%s set_link_status_to_dev_obj failed, because port_device_path is nil or empty', port_orm_obj.NodeId)256+ log:error('%sPort%s set_link_status_to_dev_obj failed, because port_device_path is nil or empty',
257+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
256 return258 return
257 end259 end
258 local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,260 local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
259 comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE)261 comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE)
260 if not devcie_obj then262 if not devcie_obj then
261- log:error('%s set_link_status_to_dev_obj failed, because devcie_obj is nil, port_device_path is %s',263+ log:error('%sPort%s set_link_status_to_dev_obj failed, because devcie_obj is nil, port_device_path is %s',
262- port_orm_obj.NodeId, port_device_path)264+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
263 return265 return
264 end266 end
265 devcie_obj.LinkStatus = value267 devcie_obj.LinkStatus = value
266- log:notice('%s set_link_status_to_device_obj success, value is %s', port_orm_obj.NodeId, value)268+ log:notice('%sPort%s set_link_status_to_device_obj success, value is %s',
269+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
267end270end
268 271 
269-- 带宽利用率更新后,同步更新到设备树对象(用于iBMA获取到带宽利用率的场景)272-- 带宽利用率更新后,同步更新到设备树对象(用于iBMA获取到带宽利用率的场景)
@@ -271,21 +274,128 @@ function port_mgmt:set_bandwidth_usage_to_device_obj(port_orm_obj, value)
271 if not port_orm_obj.CreatedByDeviceObject then274 if not port_orm_obj.CreatedByDeviceObject then
272 return275 return
273 end276 end
274- log:notice('%s set_bandwidth_usage_to_device_obj start, value is %s', port_orm_obj.NodeId, value)277+ log:notice('%sPort%s set_bandwidth_usage_to_device_obj start, value is %s',
278+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
275 local port_device_path = port_orm_obj.device_path279 local port_device_path = port_orm_obj.device_path
276 if not port_device_path or port_device_path == '' then280 if not port_device_path or port_device_path == '' then
277- log:error('%s set_bandwidth_usage_to_dev_obj failed, because port_device_path is nil or empty', port_orm_obj.NodeId)281+ log:error('%sPort%s set_bandwidth_usage_to_dev_obj failed, because port_device_path is nil or empty',
282+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
278 return283 return
279 end284 end
280 local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,285 local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
281 comm_defs.NETWORK_PORT_METRICS_INTERFACE)286 comm_defs.NETWORK_PORT_METRICS_INTERFACE)
282 if not devcie_obj then287 if not devcie_obj then
283- log:error('%s set_bandwidth_usage_to_dev_obj failed, because devcie_obj is nil, port_device_path is %s',288+ log:error('%sPort%s set_bandwidth_usage_to_dev_obj failed, because devcie_obj is nil, port_device_path is %s',
284- port_orm_obj.NodeId, port_device_path)289+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
285 return290 return
286 end291 end
287 devcie_obj.BandwidthPercent = value292 devcie_obj.BandwidthPercent = value
288- log:notice('%s set_bandwidth_usage_to_dev_obj success, value is %s', port_orm_obj.NodeId, value)293+ log:notice('%sPort%s set_bandwidth_usage_to_dev_obj success, value is %s',
294+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
295+end
296+ 
297+-- BMA 更新资源树后,同步全双工到设备树 LinkInfo(供带外与 iBMA 一致)
298+function port_mgmt:update_full_duplex_to_device_obj(port_orm_obj, value)
299+ if not port_orm_obj.CreatedByDeviceObject then
300+ return
301+ end
302+ log:notice('%sPort%s update_full_duplex_to_device_obj start, value is %s',
303+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
304+ local port_device_path = port_orm_obj.device_path
305+ if not port_device_path or port_device_path == '' then
306+ log:error('%sPort%s update_full_duplex_to_device_obj failed, because port_device_path is nil or empty',
307+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
308+ return
309+ end
310+ local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
311+ comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE)
312+ if not devcie_obj then
313+ log:error('%sPort%s update_full_duplex_to_device_obj failed, because devcie_obj is nil, port_device_path is %s',
314+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
315+ return
316+ end
317+ devcie_obj.FullDuplex = value
318+ log:notice('%sPort%s update_full_duplex_to_device_obj success, value is %s',
319+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
320+end
321+ 
322+-- BMA 更新资源树后,同步速率到设备树 LinkInfo
323+function port_mgmt:update_speed_mbps_to_device_obj(port_orm_obj, value)
324+ if not port_orm_obj.CreatedByDeviceObject then
325+ return
326+ end
327+ log:notice('%sPort%s update_speed_mbps_to_device_obj start, value is %s',
328+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
329+ local port_device_path = port_orm_obj.device_path
330+ if not port_device_path or port_device_path == '' then
331+ log:error('%sPort%s update_speed_mbps_to_device_obj failed, because port_device_path is nil or empty',
332+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
333+ return
334+ end
335+ local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
336+ comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE)
337+ if not devcie_obj then
338+ log:error('%sPort%s update_speed_mbps_to_device_obj failed, because devcie_obj is nil, port_device_path is %s',
339+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
340+ return
341+ end
342+ devcie_obj.SpeedMbps = value
343+ log:notice('%sPort%s update_speed_mbps_to_device_obj success, value is %s',
344+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
345+end
346+ 
347+-- BMA 更新资源树后,同步自协商到设备树 LinkInfo(设备侧属性名为 AutoSpeedNegotiationEnabled)
348+function port_mgmt:update_auto_negotiation_to_device_obj(port_orm_obj, value)
349+ if not port_orm_obj.CreatedByDeviceObject then
350+ return
351+ end
352+ log:notice('%sPort%s update_auto_negotiation_to_device_obj start, value is %s',
353+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
354+ local port_device_path = port_orm_obj.device_path
355+ if not port_device_path or port_device_path == '' then
356+ log:error('%sPort%s update_auto_negotiation_to_device_obj failed, because port_device_path is nil or empty',
357+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
358+ return
359+ end
360+ local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
361+ comm_defs.NETWORK_PORT_LINK_INFO_INTERFACE)
362+ if not devcie_obj then
363+ log:error(
364+ '%sPort%s update_auto_negotiation_to_device_obj failed, because devcie_obj is nil, port_device_path is %s',
365+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
366+ return
367+ end
368+ devcie_obj.AutoSpeedNegotiationEnabled = value
369+ log:notice('%sPort%s update_auto_negotiation_to_device_obj success, value is %s',
370+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
371+end
372+ 
373+-- BMA 更新资源树后,同步 BDF 到设备树 NetworkPort 主接口
374+function port_mgmt:update_bdf_to_device_obj(port_orm_obj, value)
375+ if not port_orm_obj.CreatedByDeviceObject then
376+ return
377+ end
378+ if value == nil then
379+ return
380+ end
381+ log:notice('%sPort%s update_bdf_to_device_obj start, value is %s',
382+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
383+ local port_device_path = port_orm_obj.device_path
384+ if not port_device_path or port_device_path == '' then
385+ log:error('%sPort%s update_bdf_to_device_obj failed, because port_device_path is nil or empty',
386+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID)
387+ return
388+ end
389+ local devcie_obj = comm_fun.get_device_obj_by_path_interface(self.bus, port_device_path,
390+ comm_defs.NETWORK_PORT_DEVICE_INTERFACE)
391+ if not devcie_obj then
392+ log:error('%sPort%s update_bdf_to_device_obj failed, because devcie_obj is nil, port_device_path is %s',
393+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, port_device_path)
394+ return
395+ end
396+ devcie_obj.BDF = value
397+ log:notice('%sPort%s update_bdf_to_device_obj success, value is %s',
398+ port_orm_obj.NetworkAdapterId, port_orm_obj.PortID, value)
289end399end
290 400 
291function port_mgmt:on_add_port_device_obj()401function port_mgmt:on_add_port_device_obj()
@@ -31,6 +31,8 @@ local prbs = require 'prbs_test.optical_module_prbs_test'
31local dirty = require 'dirty_test.optical_module_dirty_test'31local dirty = require 'dirty_test.optical_module_dirty_test'
32local client = require 'network_adapter.client'32local client = require 'network_adapter.client'
33local common_func = require 'common.common_func'33local common_func = require 'common.common_func'
34+local device_comm_fun = require 'device.class.nic_mgmt.comm_fun'
35+local device_comm_defs = require 'device.class.nic_mgmt.comm_defs'
34 36 
35local channel_type = enums.ChannelType37local channel_type = enums.ChannelType
36local comp_code = ipmi.types.Cc38local comp_code = ipmi.types.Cc
@@ -138,6 +140,7 @@ end
138 140 
139function c_optical_module:set_presence(presence)141function c_optical_module:set_presence(presence)
140 self.Presence = presence142 self.Presence = presence
143+ self.t_prop_without_bma.Presence = presence
141end144end
142 145 
143function c_optical_module:get_channel_num()146function c_optical_module:get_channel_num()
@@ -276,6 +279,7 @@ function c_optical_module:update_optical_temp_by_ncsi()
276 if data ~= nil then279 if data ~= nil then
277 self.ReadingCelsius = data280 self.ReadingCelsius = data
278 self.Presence = 1281 self.Presence = 1
282+ self.t_prop_without_bma.Presence = 1
279 self.presence_retry_count = 0283 self.presence_retry_count = 0
280 self.get_properties_res.TempFromNcsi = true284 self.get_properties_res.TempFromNcsi = true
281 end285 end
@@ -388,6 +392,7 @@ function c_optical_module:update_optical_bias_by_ncsi(id)
388 end392 end
389 -- 修改后需要显式地设置属性值,修改才会生效393 -- 修改后需要显式地设置属性值,修改才会生效
390 self.TXBiasCurrentMilliAmps = prop_value394 self.TXBiasCurrentMilliAmps = prop_value
395+ self.t_prop_without_bma.TXBiasCurrentMilliAmps = prop_value
391 self.get_properties_res.BiasFromNcsi = true396 self.get_properties_res.BiasFromNcsi = true
392 end)397 end)
393 self:connect_signal(s.on_error, function()398 self:connect_signal(s.on_error, function()
@@ -397,6 +402,7 @@ function c_optical_module:update_optical_bias_by_ncsi(id)
397 end402 end
398 s.data = nil -- 重置scheduler里的data,否则连接恢复后不会进入on_data_change403 s.data = nil -- 重置scheduler里的data,否则连接恢复后不会进入on_data_change
399 self.TXBiasCurrentMilliAmps = {0xFFFF}404 self.TXBiasCurrentMilliAmps = {0xFFFF}
405+ self.t_prop_without_bma.TXBiasCurrentMilliAmps = {0xFFFF}
400 end)406 end)
401 table.insert(self.schedulers, s)407 table.insert(self.schedulers, s)
402 s.data = nil408 s.data = nil
@@ -489,6 +495,7 @@ function c_optical_module:update_optical_module_static_info_by_ncsi(id)
489 self:connect_signal(s.on_data_change, function(data)495 self:connect_signal(s.on_data_change, function(data)
490 for k, v in pairs(data) do496 for k, v in pairs(data) do
491 self:set_prop(k, v)497 self:set_prop(k, v)
498+ self.t_prop_without_bma[k] = v
492 log:notice('%s optical_module_%s update %s to %s by ncsi', self.NetworkAdapterId, self.PortID, k, v)499 log:notice('%s optical_module_%s update %s to %s by ncsi', self.NetworkAdapterId, self.PortID, k, v)
493 end500 end
494 self.get_properties_res.StaticInfoFromNcsi = true501 self.get_properties_res.StaticInfoFromNcsi = true
@@ -604,9 +611,101 @@ function c_optical_module:is_prop_from_bma(key)
604 return false611 return false
605end612end
606 613 
607-function c_optical_module:reset_prop_without_bma()614+function c_optical_module:restore_optical_dynamic_prop_after_bma_stop()
608- for key, value in pairs(self.t_prop_without_bma) do615+ self:restore_temperature_celsius_after_bma_stop()
609- self[key] = value616+ self:restore_voltage_after_bma_stop()
617+ self:restore_bias_current_after_bma_stop()
618+ self:restore_tx_output_power_after_bma_stop()
619+ self:restore_rx_input_power_after_bma_stop()
620+end
621+ 
622+function c_optical_module:restore_temperature_celsius_after_bma_stop()
623+ if self.t_prop_without_bma.ReadingCelsius then
624+ self.ReadingCelsius = self.t_prop_without_bma.ReadingCelsius
625+ else
626+ self.ReadingCelsius = 0xFFFF
627+ end
628+ if self.t_prop_without_bma.TemperatureUpperThresholdCritical then
629+ self.TemperatureUpperThresholdCritical = self.t_prop_without_bma.TemperatureUpperThresholdCritical
630+ else
631+ self.TemperatureUpperThresholdCritical = 0xFFFF
632+ end
633+ if self.t_prop_without_bma.TemperatureLowerThresholdCritical then
634+ self.TemperatureLowerThresholdCritical = self.t_prop_without_bma.TemperatureLowerThresholdCritical
635+ else
636+ self.TemperatureLowerThresholdCritical = 0xFFFF
637+ end
638+end
639+ 
640+function c_optical_module:restore_voltage_after_bma_stop()
641+ if self.t_prop_without_bma.SupplyVoltage then
642+ self.SupplyVoltage = self.t_prop_without_bma.SupplyVoltage
643+ else
644+ self.SupplyVoltage = 0xFFFF
645+ end
646+ if self.t_prop_without_bma.VoltageUpperThresholdCritical then
647+ self.VoltageUpperThresholdCritical = self.t_prop_without_bma.VoltageUpperThresholdCritical
648+ else
649+ self.VoltageUpperThresholdCritical = 0xFFFF
650+ end
651+ if self.t_prop_without_bma.VoltageLowerThresholdCritical then
652+ self.VoltageLowerThresholdCritical = self.t_prop_without_bma.VoltageLowerThresholdCritical
653+ else
654+ self.VoltageLowerThresholdCritical = 0xFFFF
655+ end
656+end
657+ 
658+function c_optical_module:restore_bias_current_after_bma_stop()
659+ if self.t_prop_without_bma.TXBiasCurrentMilliAmps then
660+ self.TXBiasCurrentMilliAmps = self.t_prop_without_bma.TXBiasCurrentMilliAmps
661+ else
662+ self.TXBiasCurrentMilliAmps = {0xFFFF}
663+ end
664+ if self.t_prop_without_bma.BC_TXUpperThresholdCritical then
665+ self.BC_TXUpperThresholdCritical = self.t_prop_without_bma.BC_TXUpperThresholdCritical
666+ else
667+ self.BC_TXUpperThresholdCritical = 0xFFFF
668+ end
669+ if self.t_prop_without_bma.BC_TXLowerThresholdCritical then
670+ self.BC_TXLowerThresholdCritical = self.t_prop_without_bma.BC_TXLowerThresholdCritical
671+ else
672+ self.BC_TXLowerThresholdCritical = 0xFFFF
673+ end
674+end
675+ 
676+function c_optical_module:restore_tx_output_power_after_bma_stop()
677+ if self.t_prop_without_bma.TXOutputPowerMilliWatts then
678+ self.TXOutputPowerMilliWatts = self.t_prop_without_bma.TXOutputPowerMilliWatts
679+ else
680+ self.TXOutputPowerMilliWatts = {0xFFFF}
681+ end
682+ if self.t_prop_without_bma.Power_TXUpperThresholdCritical then
683+ self.Power_TXUpperThresholdCritical = self.t_prop_without_bma.Power_TXUpperThresholdCritical
684+ else
685+ self.Power_TXUpperThresholdCritical = 0xFFFF
686+ end
687+ if self.t_prop_without_bma.Power_TXLowerThresholdCritical then
688+ self.Power_TXLowerThresholdCritical = self.t_prop_without_bma.Power_TXLowerThresholdCritical
689+ else
690+ self.Power_TXLowerThresholdCritical = 0xFFFF
691+ end
692+end
693+ 
694+function c_optical_module:restore_rx_input_power_after_bma_stop()
695+ if self.t_prop_without_bma.RXInputPowerMilliWatts then
696+ self.RXInputPowerMilliWatts = self.t_prop_without_bma.RXInputPowerMilliWatts
697+ else
698+ self.RXInputPowerMilliWatts = {0xFFFF}
699+ end
700+ if self.t_prop_without_bma.RXUpperThresholdCritical then
701+ self.RXUpperThresholdCritical = self.t_prop_without_bma.RXUpperThresholdCritical
702+ else
703+ self.RXUpperThresholdCritical = 0xFFFF
704+ end
705+ if self.t_prop_without_bma.RXLowerThresholdCritical then
706+ self.RXLowerThresholdCritical = self.t_prop_without_bma.RXLowerThresholdCritical
707+ else
708+ self.RXLowerThresholdCritical = 0xFFFF
610 end709 end
611end710end
612 711 
@@ -619,6 +718,7 @@ local prop_name_with_bma = {
619function c_optical_module:set_prop(key, value)718function c_optical_module:set_prop(key, value)
620 if not prop_name_with_bma[key] then719 if not prop_name_with_bma[key] then
621 self[key] = value720 self[key] = value
721+ self.t_prop_without_bma[key] = value
622 return722 return
623 end723 end
624 -- prop_name_with_bma表中的属性更新前先判断当前数据是否为bma获取的,优先以bma获取的值为准724 -- prop_name_with_bma表中的属性更新前先判断当前数据是否为bma获取的,优先以bma获取的值为准
@@ -646,6 +746,7 @@ function c_optical_module:update_NSCI_optical_module_info()
646 end746 end
647 self.get_properties_res.ModuleInfoFromNcsi = true747 self.get_properties_res.ModuleInfoFromNcsi = true
648 self.Presence = 1748 self.Presence = 1
749+ self.t_prop_without_bma.Presence = 1
649 self.presence_retry_count = 0750 self.presence_retry_count = 0
650 self:update_asset_data_info()751 self:update_asset_data_info()
651 end)752 end)
@@ -730,6 +831,7 @@ function c_optical_module:set_link_status(link_status_value)
730 self.NetworkAdapterId, self.PortID, link_status_value)831 self.NetworkAdapterId, self.PortID, link_status_value)
731 if link_status_value == 'Connected' or link_status_value == 'LinkUp' then832 if link_status_value == 'Connected' or link_status_value == 'LinkUp' then
732 self.Presence = 1833 self.Presence = 1
834+ self.t_prop_without_bma.Presence = 1
733 end835 end
734 -- 延迟 require,避免循环依赖;调用时 om_mgmt 已由 network_port 等加载836 -- 延迟 require,避免循环依赖;调用时 om_mgmt 已由 network_port 等加载
735 pcall(function()837 pcall(function()
@@ -763,55 +865,114 @@ function c_optical_module:update_reading_celsius(_, value)
763 end865 end
764end866end
765 867 
868+function c_optical_module:restore_optical_static_info_after_bma_stop()
869+ self:restore_manufacturer_after_bma_stop()
870+ self:restore_part_number_after_bma_stop()
871+ self:restore_serial_number_after_bma_stop()
872+ self:restore_production_date_after_bma_stop()
873+ self:restore_wave_length_nanometer_after_bma_stop()
874+ self:restore_presence_after_bma_stop()
875+end
876+ 
877+function c_optical_module:restore_manufacturer_after_bma_stop()
878+ if self.t_prop_without_bma.Manufacturer then
879+ self.Manufacturer = self.t_prop_without_bma.Manufacturer
880+ else
881+ self.Manufacturer = ''
882+ end
883+end
884+ 
885+function c_optical_module:restore_part_number_after_bma_stop()
886+ if self.t_prop_without_bma.PartNumber then
887+ self.PartNumber = self.t_prop_without_bma.PartNumber
888+ else
889+ self.PartNumber = ''
890+ end
891+end
892+ 
893+function c_optical_module:restore_serial_number_after_bma_stop()
894+ if self.t_prop_without_bma.SerialNumber then
895+ self.SerialNumber = self.t_prop_without_bma.SerialNumber
896+ else
897+ self.SerialNumber = ''
898+ end
899+end
900+ 
901+function c_optical_module:restore_production_date_after_bma_stop()
902+ if self.t_prop_without_bma.ProductionDate then
903+ self.ProductionDate = self.t_prop_without_bma.ProductionDate
904+ else
905+ self.ProductionDate = ''
906+ end
907+end
908+ 
909+function c_optical_module:restore_presence_after_bma_stop()
910+ if self.t_prop_without_bma.Presence then
911+ self.Presence = self.t_prop_without_bma.Presence
912+ else
913+ self.Presence = 0
914+ end
915+end
916+ 
917+function c_optical_module:restore_wave_length_nanometer_after_bma_stop()
918+ if self.t_prop_without_bma.WaveLengthNanometer then
919+ self.WaveLengthNanometer = self.t_prop_without_bma.WaveLengthNanometer
920+ else
921+ self.WaveLengthNanometer = ''
922+ end
923+end
924+ 
766function c_optical_module:reset_bma_info()925function c_optical_module:reset_bma_info()
926+ log:notice('%s optical_module_%s reset bma info', self.NetworkAdapterId, self.PortID)
767 self.TransceiverType = ''927 self.TransceiverType = ''
768- self.ProductionDate = ''
769 self.FiberConnectionType = ''928 self.FiberConnectionType = ''
770 self.SupportedSpeedsMbps = {}929 self.SupportedSpeedsMbps = {}
771 self.Type = ''930 self.Type = ''
772 self.TypeMatch = true931 self.TypeMatch = true
773 self.SpeedMatch = true932 self.SpeedMatch = true
774- if not next(self.ncsi_config_obj) or not self.ncsi_config_obj.OpticalModuleInfo then933+ if self.CreatedByDeviceObject then
775- self.Manufacturer = ''934+ local bus = c_object_manage.get_instance().bus
776- self.PartNumber = ''935+ local device_obj = device_comm_fun.get_device_obj_by_path_interface(bus, self.device_path,
777- self.SerialNumber = ''936+ device_comm_defs.OPTICAL_MODULE_OEM_INTERFACE)
778- self.WaveLengthNanometer = ''937+ if not device_obj then
938+ log:notice('%s optical_module_%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
939+ return
940+ end
941+ local ok = pcall(function()
942+ return device_obj:call_method('RestoreStaticPropAfterBmaStop', '')
943+ end)
944+ if not ok then
945+ log:notice('%s optical_module_%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
946+ return
947+ end
779 else948 else
780- self:next_tick(self.update_NSCI_optical_module_info, self)949+ self:restore_optical_static_info_after_bma_stop()
781 end950 end
782- log:debug('OpticalModule(%sPort%s) stats reset from bma complete', self.NetworkAdapterId,951+ log:notice('%s optical_module_%s reset bma info complete', self.NetworkAdapterId, self.PortID)
783- self.PortID)
784end952end
785 953 
786function c_optical_module:reset_bma_stats()954function c_optical_module:reset_bma_stats()
955+ log:notice('%s optical_module_%s reset bma stats', self.NetworkAdapterId, self.PortID)
787 self.get_diagnostic_by_ibma_success = false956 self.get_diagnostic_by_ibma_success = false
788- self:reset_prop_without_bma()957+ if self.CreatedByDeviceObject then
789- if not next(self.ncsi_config_obj) or not self.ncsi_config_obj.OpticalModuleInfo then958+ local bus = c_object_manage.get_instance().bus
790- self.ReadingCelsius = 0xFFFF959+ local device_obj = device_comm_fun.get_device_obj_by_path_interface(bus, self.device_path,
791- self.Temp_UpperThresholdCritical = 0xFFFF960+ device_comm_defs.OPTICAL_MODULE_OEM_INTERFACE)
792- self.Temp_LowerThresholdCritical = 0xFFFF961+ if not device_obj then
793- self.TemperatureLowerThresholdCritical = 0xFFFF962+ log:notice('%s optical_module_%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
794- self.TemperatureUpperThresholdCritical = 0xFFFF963+ return
795- self.SupplyVoltage = 0xFFFF964+ end
796- self.Vol_UpperThresholdCritical = 0xFFFF965+ local ok = pcall(function()
797- self.Vol_LowerThresholdCritical = 0xFFFF966+ return device_obj:call_method('RestoreDynamicPropAfterBmaStop', '')
798- self.VoltageLowerThresholdCritical = 0xFFFF967+ end)
799- self.VoltageUpperThresholdCritical = 0xFFFF968+ if not ok then
800- self.TXBiasCurrentMilliAmps = {0xFFFF}969+ log:notice('%s optical_module_%s reset_bma_info failed', self.NetworkAdapterId, self.PortID)
801- self.BC_TXUpperThresholdCritical = 0xFFFF970+ return
802- self.BC_TXLowerThresholdCritical = 0xFFFF971+ end
803- self.TXOutputPowerMilliWatts = {0xFFFF}
804- self.Power_TXUpperThresholdCritical = 0xFFFF
805- self.Power_TXLowerThresholdCritical = 0xFFFF
806- self.RXInputPowerMilliWatts = {0xFFFF}
807- self.RXUpperThresholdCritical = 0xFFFF
808- self.RXLowerThresholdCritical = 0xFFFF
809 else972 else
810- self:next_tick(self.update_NSCI_optical_module_info, self)973+ self:restore_optical_dynamic_prop_after_bma_stop()
811 end974 end
812- 975+ log:notice('%s optical_module_%s reset_bma_stats complete', self.NetworkAdapterId, self.PortID)
813- log:debug('OpticalModule(%sPort%s) stats reset from bma complete', self.NetworkAdapterId,
814- self.PortID)
815end976end
816 977 
817function c_optical_module:restart_update_NSCI_optical_module_info(_, Presence)978function c_optical_module:restart_update_NSCI_optical_module_info(_, Presence)
@@ -1687,6 +1848,7 @@ function c_optical_module:sfp_read_eeprom_offset(offset, length)
1687 1848 
1688 if rsp and rsp.Status == 0x00 then1849 if rsp and rsp.Status == 0x00 then
1689 self.Presence = 11850 self.Presence = 1
1851+ self.t_prop_without_bma.Presence = 1
1690 else1852 else
1691 log:info("optical module not supported")1853 log:info("optical module not supported")
1692 end1854 end
@@ -2264,4 +2264,135 @@ function TestCardMgmt:test_handle_port_count_mismatch_mismatch_set_failed()
2264 c_network_adapter.collection.find = orig_collection_find2264 c_network_adapter.collection.find = orig_collection_find
2265end2265end
2266 2266 
2267+-- 覆盖 card_mgmt:update_firmware_version(card_mgmt.lua 581-600)
2268+function TestCardMgmt:test_update_firmware_version_skips_when_not_created_by_device_object()
2269+ local orig_get = comm_fun.get_device_obj_by_path_interface
2270+ local called = false
2271+ comm_fun.get_device_obj_by_path_interface = function()
2272+ called = true
2273+ return {}
2274+ end
2275+ local mgr = card_mgmt
2276+ mgr.bus = {}
2277+ mgr:update_firmware_version({
2278+ CreatedByDeviceObject = false,
2279+ NodeId = 'NA_SKIP',
2280+ device_path = '/any',
2281+ }, '1.0.0')
2282+ lu.assertFalse(called)
2283+ comm_fun.get_device_obj_by_path_interface = orig_get
2284+end
2285+ 
2286+function TestCardMgmt:test_update_firmware_version_fails_when_device_path_empty()
2287+ local orig_get = comm_fun.get_device_obj_by_path_interface
2288+ local errors = {}
2289+ local orig_notice, orig_error = log.notice, log.error
2290+ log.notice = function() end
2291+ log.error = function(_, fmt, ...)
2292+ table.insert(errors, string.format(fmt, ...))
2293+ end
2294+ comm_fun.get_device_obj_by_path_interface = function()
2295+ error('should not get device when path empty')
2296+ end
2297+ local mgr = card_mgmt
2298+ mgr.bus = {}
2299+ mgr:update_firmware_version({
2300+ CreatedByDeviceObject = true,
2301+ NodeId = 'NA_EMPTY',
2302+ device_path = '',
2303+ }, '1.0.0')
2304+ local hit = false
2305+ for _, msg in ipairs(errors) do
2306+ if msg:find('port_device_path is nil or empty') then
2307+ hit = true
2308+ break
2309+ end
2310+ end
2311+ lu.assertTrue(hit)
2312+ log.notice = orig_notice
2313+ log.error = orig_error
2314+ comm_fun.get_device_obj_by_path_interface = orig_get
2315+end
2316+ 
2317+function TestCardMgmt:test_update_firmware_version_fails_when_device_path_nil()
2318+ local orig_get = comm_fun.get_device_obj_by_path_interface
2319+ local errors = {}
2320+ local orig_notice, orig_error = log.notice, log.error
2321+ log.notice = function() end
2322+ log.error = function(_, fmt, ...)
2323+ table.insert(errors, string.format(fmt, ...))
2324+ end
2325+ comm_fun.get_device_obj_by_path_interface = function()
2326+ error('should not get device when path nil')
2327+ end
2328+ local mgr = card_mgmt
2329+ mgr.bus = {}
2330+ mgr:update_firmware_version({
2331+ CreatedByDeviceObject = true,
2332+ NodeId = 'NA_NIL_PATH',
2333+ device_path = nil,
2334+ }, '1.0.0')
2335+ lu.assertEquals(#errors, 1)
2336+ lu.assertNotNil(string.find(errors[1], 'port_device_path is nil or empty', 1, true))
2337+ log.notice = orig_notice
2338+ log.error = orig_error
2339+ comm_fun.get_device_obj_by_path_interface = orig_get
2340+end
2341+ 
2342+function TestCardMgmt:test_update_firmware_version_fails_when_card_device_obj_nil()
2343+ local orig_get = comm_fun.get_device_obj_by_path_interface
2344+ local errors = {}
2345+ local orig_notice, orig_error = log.notice, log.error
2346+ log.notice = function() end
2347+ log.error = function(_, fmt, ...)
2348+ table.insert(errors, string.format(fmt, ...))
2349+ end
2350+ local bus = {}
2351+ comm_fun.get_device_obj_by_path_interface = function(b, path, iface)
2352+ lu.assertIs(b, bus)
2353+ lu.assertEquals(path, '/ut/card0')
2354+ lu.assertEquals(iface, comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE)
2355+ return nil
2356+ end
2357+ local mgr = card_mgmt
2358+ mgr.bus = bus
2359+ mgr:update_firmware_version({
2360+ CreatedByDeviceObject = true,
2361+ NodeId = 'NA_NIL_DEV',
2362+ device_path = '/ut/card0',
2363+ }, '2.0.0')
2364+ local hit = false
2365+ for _, msg in ipairs(errors) do
2366+ if msg:find('card_device_obj is nil') and msg:find('/ut/card0') then
2367+ hit = true
2368+ break
2369+ end
2370+ end
2371+ lu.assertTrue(hit)
2372+ log.notice = orig_notice
2373+ log.error = orig_error
2374+ comm_fun.get_device_obj_by_path_interface = orig_get
2375+end
2376+ 
2377+function TestCardMgmt:test_update_firmware_version_success_sets_property()
2378+ local orig_get = comm_fun.get_device_obj_by_path_interface
2379+ local bus = {}
2380+ local dbus_card = { FirmwareVersion = 'old' }
2381+ comm_fun.get_device_obj_by_path_interface = function(b, path, iface)
2382+ lu.assertIs(b, bus)
2383+ lu.assertEquals(path, '/ut/card_ok')
2384+ lu.assertEquals(iface, comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE)
2385+ return dbus_card
2386+ end
2387+ local mgr = card_mgmt
2388+ mgr.bus = bus
2389+ mgr:update_firmware_version({
2390+ CreatedByDeviceObject = true,
2391+ NodeId = 'NA_OK',
2392+ device_path = '/ut/card_ok',
2393+ }, 'FW_NEW')
2394+ lu.assertEquals(dbus_card.FirmwareVersion, 'FW_NEW')
2395+ comm_fun.get_device_obj_by_path_interface = orig_get
2396+end
2397+ 
2267return TestCardMgmt2398return TestCardMgmt
@@ -43,7 +43,23 @@ local sync_cases = {
43 { func = 'set_voltage_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_VOLTAGE_INTERFACE', field = 'VoltageLowerThresholdCritical' },43 { func = 'set_voltage_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_VOLTAGE_INTERFACE', field = 'VoltageLowerThresholdCritical' },
44 { func = 'set_voltage_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_VOLTAGE_INTERFACE', field = 'VoltageUpperThresholdCritical' },44 { func = 'set_voltage_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_VOLTAGE_INTERFACE', field = 'VoltageUpperThresholdCritical' },
45 { func = 'set_bias_current_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_CURRENT_INTERFACE', field = 'TXBiasCurrentUpperThresholdCritical' },45 { func = 'set_bias_current_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_CURRENT_INTERFACE', field = 'TXBiasCurrentUpperThresholdCritical' },
46- { func = 'set_bias_current_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_CURRENT_INTERFACE', field = 'TXBiasCurrentLowerThresholdCritical' }46+ { func = 'set_bias_current_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_CURRENT_INTERFACE', field = 'TXBiasCurrentLowerThresholdCritical' },
47+ -- BMA → 设备树:厂商/料号/序列号/日期/波长(om_mgmt.lua 234-257)
48+ { func = 'update_manufacturer_to_device_obj', interface_key = 'OPTICAL_MODULE_DEVICE_INTERFACE', field = 'Manufacturer' },
49+ { func = 'update_part_number_to_device_obj', interface_key = 'OPTICAL_MODULE_DEVICE_INTERFACE', field = 'PartNumber' },
50+ { func = 'update_serial_number_to_device_obj', interface_key = 'OPTICAL_MODULE_DEVICE_INTERFACE', field = 'SerialNumber' },
51+ { func = 'update_production_date_to_device_obj', interface_key = 'OPTICAL_MODULE_DEVICE_INTERFACE', field = 'ProductionDate' },
52+ { func = 'update_wave_length_nanometer_to_device_obj', interface_key = 'OPTICAL_MODULE_DEVICE_INTERFACE', field = 'WaveLengthNanometer' },
53+ -- 温度/功率/电流阈值与诊断量(om_mgmt.lua 313-356)
54+ { func = 'set_temperature_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE', field = 'TemperatureUpperThresholdCritical' },
55+ { func = 'set_temperature_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_TEMPERATURE_CELSIUS_INTERFACE', field = 'TemperatureLowerThresholdCritical' },
56+ { func = 'set_tx_bias_current_milli_amps_to_device_obj', interface_key = 'OPTICAL_MODULE_CURRENT_INTERFACE', field = 'TXBiasCurrentMilliAmps' },
57+ { func = 'set_tx_output_power_milli_watts_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'TXOutputPowerMilliWatts' },
58+ { func = 'set_rx_input_power_milli_watts_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'RXInputPowerMilliWatts' },
59+ { func = 'set_rx_power_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'RXPowerUpperThresholdCritical' },
60+ { func = 'set_rx_power_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'RXPowerLowerThresholdCritical' },
61+ { func = 'set_tx_power_upper_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'TXPowerUpperThresholdCritical' },
62+ { func = 'set_tx_power_lower_threshold_critical_to_device_obj', interface_key = 'OPTICAL_MODULE_POWER_INTERFACE', field = 'TXPowerLowerThresholdCritical' },
47}63}
48 64 
49local NIL = {}65local NIL = {}
@@ -81,6 +97,8 @@ function TestOmMgmt:setUp()
81 -- mock comm_defs97 -- mock comm_defs
82 stub(comm_defs, 'CARD_DEVICE_PATH_PATTERN', '/mock/pattern')98 stub(comm_defs, 'CARD_DEVICE_PATH_PATTERN', '/mock/pattern')
83 stub(comm_defs, 'OPTICAL_MODULE_DEVICE_INTERFACE', 'iface_om')99 stub(comm_defs, 'OPTICAL_MODULE_DEVICE_INTERFACE', 'iface_om')
100+ stub(comm_defs, 'OPTICAL_MODULE_CURRENT_INTERFACE', 'iface_cur')
101+ stub(comm_defs, 'OPTICAL_MODULE_POWER_INTERFACE', 'iface_pwr')
84 stub(comm_defs, 'MACA_SERVICE', 'svc')102 stub(comm_defs, 'MACA_SERVICE', 'svc')
85 stub(comm_defs, 'MDB_PATH', '/mdb')103 stub(comm_defs, 'MDB_PATH', '/mdb')
86 stub(comm_defs, 'MDB_INTERFACE', 'mdb_iface')104 stub(comm_defs, 'MDB_INTERFACE', 'mdb_iface')
@@ -337,4 +355,150 @@ function TestOmMgmt:test_del_obj_remove_optical_module()
337 c_optical_module.collection.del_object = orig_del355 c_optical_module.collection.del_object = orig_del
338end356end
339 357 
358+-- 覆盖 handle_special_property_mapping:经 init_obj → synchronize_property(om_mgmt.lua 85-106)
359+function TestOmMgmt:test_synchronize_special_property_mapping_basic()
360+ local iface_om = comm_defs.OPTICAL_MODULE_DEVICE_INTERFACE
361+ local iface_cur = comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE
362+ local iface_pwr = comm_defs.OPTICAL_MODULE_POWER_INTERFACE
363+ local dbus_tx = { 0.11 }
364+ local dbus_rx = { 0.22 }
365+ local dbus_txpwr = { 0.33 }
366+ 
367+ local orig_get_object = mdb.get_object
368+ mdb.get_object = function(bus, path, interface)
369+ return {
370+ get_property = function(_, prop)
371+ if interface == iface_om and prop == 'TransmissionDistance' then
372+ return 0, 42
373+ end
374+ if interface == iface_cur and prop == 'TXBiasCurrentMilliAmps' then
375+ return 0, dbus_tx
376+ end
377+ if interface == iface_pwr and prop == 'RXInputPowerMilliWatts' then
378+ return 0, dbus_rx
379+ end
380+ if interface == iface_pwr and prop == 'TXOutputPowerMilliWatts' then
381+ return 0, dbus_txpwr
382+ end
383+ return -1, nil
384+ end,
385+ }
386+ end
387+ 
388+ local bus = {}
389+ bus.match = function()
390+ return 1
391+ end
392+ bus.call = function(_, svc, devpath, org_iface, method, ...)
393+ if method == 'GetObject' then
394+ return { svc = { iface_om, iface_cur, iface_pwr } }
395+ end
396+ if method == 'GetAll' then
397+ local _, interface = ...
398+ if interface == iface_om then
399+ return { TransmissionDistance = true }
400+ end
401+ if interface == iface_cur then
402+ return { TXBiasCurrentMilliAmps = true }
403+ end
404+ if interface == iface_pwr then
405+ return { RXInputPowerMilliWatts = true, TXOutputPowerMilliWatts = true }
406+ end
407+ end
408+ return {}
409+ end
410+ 
411+ local mgr = om_mgmt
412+ mgr.bus = bus
413+ mgr.objects = {}
414+ mgr.sig_slot = {}
415+ mgr:init_obj('/om1')
416+ mdb.get_object = orig_get_object
417+ 
418+ local orm = mgr.objects['/om1']
419+ lu.assertNotNil(orm)
420+ lu.assertEquals(orm.TransmissionDistance, '42')
421+ lu.assertEquals(orm.TXBiasCurrentMilliAmps, dbus_tx)
422+ lu.assertEquals(orm.RXInputPowerMilliWatts, dbus_rx)
423+ lu.assertEquals(orm.TXOutputPowerMilliWatts, dbus_txpwr)
424+end
425+ 
426+-- 多通道且 iBMA 诊断已成功时,不以设备树覆盖 BMA 侧 TX/RX/TX 功率
427+function TestOmMgmt:test_synchronize_special_property_mapping_skips_multi_channel_when_ibma_ok()
428+ local iface_cur = comm_defs.OPTICAL_MODULE_CURRENT_INTERFACE
429+ local iface_pwr = comm_defs.OPTICAL_MODULE_POWER_INTERFACE
430+ 
431+ local keep_tx = { 1, 2 }
432+ local keep_rx = { 3, 4 }
433+ local keep_txpwr = { 5, 6 }
434+ 
435+ local coll = c_optical_module.collection
436+ local orig_find = coll.find
437+ coll.find = function(self, q)
438+ return {
439+ children = {},
440+ PortID = q and q.PortID or 123,
441+ NetworkAdapterId = q and q.NetworkAdapterId or 'nid',
442+ parent = { ObjectName = 'obj' },
443+ ObjectName = 'portobj',
444+ TXBiasCurrentMilliAmps = keep_tx,
445+ RXInputPowerMilliWatts = keep_rx,
446+ TXOutputPowerMilliWatts = keep_txpwr,
447+ get_diagnostic_by_ibma_success = true,
448+ }
449+ end
450+ 
451+ local orig_get_object = mdb.get_object
452+ mdb.get_object = function(bus, path, interface)
453+ return {
454+ get_property = function(_, prop)
455+ if interface == iface_cur and prop == 'TXBiasCurrentMilliAmps' then
456+ return 0, { 99 }
457+ end
458+ if interface == iface_pwr and prop == 'RXInputPowerMilliWatts' then
459+ return 0, { 98 }
460+ end
461+ if interface == iface_pwr and prop == 'TXOutputPowerMilliWatts' then
462+ return 0, { 97 }
463+ end
464+ return -1, nil
465+ end,
466+ }
467+ end
468+ 
469+ local bus = {}
470+ bus.match = function()
471+ return 1
472+ end
473+ bus.call = function(_, svc, devpath, org_iface, method, ...)
474+ if method == 'GetObject' then
475+ return { svc = { iface_cur, iface_pwr } }
476+ end
477+ if method == 'GetAll' then
478+ local _, interface = ...
479+ if interface == iface_cur then
480+ return { TXBiasCurrentMilliAmps = true }
481+ end
482+ if interface == iface_pwr then
483+ return { RXInputPowerMilliWatts = true, TXOutputPowerMilliWatts = true }
484+ end
485+ end
486+ return {}
487+ end
488+ 
489+ local mgr = om_mgmt
490+ mgr.bus = bus
491+ mgr.objects = {}
492+ mgr.sig_slot = {}
493+ mgr:init_obj('/om1')
494+ mdb.get_object = orig_get_object
495+ coll.find = orig_find
496+ 
497+ local orm = mgr.objects['/om1']
498+ lu.assertNotNil(orm)
499+ lu.assertEquals(orm.TXBiasCurrentMilliAmps, keep_tx)
500+ lu.assertEquals(orm.RXInputPowerMilliWatts, keep_rx)
501+ lu.assertEquals(orm.TXOutputPowerMilliWatts, keep_txpwr)
502+end
503+ 
340return TestOmMgmt504return TestOmMgmt
@@ -40,7 +40,11 @@ TestPortMgmt = {}
40local NIL = {}40local NIL = {}
41local sync_cases = {41local sync_cases = {
42 { func = 'set_link_status_to_device_obj', interface_key = 'NETWORK_PORT_LINK_INFO_INTERFACE', field = 'LinkStatus' },42 { func = 'set_link_status_to_device_obj', interface_key = 'NETWORK_PORT_LINK_INFO_INTERFACE', field = 'LinkStatus' },
43- { func = 'set_bandwidth_usage_to_device_obj', interface_key = 'NETWORK_PORT_METRICS_INTERFACE', field = 'BandwidthPercent' }43+ { func = 'set_bandwidth_usage_to_device_obj', interface_key = 'NETWORK_PORT_METRICS_INTERFACE', field = 'BandwidthPercent' },
44+ { func = 'update_full_duplex_to_device_obj', interface_key = 'NETWORK_PORT_LINK_INFO_INTERFACE', field = 'FullDuplex' },
45+ { func = 'update_speed_mbps_to_device_obj', interface_key = 'NETWORK_PORT_LINK_INFO_INTERFACE', field = 'SpeedMbps' },
46+ { func = 'update_auto_negotiation_to_device_obj', interface_key = 'NETWORK_PORT_LINK_INFO_INTERFACE', field = 'AutoSpeedNegotiationEnabled' },
47+ { func = 'update_bdf_to_device_obj', interface_key = 'NETWORK_PORT_DEVICE_INTERFACE', field = 'BDF' },
44}48}
45 49 
46local function make_port_obj(overrides)50local function make_port_obj(overrides)
@@ -74,6 +78,7 @@ function TestPortMgmt:setUp()
74 stub(comm_defs, 'CARD_DEVICE_PATH_PATTERN', '/mock/pattern')78 stub(comm_defs, 'CARD_DEVICE_PATH_PATTERN', '/mock/pattern')
75 stub(comm_defs, 'NETWORK_PORT_DEVICE_INTERFACE', 'iface_port')79 stub(comm_defs, 'NETWORK_PORT_DEVICE_INTERFACE', 'iface_port')
76 stub(comm_defs, 'NETWORK_PORT_LINK_INFO_INTERFACE', 'link_info_iface')80 stub(comm_defs, 'NETWORK_PORT_LINK_INFO_INTERFACE', 'link_info_iface')
81+ stub(comm_defs, 'NETWORK_PORT_METRICS_INTERFACE', 'metrics_iface')
77 stub(comm_defs, 'MACA_SERVICE', 'svc')82 stub(comm_defs, 'MACA_SERVICE', 'svc')
78 stub(comm_defs, 'MDB_PATH', '/mdb')83 stub(comm_defs, 'MDB_PATH', '/mdb')
79 stub(comm_defs, 'MDB_INTERFACE', 'mdb_iface')84 stub(comm_defs, 'MDB_INTERFACE', 'mdb_iface')
@@ -295,6 +300,20 @@ function TestPortMgmt:test_sync_port_device_obj_success_sets_field()
295 end300 end
296end301end
297 302 
303+-- update_bdf_to_device_obj:value 为 nil 时直接返回(port_mgmt.lua 378-380)
304+function TestPortMgmt:test_update_bdf_to_device_obj_skips_when_value_nil()
305+ local mgr = port_mgmt
306+ mgr.bus = self.bus
307+ local call_count = 0
308+ local restore = set_device_obj_stub(function(...)
309+ call_count = call_count + 1
310+ return {}
311+ end)
312+ mgr:update_bdf_to_device_obj(make_port_obj(), nil)
313+ lu.assertEquals(call_count, 0)
314+ restore()
315+end
316+ 
298function TestPortMgmt:test_link_status_property_change()317function TestPortMgmt:test_link_status_property_change()
299 local set_link_status_called = false318 local set_link_status_called = false
300 local set_link_status_numeric_called = false319 local set_link_status_numeric_called = false
@@ -10,12 +10,13 @@
10local lu = require 'luaunit'10local lu = require 'luaunit'
11local c_network_port = require 'device.class.network_port'11local c_network_port = require 'device.class.network_port'
12local c_object_manage = require 'mc.orm.object_manage'12local c_object_manage = require 'mc.orm.object_manage'
13+local device_comm_fun = require 'device.class.nic_mgmt.comm_fun'
14+local device_comm_defs = require 'device.class.nic_mgmt.comm_defs'
13local npu_imu_cmd = require 'npu.hdk_cmd'15local npu_imu_cmd = require 'npu.hdk_cmd'
14local test_utils = require 'test_utils'16local test_utils = require 'test_utils'
15local class_mgnt = require "mc.class_mgnt"17local class_mgnt = require "mc.class_mgnt"
16local fructl = require 'infrastructure.fructl'18local fructl = require 'infrastructure.fructl'
17skynet = require 'skynet'19skynet = require 'skynet'
18-local c_network_port = require 'device.class.network_port'
19local context = require 'mc.context'20local context = require 'mc.context'
20local client = require 'network_adapter.client'21local client = require 'network_adapter.client'
21local vos = require 'utils.vos'22local vos = require 'utils.vos'
@@ -200,9 +201,10 @@ local test_data = {
200}201}
201-- 测试更新链接状态202-- 测试更新链接状态
202function TEST_network_port:test_update_ncsi_link_status()203function TEST_network_port:test_update_ncsi_link_status()
204+ local origin_schedulers = c_network_port.schedulers
203 local origin_smbus_schedulers = c_network_port.smbus_schedulers205 local origin_smbus_schedulers = c_network_port.smbus_schedulers
204 local origin_get_properties_res = c_network_port.get_properties_res206 local origin_get_properties_res = c_network_port.get_properties_res
205- c_network_port.t_port_prop_without_bma = {}207+ c_network_port.t_prop_without_bma = {}
206 c_network_port.schedulers = {}208 c_network_port.schedulers = {}
207 c_network_port.smbus_schedulers = {}209 c_network_port.smbus_schedulers = {}
208 c_network_port.get_properties_res = {}210 c_network_port.get_properties_res = {}
@@ -1107,7 +1109,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_recovered_stops_smb
1107 local original_ncsi_config_obj = c_network_port.ncsi_config_obj1109 local original_ncsi_config_obj = c_network_port.ncsi_config_obj
1108 local original_package_id = c_network_port.package_id1110 local original_package_id = c_network_port.package_id
1109 local original_get_port_id = c_network_port.get_port_id1111 local original_get_port_id = c_network_port.get_port_id
1110- local original_t_port_prop_without_bma = c_network_port.t_port_prop_without_bma1112+ local original_t_prop_without_bma = c_network_port.t_prop_without_bma
1111 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count1113 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count
1112 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess1114 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess
1113 local original_LinkStatus = c_network_port.LinkStatus1115 local original_LinkStatus = c_network_port.LinkStatus
@@ -1120,7 +1122,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_recovered_stops_smb
1120 c_network_port.smbus_schedulers = {}1122 c_network_port.smbus_schedulers = {}
1121 c_network_port.package_id = 01123 c_network_port.package_id = 0
1122 c_network_port.get_port_id = function() return 1 end1124 c_network_port.get_port_id = function() return 1 end
1123- c_network_port.t_port_prop_without_bma = {}1125+ c_network_port.t_prop_without_bma = {}
1124 c_network_port.ncsi_get_linkstatus_retry_count = 01126 c_network_port.ncsi_get_linkstatus_retry_count = 0
1125 c_network_port.get_ncsi_link_status_succeess = false1127 c_network_port.get_ncsi_link_status_succeess = false
1126 1128
@@ -1184,7 +1186,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_recovered_stops_smb
1184 c_network_port.ncsi_config_obj = original_ncsi_config_obj1186 c_network_port.ncsi_config_obj = original_ncsi_config_obj
1185 c_network_port.package_id = original_package_id1187 c_network_port.package_id = original_package_id
1186 c_network_port.get_port_id = original_get_port_id1188 c_network_port.get_port_id = original_get_port_id
1187- c_network_port.t_port_prop_without_bma = original_t_port_prop_without_bma1189+ c_network_port.t_prop_without_bma = original_t_prop_without_bma
1188 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count1190 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count
1189 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess1191 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess
1190 c_network_port.LinkStatus = original_LinkStatus1192 c_network_port.LinkStatus = original_LinkStatus
@@ -1201,7 +1203,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_failed_activates_sm
1201 local original_ncsi_config_obj = c_network_port.ncsi_config_obj1203 local original_ncsi_config_obj = c_network_port.ncsi_config_obj
1202 local original_package_id = c_network_port.package_id1204 local original_package_id = c_network_port.package_id
1203 local original_get_port_id = c_network_port.get_port_id1205 local original_get_port_id = c_network_port.get_port_id
1204- local original_t_port_prop_without_bma = c_network_port.t_port_prop_without_bma1206+ local original_t_prop_without_bma = c_network_port.t_prop_without_bma
1205 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count1207 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count
1206 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess1208 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess
1207 local original_LinkStatus = c_network_port.LinkStatus1209 local original_LinkStatus = c_network_port.LinkStatus
@@ -1214,7 +1216,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_failed_activates_sm
1214 c_network_port.smbus_schedulers = {}1216 c_network_port.smbus_schedulers = {}
1215 c_network_port.package_id = 01217 c_network_port.package_id = 0
1216 c_network_port.get_port_id = function() return 1 end1218 c_network_port.get_port_id = function() return 1 end
1217- c_network_port.t_port_prop_without_bma = {}1219+ c_network_port.t_prop_without_bma = {}
1218 c_network_port.ncsi_get_linkstatus_retry_count = 01220 c_network_port.ncsi_get_linkstatus_retry_count = 0
1219 c_network_port.get_ncsi_link_status_succeess = false1221 c_network_port.get_ncsi_link_status_succeess = false
1220 1222
@@ -1268,7 +1270,7 @@ function TEST_network_port:test_update_ncsi_link_status_ncsi_failed_activates_sm
1268 c_network_port.ncsi_config_obj = original_ncsi_config_obj1270 c_network_port.ncsi_config_obj = original_ncsi_config_obj
1269 c_network_port.package_id = original_package_id1271 c_network_port.package_id = original_package_id
1270 c_network_port.get_port_id = original_get_port_id1272 c_network_port.get_port_id = original_get_port_id
1271- c_network_port.t_port_prop_without_bma = original_t_port_prop_without_bma1273+ c_network_port.t_prop_without_bma = original_t_prop_without_bma
1272 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count1274 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count
1273 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess1275 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess
1274 c_network_port.LinkStatus = original_LinkStatus1276 c_network_port.LinkStatus = original_LinkStatus
@@ -1450,13 +1452,14 @@ function TEST_network_port:test_update_BDF_by_ncsi_while_loop_logic()
1450 local original_sleep_ms = c_network_port.sleep_ms1452 local original_sleep_ms = c_network_port.sleep_ms
1451 local original_WorkloadType = c_network_port.WorkloadType1453 local original_WorkloadType = c_network_port.WorkloadType
1452 local original_BDF = c_network_port.BDF1454 local original_BDF = c_network_port.BDF
1455+ local original_t_prop_without_bma = c_network_port.t_prop_without_bma
1453 1456
1454 -- 初始化测试状态1457 -- 初始化测试状态
1455 c_network_port.package_id = 01458 c_network_port.package_id = 0
1456 c_network_port.get_port_id = function() return 1 end1459 c_network_port.get_port_id = function() return 1 end
1457 c_network_port.bdf_task_is_running = false1460 c_network_port.bdf_task_is_running = false
1458 c_network_port.WorkloadType = 01461 c_network_port.WorkloadType = 0
1459- 1462+ c_network_port.t_prop_without_bma = {}
1460 -- 模拟BDF获取成功的情况1463 -- 模拟BDF获取成功的情况
1461 local call_count = 01464 local call_count = 0
1462 c_network_port.ncsi_config_obj = {1465 c_network_port.ncsi_config_obj = {
@@ -1502,6 +1505,7 @@ function TEST_network_port:test_update_BDF_by_ncsi_while_loop_logic()
1502 c_network_port.sleep_ms = original_sleep_ms1505 c_network_port.sleep_ms = original_sleep_ms
1503 c_network_port.WorkloadType = original_WorkloadType1506 c_network_port.WorkloadType = original_WorkloadType
1504 c_network_port.BDF = original_BDF1507 c_network_port.BDF = original_BDF
1508+ c_network_port.t_prop_without_bma = original_t_prop_without_bma
1505end1509end
1506 1510 
1507-- 测试update_BDF_by_ncsi函数的重复调用保护1511-- 测试update_BDF_by_ncsi函数的重复调用保护
@@ -1576,7 +1580,7 @@ function TEST_network_port:test_ncsi_recovered_when_smbus_already_paused()
1576 local original_ncsi_config_obj = c_network_port.ncsi_config_obj1580 local original_ncsi_config_obj = c_network_port.ncsi_config_obj
1577 local original_package_id = c_network_port.package_id1581 local original_package_id = c_network_port.package_id
1578 local original_get_port_id = c_network_port.get_port_id1582 local original_get_port_id = c_network_port.get_port_id
1579- local original_t_port_prop_without_bma = c_network_port.t_port_prop_without_bma1583+ local original_t_prop_without_bma = c_network_port.t_prop_without_bma
1580 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count1584 local original_ncsi_get_linkstatus_retry_count = c_network_port.ncsi_get_linkstatus_retry_count
1581 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess1585 local original_get_ncsi_link_status_succeess = c_network_port.get_ncsi_link_status_succeess
1582 local original_LinkStatus = c_network_port.LinkStatus1586 local original_LinkStatus = c_network_port.LinkStatus
@@ -1589,7 +1593,7 @@ function TEST_network_port:test_ncsi_recovered_when_smbus_already_paused()
1589 c_network_port.smbus_schedulers = {}1593 c_network_port.smbus_schedulers = {}
1590 c_network_port.package_id = 01594 c_network_port.package_id = 0
1591 c_network_port.get_port_id = function() return 1 end1595 c_network_port.get_port_id = function() return 1 end
1592- c_network_port.t_port_prop_without_bma = {}1596+ c_network_port.t_prop_without_bma = {}
1593 c_network_port.ncsi_get_linkstatus_retry_count = 01597 c_network_port.ncsi_get_linkstatus_retry_count = 0
1594 c_network_port.get_ncsi_link_status_succeess = false1598 c_network_port.get_ncsi_link_status_succeess = false
1595 1599
@@ -1649,13 +1653,13 @@ function TEST_network_port:test_ncsi_recovered_when_smbus_already_paused()
1649 c_network_port.ncsi_config_obj = original_ncsi_config_obj1653 c_network_port.ncsi_config_obj = original_ncsi_config_obj
1650 c_network_port.package_id = original_package_id1654 c_network_port.package_id = original_package_id
1651 c_network_port.get_port_id = original_get_port_id1655 c_network_port.get_port_id = original_get_port_id
1652- c_network_port.t_port_prop_without_bma = original_t_port_prop_without_bma
1653 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count1656 c_network_port.ncsi_get_linkstatus_retry_count = original_ncsi_get_linkstatus_retry_count
1654 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess1657 c_network_port.get_ncsi_link_status_succeess = original_get_ncsi_link_status_succeess
1655 c_network_port.LinkStatus = original_LinkStatus1658 c_network_port.LinkStatus = original_LinkStatus
1656 c_network_port.SpeedMbps = original_SpeedMbps1659 c_network_port.SpeedMbps = original_SpeedMbps
1657 c_network_port.AutoSpeedNegotiation = original_AutoSpeedNegotiation1660 c_network_port.AutoSpeedNegotiation = original_AutoSpeedNegotiation
1658 c_network_port.FullDuplex = original_FullDuplex1661 c_network_port.FullDuplex = original_FullDuplex
1662+ c_network_port.t_prop_without_bma = original_t_prop_without_bma
1659end1663end
1660 1664 
1661-- 测试enable_lldp_over_mctp函数第一次就成功的场景1665-- 测试enable_lldp_over_mctp函数第一次就成功的场景
@@ -1721,7 +1725,7 @@ end
1721-- local log_module = require 'mc.logging'1725-- local log_module = require 'mc.logging'
1722-- local original_log_notice = log_module.notice1726-- local original_log_notice = log_module.notice
1723-- local original_log_debug = log_module.debug1727-- local original_log_debug = log_module.debug
1724--- local original_reset_port_prop_without_bma = c_network_port.reset_port_prop_without_bma1728+-- local original_restore_port_prop_without_bma = c_network_port.restore_port_prop_without_bma
1725 1729
1726-- -- 备份原始状态1730-- -- 备份原始状态
1727-- local original_NetworkAdapterId = c_network_port.NetworkAdapterId1731-- local original_NetworkAdapterId = c_network_port.NetworkAdapterId
@@ -1741,7 +1745,7 @@ end
1741-- local original_SpeedGbps = c_network_port.SpeedGbps1745-- local original_SpeedGbps = c_network_port.SpeedGbps
1742-- local original_FirmwareVersion = c_network_port.FirmwareVersion1746-- local original_FirmwareVersion = c_network_port.FirmwareVersion
1743-- local original_ncsi_config_obj = c_network_port.ncsi_config_obj1747-- local original_ncsi_config_obj = c_network_port.ncsi_config_obj
1744--- local original_t_port_prop_without_bma = c_network_port.t_port_prop_without_bma1748+-- local original_t_prop_without_bma = c_network_port.t_prop_without_bma
1745 1749
1746-- -- 记录日志调用1750-- -- 记录日志调用
1747-- local log_notice_calls = {}1751-- local log_notice_calls = {}
@@ -1764,9 +1768,9 @@ end
1764-- c_network_port.SpeedMbps = 10001768-- c_network_port.SpeedMbps = 1000
1765-- c_network_port.AutoSpeedNegotiation = true1769-- c_network_port.AutoSpeedNegotiation = true
1766-- c_network_port.ncsi_config_obj = {}1770-- c_network_port.ncsi_config_obj = {}
1767--- c_network_port.t_port_prop_without_bma = {LinkStatus = 'N/A'}1771+-- c_network_port.t_prop_without_bma = {LinkStatus = 'N/A'}
1768 1772
1769--- c_network_port.reset_port_prop_without_bma = function(self)1773+-- c_network_port.restore_port_prop_without_bma = function(self)
1770-- self.LinkStatus = 'N/A'1774-- self.LinkStatus = 'N/A'
1771-- end1775-- end
1772 1776
@@ -1876,7 +1880,7 @@ end
1876-- lu.assertEquals(c_network_port.FirmwareVersion, "2.0.0", "FirmwareVersion should not be reset when FCId is empty")1880-- lu.assertEquals(c_network_port.FirmwareVersion, "2.0.0", "FirmwareVersion should not be reset when FCId is empty")
1877 1881
1878-- -- 还原原始状态1882-- -- 还原原始状态
1879--- c_network_port.reset_port_prop_without_bma = original_reset_port_prop_without_bma1883+-- c_network_port.restore_port_prop_without_bma = original_restore_port_prop_without_bma
1880-- c_network_port.NetworkAdapterId = original_NetworkAdapterId1884-- c_network_port.NetworkAdapterId = original_NetworkAdapterId
1881-- c_network_port.PortID = original_PortID1885-- c_network_port.PortID = original_PortID
1882-- c_network_port.OSLinkStatus = original_OSLinkStatus1886-- c_network_port.OSLinkStatus = original_OSLinkStatus
@@ -1894,11 +1898,206 @@ end
1894-- c_network_port.SpeedGbps = original_SpeedGbps1898-- c_network_port.SpeedGbps = original_SpeedGbps
1895-- c_network_port.FirmwareVersion = original_FirmwareVersion1899-- c_network_port.FirmwareVersion = original_FirmwareVersion
1896-- c_network_port.ncsi_config_obj = original_ncsi_config_obj1900-- c_network_port.ncsi_config_obj = original_ncsi_config_obj
1897--- c_network_port.t_port_prop_without_bma = original_t_port_prop_without_bma1901+-- c_network_port.t_prop_without_bma = original_t_prop_without_bma
1898-- log_module.notice = original_log_notice1902-- log_module.notice = original_log_notice
1899-- log_module.debug = original_log_debug1903-- log_module.debug = original_log_debug
1900-- end1904-- end
1901 1905 
1906+-- 覆盖 restore_*_after_bma_stop、restore_port_prop_without_bma、reset_bma_info 中非 BMA 属性恢复(network_port.lua 101-148, 817-858)
1907+local function make_np_bma_stub(overrides)
1908+ local p = {
1909+ NetworkAdapterId = 'UT',
1910+ PortID = 1,
1911+ device_path = '/ut/pcie/p0',
1912+ CreatedByDeviceObject = false,
1913+ FCId = '',
1914+ t_prop_without_bma = {},
1915+ OSLinkStatus = 'Up',
1916+ Name = 'eth0',
1917+ WorkMode = 'Loop',
1918+ DriverName = 'drv',
1919+ DriverVersion = '1.0',
1920+ SpeedMbps = 9999,
1921+ AutoSpeedNegotiation = 1,
1922+ FullDuplex = 1,
1923+ BDF = 'bdf_bma',
1924+ FirmwareVersion = 'fw_bma',
1925+ MACAddress = '11:22:33:44:55:66',
1926+ PermanentMACAddress = nil,
1927+ }
1928+ if overrides then
1929+ for k, v in pairs(overrides) do
1930+ p[k] = v
1931+ end
1932+ end
1933+ setmetatable(p, { __index = c_network_port })
1934+ return p
1935+end
1936+ 
1937+function TEST_network_port:test_restore_speed_mbps_after_bma_stop_uses_cache()
1938+ local p = make_np_bma_stub()
1939+ p.t_prop_without_bma.SpeedMbps = 2500
1940+ c_network_port.restore_speed_mbps_after_bma_stop(p)
1941+ lu.assertEquals(p.SpeedMbps, 2500)
1942+end
1943+ 
1944+function TEST_network_port:test_restore_speed_mbps_after_bma_stop_default_uint_max()
1945+ local p = make_np_bma_stub()
1946+ c_network_port.restore_speed_mbps_after_bma_stop(p)
1947+ lu.assertEquals(p.SpeedMbps, 4294967295)
1948+end
1949+ 
1950+function TEST_network_port:test_restore_auto_speed_negotiation_after_bma_stop_uses_cache()
1951+ local p = make_np_bma_stub()
1952+ p.t_prop_without_bma.AutoSpeedNegotiation = 2
1953+ c_network_port.restore_auto_speed_negotiation_after_bma_stop(p)
1954+ lu.assertEquals(p.AutoSpeedNegotiation, 2)
1955+end
1956+ 
1957+function TEST_network_port:test_restore_auto_speed_negotiation_after_bma_stop_default_255()
1958+ local p = make_np_bma_stub()
1959+ p.AutoSpeedNegotiation = 1
1960+ c_network_port.restore_auto_speed_negotiation_after_bma_stop(p)
1961+ lu.assertEquals(p.AutoSpeedNegotiation, 255)
1962+end
1963+ 
1964+function TEST_network_port:test_restore_full_duplex_after_bma_stop_uses_cache()
1965+ local p = make_np_bma_stub()
1966+ p.t_prop_without_bma.FullDuplex = 0
1967+ c_network_port.restore_full_duplex_after_bma_stop(p)
1968+ lu.assertEquals(p.FullDuplex, 0)
1969+end
1970+ 
1971+function TEST_network_port:test_restore_full_duplex_after_bma_stop_default_255()
1972+ local p = make_np_bma_stub()
1973+ c_network_port.restore_full_duplex_after_bma_stop(p)
1974+ lu.assertEquals(p.FullDuplex, 255)
1975+end
1976+ 
1977+function TEST_network_port:test_restore_bdf_after_bma_stop_uses_cache()
1978+ local p = make_np_bma_stub()
1979+ p.t_prop_without_bma.BDF = '0000:03:00.0'
1980+ c_network_port.restore_bdf_after_bma_stop(p)
1981+ lu.assertEquals(p.BDF, '0000:03:00.0')
1982+end
1983+ 
1984+function TEST_network_port:test_restore_bdf_after_bma_stop_default_empty()
1985+ local p = make_np_bma_stub()
1986+ c_network_port.restore_bdf_after_bma_stop(p)
1987+ lu.assertEquals(p.BDF, '')
1988+end
1989+ 
1990+function TEST_network_port:test_restore_firmware_version_after_bma_stop_uses_cache()
1991+ local p = make_np_bma_stub()
1992+ p.t_prop_without_bma.FirmwareVersion = 'SR_1.2.3'
1993+ c_network_port.restore_firmware_version_after_bma_stop(p)
1994+ lu.assertEquals(p.FirmwareVersion, 'SR_1.2.3')
1995+end
1996+ 
1997+function TEST_network_port:test_restore_firmware_version_after_bma_stop_default_empty()
1998+ local p = make_np_bma_stub()
1999+ c_network_port.restore_firmware_version_after_bma_stop(p)
2000+ lu.assertEquals(p.FirmwareVersion, '')
2001+end
2002+ 
2003+function TEST_network_port:test_restore_port_prop_without_bma_restores_all_from_cache()
2004+ local p = make_np_bma_stub()
2005+ p.t_prop_without_bma.SpeedMbps = 100
2006+ p.t_prop_without_bma.AutoSpeedNegotiation = 2
2007+ p.t_prop_without_bma.FullDuplex = 3
2008+ p.t_prop_without_bma.BDF = 'bdf_ok'
2009+ p.t_prop_without_bma.FirmwareVersion = 'fw_ok'
2010+ c_network_port.restore_port_prop_without_bma(p)
2011+ lu.assertEquals(p.SpeedMbps, 100)
2012+ lu.assertEquals(p.AutoSpeedNegotiation, 2)
2013+ lu.assertEquals(p.FullDuplex, 3)
2014+ lu.assertEquals(p.BDF, 'bdf_ok')
2015+ lu.assertEquals(p.FirmwareVersion, 'fw_ok')
2016+end
2017+ 
2018+function TEST_network_port:test_reset_bma_info_non_device_object_restores_firmware()
2019+ local p = make_np_bma_stub({ CreatedByDeviceObject = false })
2020+ p.t_prop_without_bma.FirmwareVersion = 'cached_fw'
2021+ p.FirmwareVersion = 'bma_fw'
2022+ c_network_port.reset_bma_info(p)
2023+ lu.assertEquals(p.DriverName, '')
2024+ lu.assertEquals(p.FirmwareVersion, 'cached_fw')
2025+end
2026+ 
2027+function TEST_network_port:test_reset_bma_info_device_object_missing_returns_early()
2028+ local p = make_np_bma_stub({ CreatedByDeviceObject = true })
2029+ p.FirmwareVersion = 'keep_fw'
2030+ local orig_gi = c_object_manage.get_instance
2031+ local orig_gdo = device_comm_fun.get_device_obj_by_path_interface
2032+ c_object_manage.get_instance = function()
2033+ return { bus = {} }
2034+ end
2035+ device_comm_fun.get_device_obj_by_path_interface = function()
2036+ return nil
2037+ end
2038+ c_network_port.reset_bma_info(p)
2039+ lu.assertEquals(p.Name, '')
2040+ lu.assertEquals(p.FirmwareVersion, 'keep_fw')
2041+ c_object_manage.get_instance = orig_gi
2042+ device_comm_fun.get_device_obj_by_path_interface = orig_gdo
2043+end
2044+ 
2045+function TEST_network_port:test_reset_bma_info_device_object_restore_prop_pcall_fail()
2046+ local p = make_np_bma_stub({ CreatedByDeviceObject = true })
2047+ p.FirmwareVersion = 'keep_fw'
2048+ local orig_gi = c_object_manage.get_instance
2049+ local orig_gdo = device_comm_fun.get_device_obj_by_path_interface
2050+ local mock_bus = {}
2051+ c_object_manage.get_instance = function()
2052+ return { bus = mock_bus }
2053+ end
2054+ device_comm_fun.get_device_obj_by_path_interface = function(bus, path, iface)
2055+ lu.assertIs(bus, mock_bus)
2056+ lu.assertEquals(path, p.device_path)
2057+ lu.assertEquals(iface, device_comm_defs.NETWORK_PORT_OEM_INTERFACE)
2058+ return {
2059+ call_method = function()
2060+ error('restore_fail')
2061+ end,
2062+ }
2063+ end
2064+ c_network_port.reset_bma_info(p)
2065+ lu.assertEquals(p.FirmwareVersion, 'keep_fw')
2066+ c_object_manage.get_instance = orig_gi
2067+ device_comm_fun.get_device_obj_by_path_interface = orig_gdo
2068+end
2069+ 
2070+function TEST_network_port:test_reset_bma_info_device_object_restore_prop_ok()
2071+ local restore_called = false
2072+ local p = make_np_bma_stub({ CreatedByDeviceObject = true })
2073+ p.FirmwareVersion = 'keep_fw'
2074+ local orig_gi = c_object_manage.get_instance
2075+ local orig_gdo = device_comm_fun.get_device_obj_by_path_interface
2076+ local mock_bus = {}
2077+ c_object_manage.get_instance = function()
2078+ return { bus = mock_bus }
2079+ end
2080+ device_comm_fun.get_device_obj_by_path_interface = function(bus, path, iface)
2081+ lu.assertIs(bus, mock_bus)
2082+ lu.assertEquals(path, p.device_path)
2083+ lu.assertEquals(iface, device_comm_defs.NETWORK_PORT_OEM_INTERFACE)
2084+ return {
2085+ call_method = function(_, method, sig)
2086+ if method == 'RestorePropAfterBmaStop' and sig == '' then
2087+ restore_called = true
2088+ return true
2089+ end
2090+ return false
2091+ end,
2092+ }
2093+ end
2094+ c_network_port.reset_bma_info(p)
2095+ lu.assertTrue(restore_called)
2096+ lu.assertEquals(p.FirmwareVersion, 'keep_fw')
2097+ c_object_manage.get_instance = orig_gi
2098+ device_comm_fun.get_device_obj_by_path_interface = orig_gdo
2099+end
2100+ 
1902local cnt = 02101local cnt = 0
1903function TEST_network_port:test_update_npu_heartbeat_status()2102function TEST_network_port:test_update_npu_heartbeat_status()
1904 local old_loop = skynet.fork_loop2103 local old_loop = skynet.fork_loop
@@ -19,7 +19,7 @@ logging:setLevel(logging.INFO)
19 19 
20local lu = require('luaunit')20local lu = require('luaunit')
21require 'test_imu'21require 'test_imu'
22--- require 'test_bma'22+require 'test_bma'
23require 'test_network_adapter_debug'23require 'test_network_adapter_debug'
24require 'test_device'24require 'test_device'
25require 'test_network_adapter_ready_to_remove'25require 'test_network_adapter_ready_to_remove'
@@ -10,7 +10,7 @@
10STOP_INIT = true10STOP_INIT = true
11require 'test_bma.test_bma_eth'11require 'test_bma.test_bma_eth'
12require 'test_bma.test_bma_optical'12require 'test_bma.test_bma_optical'
13-require 'test_bma.test_bma_redfish_resource'13+-- require 'test_bma.test_bma_redfish_resource'
14-require 'test_bma.test_bma_dbus_sms'14+-- require 'test_bma.test_bma_dbus_sms'
15-require 'test_bma.test_bma_vlan'15+-- require 'test_bma.test_bma_vlan'
16-require 'test_bma.test_bma_rpc'16+-- require 'test_bma.test_bma_rpc'
@@ -8,310 +8,785 @@
8-- See the Mulan PSL v2 for more details.8-- See the Mulan PSL v2 for more details.
9 9 
10local lu = require 'luaunit'10local lu = require 'luaunit'
11-local c_bma = require 'bma'
12-local test_data = require 'test_datas.bma_nic'
13-local c_network_adapter_db = require 'network_adapter.db'
14-local c_ipv4_address = require 'device.class.ipv4_address'
15-local c_ipv6_address = require 'device.class.ipv6_address'
16-local c_network_bonding = require 'device.class.network_bonding'
17-local hook_tasks = require 'test_common.hook_tasks'
18-local c_object_manage = require 'mc.orm.object_manage'
19-local c_tasks = require 'mc.orm.tasks'
20-local test_utils = require 'test_utils'
21local json = require 'cjson'11local json = require 'cjson'
22-local client = require 'network_adapter.client'12+local c_handler_eth = require 'bma.handles.handler_eth'
13+local c_network_adapter = require 'device.class.network_adapter'
14+local card_mgmt = require 'device.class.nic_mgmt.card_mgmt'
15+local port_mgmt = require 'device.class.nic_mgmt.port_mgmt'
16+local log = require 'mc.logging'
17+-- local c_bma = require 'bma'
18+-- local test_data = require 'test_datas.bma_nic'
19+-- local c_network_adapter_db = require 'network_adapter.db'
20+-- local c_ipv4_address = require 'device.class.ipv4_address'
21+-- local c_ipv6_address = require 'device.class.ipv6_address'
22+-- local c_network_bonding = require 'device.class.network_bonding'
23+-- local hook_tasks = require 'test_common.hook_tasks'
24+-- local c_object_manage = require 'mc.orm.object_manage'
25+-- local c_tasks = require 'mc.orm.tasks'
26+-- local test_utils = require 'test_utils'
27+-- local json = require 'cjson'
28+-- local client = require 'network_adapter.client'
23 29 
24-local ipv4_obj = test_utils.ipv4_obj30+-- local ipv4_obj = test_utils.ipv4_obj
25-local ipv6_obj = test_utils.ipv6_obj31+-- local ipv6_obj = test_utils.ipv6_obj
26-local find_address = test_utils.find_address32+-- local find_address = test_utils.find_address
27 33 
28TEST_bma_eth = {}34TEST_bma_eth = {}
29 35 
30-function TEST_bma_eth:setUp()36+-- function TEST_bma_eth:setUp()
31- client.OnDPUCardInterfacesAdded = function()37+-- client.OnDPUCardInterfacesAdded = function()
32- return {}38+-- return {}
33- end39+-- end
34- client.ForeachDPUCardObjects = function()40+-- client.ForeachDPUCardObjects = function()
35- return {}41+-- return {}
36- end42+-- end
37- self.database = c_network_adapter_db(':memory:')43+-- self.database = c_network_adapter_db(':memory:')
38 44 
39- hook_tasks.hook()45+-- hook_tasks.hook()
40- self.object_manage = c_object_manage.new(self.database)46+-- self.object_manage = c_object_manage.new(self.database)
41- self.object_manage.app = self47+-- self.object_manage.app = self
42 48 
43- self.bma = c_bma.new()49+-- self.bma = c_bma.new()
44 50 
45- local position = '00010102'51+-- local position = '00010102'
46- self.network_adapter_obj = test_utils.add_network_adapter(self.object_manage,52+-- self.network_adapter_obj = test_utils.add_network_adapter(self.object_manage,
47- 'NetworkAdapter_1', {53+-- 'NetworkAdapter_1', {
48- BoardID = 0x123,54+-- BoardID = 0x123,
49- DeviceLocator = 'some locator',55+-- DeviceLocator = 'some locator',
50- Position = 'position',56+-- Position = 'position',
51- Type = 'Physical',57+-- Type = 'Physical',
52- Model = 'MyMode',58+-- Model = 'MyMode',
53- Name = "a network card",59+-- Name = "a network card",
54- Bus = 0xbc,60+-- Bus = 0xbc,
55- Device = 0,61+-- Device = 0,
56- Function = 0,62+-- Function = 0,
57- DevBus = 0xbc,63+-- DevBus = 0xbc,
58- DevDevice = 0,64+-- DevDevice = 0,
59- DevFunction = 1,65+-- DevFunction = 1,
60- SpecialPcieCard = true66+-- SpecialPcieCard = true
61- }, position)67+-- }, position)
62- self.network_port_obj = test_utils.add_network_port(self.object_manage, 'NetworkPort_1',68+-- self.network_port_obj = test_utils.add_network_port(self.object_manage, 'NetworkPort_1',
63- {PortID = 0, NetDevFuncType = 1}, position, self.network_adapter_obj)69+-- {PortID = 0, NetDevFuncType = 1}, position, self.network_adapter_obj)
64- test_utils.add_object_complete(self.object_manage, position)70+-- test_utils.add_object_complete(self.object_manage, position)
65 71 
66- self.object_manage.mc:prepare_ok()72+-- self.object_manage.mc:prepare_ok()
67 73 
68- local eth_data = json.decode(test_data.EthernetInterface)74+-- local eth_data = json.decode(test_data.EthernetInterface)
69- self.url = eth_data['@odata.id']75+-- self.url = eth_data['@odata.id']
70-end76+-- end
71 77 
72-function TEST_bma_eth:CreateVLANs()78+-- function TEST_bma_eth:CreateVLANs()
73-end79+-- end
74 80 
75-function TEST_bma_eth:tearDown()81+-- function TEST_bma_eth:tearDown()
76- c_bma.destroy()82+-- c_bma.destroy()
77- c_object_manage.destroy()83+-- c_object_manage.destroy()
78- self.database.db:close()84+-- self.database.db:close()
79- hook_tasks.unhook()85+-- hook_tasks.unhook()
80-end86+-- end
81 87 
82-function TEST_bma_eth:CreateIPv4Address(SystemID, ID1, ID2, ID3, prop_setting_cb)88+-- function TEST_bma_eth:CreateIPv4Address(SystemID, ID1, ID2, ID3, prop_setting_cb)
83- return test_utils.CreateIPv4Address(SystemID, ID1, ID2, ID3, prop_setting_cb)89+-- return test_utils.CreateIPv4Address(SystemID, ID1, ID2, ID3, prop_setting_cb)
84-end90+-- end
85 91 
86-function TEST_bma_eth:CreateIPv6Address(SystemID, ID1, ID2, ID3, prop_setting_cb)92+-- function TEST_bma_eth:CreateIPv6Address(SystemID, ID1, ID2, ID3, prop_setting_cb)
87- return test_utils.CreateIPv6Address(SystemID, ID1, ID2, ID3, prop_setting_cb)93+-- return test_utils.CreateIPv6Address(SystemID, ID1, ID2, ID3, prop_setting_cb)
88-end94+-- end
89 95 
90-function TEST_bma_eth:test_bma_update_eth()96+-- function TEST_bma_eth:test_bma_update_eth()
91- local na = self.network_adapter_obj97+-- local na = self.network_adapter_obj
92- local np = self.network_port_obj98+-- local np = self.network_port_obj
93- local data = json.decode(test_data.EthernetInterface)99+-- local data = json.decode(test_data.EthernetInterface)
94- local huawei = data.Oem.Huawei100+-- local huawei = data.Oem.Huawei
95 101 
96- self.bma:add(self.url, data)102+-- self.bma:add(self.url, data)
97 103 
98- lu.assertEquals(na.Model, 'MyMode') -- Model 以 sr 配置为准,除非 sr 中没有配置104+-- lu.assertEquals(na.Model, 'MyMode') -- Model 以 sr 配置为准,除非 sr 中没有配置
99- lu.assertEquals(na.Manufacturer, data.Manufacturer) -- Manufacturer 以 sr 配置为准,除非 sr 中没有配置105+-- lu.assertEquals(na.Manufacturer, data.Manufacturer) -- Manufacturer 以 sr 配置为准,除非 sr 中没有配置
100- lu.assertEquals(na.DisplayName, huawei.NICName)106+-- lu.assertEquals(na.DisplayName, huawei.NICName)
101- lu.assertEquals(na.FirmwareVersion, huawei.FirmwareVersion)107+-- lu.assertEquals(na.FirmwareVersion, huawei.FirmwareVersion)
102- lu.assertEquals(na.DriverName, huawei.DriverInfo.DriverName)108+-- lu.assertEquals(na.DriverName, huawei.DriverInfo.DriverName)
103- lu.assertEquals(na.DriverVersion, huawei.DriverInfo.DriverVersion)109+-- lu.assertEquals(na.DriverVersion, huawei.DriverInfo.DriverVersion)
104- lu.assertEquals(na.Description, data.Description)110+-- lu.assertEquals(na.Description, data.Description)
105- lu.assertEquals(na.RootBDF, huawei.BDFNumber.RootBDF)111+-- lu.assertEquals(na.RootBDF, huawei.BDFNumber.RootBDF)
106 112 
107- lu.assertEquals(np.Name, huawei.NICName)113+-- lu.assertEquals(np.Name, huawei.NICName)
108- lu.assertEquals(np.MACAddress, string.upper(data.MACAddress))114+-- lu.assertEquals(np.MACAddress, string.upper(data.MACAddress))
109- lu.assertEquals(np.BDF, huawei.BDFNumber.BDF)115+-- lu.assertEquals(np.BDF, huawei.BDFNumber.BDF)
110- lu.assertEquals(np.DriverName, huawei.DriverInfo.DriverName)116+-- lu.assertEquals(np.DriverName, huawei.DriverInfo.DriverName)
111- lu.assertEquals(np.DriverVersion, huawei.DriverInfo.DriverVersion)117+-- lu.assertEquals(np.DriverVersion, huawei.DriverInfo.DriverVersion)
112 118 
113- local ipv4_addrs = c_ipv4_address.get_addresses()119+-- local ipv4_addrs = c_ipv4_address.get_addresses()
114- lu.assertEquals(#ipv4_addrs, #data.IPv4Addresses)120+-- lu.assertEquals(#ipv4_addrs, #data.IPv4Addresses)
115- for _, v in ipairs(ipv4_addrs) do121+-- for _, v in ipairs(ipv4_addrs) do
116- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))122+-- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))
117- end123+-- end
118 124 
119- local ipv6_addrs = c_ipv6_address.get_addresses()125+-- local ipv6_addrs = c_ipv6_address.get_addresses()
120- lu.assertEquals(#ipv6_addrs, #data.IPv6Addresses)126+-- lu.assertEquals(#ipv6_addrs, #data.IPv6Addresses)
121- for _, v in ipairs(ipv6_addrs) do127+-- for _, v in ipairs(ipv6_addrs) do
122- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))128+-- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))
129+-- end
130+-- end
131+ 
132+-- function TEST_bma_eth:test_bma_update_ipv4_address()
133+-- local data = json.decode(test_data.EthernetInterface)
134+ 
135+-- -- 装入初始化测试数据
136+-- self.bma:add(self.url, data)
137+-- local old_ipv4_addrs = c_ipv4_address.get_addresses()
138+ 
139+-- -- 修改旧的 ipv4 地址信息
140+-- data.IPv4Addresses[1].SubnetMask = '0.0.0.1'
141+-- -- 再插入一个新 ipv4 地址
142+-- data.IPv4Addresses[#data.IPv4Addresses + 1] = {
143+-- Address = '127.0.0.0',
144+-- AddressOrigin = 'Static',
145+-- Gateway = {'196.128.0.0'},
146+-- SubnetMask = '0.0.0.0'
147+-- }
148+-- self.bma:add(self.url, data)
149+ 
150+-- local new_ipv4_addrs = c_ipv4_address.get_addresses()
151+-- lu.assertEquals(#new_ipv4_addrs, #old_ipv4_addrs + 1)
152+-- for _, v in ipairs(new_ipv4_addrs) do
153+-- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))
154+-- end
155+ 
156+-- -- 删除第一个地址
157+-- table.remove(data.IPv4Addresses, 1)
158+-- self.bma:add(self.url, data)
159+-- local last_ipv4_addrs = c_ipv4_address.get_addresses()
160+-- lu.assertEquals(#last_ipv4_addrs, #new_ipv4_addrs - 1)
161+-- for _, v in ipairs(last_ipv4_addrs) do
162+-- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))
163+-- end
164+ 
165+-- -- 清空地址
166+-- data.IPv4Addresses = {}
167+-- self.bma:add(self.url, data)
168+-- lu.assertEquals(c_ipv4_address.get_addresses(), {})
169+-- end
170+ 
171+-- function TEST_bma_eth:test_bma_add_and_update_ipv4_address()
172+-- local data = json.decode(test_data.EthernetInterface)
173+ 
174+-- -- 装入初始化测试数据
175+-- self.bma:add(self.url, data)
176+-- local old_ipv4_addrs = c_ipv4_address.get_addresses()
177+ 
178+-- -- 部分更新,new_data 仅包含要更新的信息
179+-- local new_data = {IPv4Addresses = test_utils.table_clone(data.IPv4Addresses)}
180+-- new_data.IPv4Addresses[1].SubnetMask = '0.0.0.1'
181+-- new_data.IPv4Addresses[#new_data.IPv4Addresses + 1] = {
182+-- Address = '127.0.0.0',
183+-- AddressOrigin = 'Static',
184+-- Gateway = {'196.128.0.0'},
185+-- SubnetMask = '0.0.0.0'
186+-- }
187+-- self.bma:update(self.url, new_data)
188+ 
189+-- local new_ipv4_addrs = c_ipv4_address.get_addresses()
190+-- lu.assertEquals(#new_ipv4_addrs, #old_ipv4_addrs + 1)
191+-- for _, v in ipairs(new_ipv4_addrs) do
192+-- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(new_data.IPv4Addresses, v.Address)))
193+-- end
194+ 
195+-- -- 删除第一个地址
196+-- table.remove(new_data.IPv4Addresses, 1)
197+-- self.bma:update(self.url, new_data)
198+-- local last_ipv4_addrs = c_ipv4_address.get_addresses()
199+-- lu.assertEquals(#last_ipv4_addrs, #new_ipv4_addrs - 1)
200+-- for _, v in ipairs(last_ipv4_addrs) do
201+-- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(new_data.IPv4Addresses, v.Address)))
202+-- end
203+ 
204+-- -- 清空地址
205+-- new_data.IPv4Addresses = {}
206+-- self.bma:update(self.url, new_data)
207+-- lu.assertEquals(c_ipv4_address.get_addresses(), {})
208+-- end
209+ 
210+-- function TEST_bma_eth:test_bma_update_ipv6_address()
211+-- local data = json.decode(test_data.EthernetInterface)
212+ 
213+-- -- 装入初始化测试数据
214+-- self.bma:add(self.url, data)
215+-- local old_ipv6_addrs = c_ipv6_address.get_addresses()
216+ 
217+-- -- 修改旧的 ipv6 地址信息
218+-- data.IPv6Addresses[1].PrefixLength = '128'
219+-- -- 再插入一个新 ipv6 地址
220+-- data.IPv6Addresses[#data.IPv6Addresses + 1] = {
221+-- Address = '8888:1871:1:0:f40:3935:cf5c:aaaa',
222+-- AddressOrigin = 'SLAAC',
223+-- AddressState = 'Deprecated',
224+-- PrefixLength = '64'
225+-- }
226+-- self.bma:add(self.url, data)
227+ 
228+-- local new_ipv6_addrs = c_ipv6_address.get_addresses()
229+-- lu.assertEquals(#new_ipv6_addrs, #old_ipv6_addrs + 1)
230+-- for _, v in ipairs(new_ipv6_addrs) do
231+-- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))
232+-- end
233+ 
234+-- -- 删除第一个地址
235+-- table.remove(data.IPv6Addresses, 1)
236+-- self.bma:add(self.url, data)
237+-- local last_ipv6_addrs = c_ipv6_address.get_addresses()
238+-- lu.assertEquals(#last_ipv6_addrs, #new_ipv6_addrs - 1)
239+-- for _, v in ipairs(last_ipv6_addrs) do
240+-- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))
241+-- end
242+ 
243+-- -- 清空地址
244+-- data.IPv6Addresses = {}
245+-- self.bma:add(self.url, data)
246+-- lu.assertEquals(c_ipv6_address.get_addresses(), {})
247+-- end
248+ 
249+-- function TEST_bma_eth:test_bma_add_team()
250+-- local data = json.decode(test_data.Team)
251+-- local url = data['@odata.id']
252+-- -- 装入初始化测试数据
253+-- self.bma:add(url, data)
254+-- local team_objs = c_network_bonding.collection:fetch({Id = 'team00'})
255+-- for _, v in pairs(team_objs) do
256+-- lu.assertEquals(v.Name, 'teamA')
257+-- end
258+-- -- ports更新测试
259+-- data['Ports'] = {'eno1'}
260+-- self.bma:add(url, data)
261+-- team_objs = c_network_bonding.collection:fetch({Id = 'team00'})
262+-- for _, v in pairs(team_objs) do
263+-- lu.assertEquals(v.Ports[1], 'eno1')
264+-- end
265+-- end
266+ 
267+-- function TEST_bma_eth:test_bma_reset_eth()
268+-- local na = self.network_adapter_obj
269+-- local np = self.network_port_obj
270+-- local data = json.decode(test_data.EthernetInterface)
271+-- local huawei = data.Oem.Huawei
272+ 
273+-- self.bma:add(self.url, data)
274+-- self.bma:on_reset()
275+ 
276+-- lu.assertEquals(na.DisplayName, '')
277+-- lu.assertEquals(na.FirmwareVersion, '')
278+-- lu.assertEquals(na.DriverName, '')
279+-- lu.assertEquals(na.DriverVersion, '')
280+-- lu.assertEquals(na.RootBDF, huawei.BDFNumber.RootBDF)
281+ 
282+-- lu.assertEquals(np.Name, '')
283+-- lu.assertEquals(np.OSLinkStatus, '')
284+-- lu.assertEquals(np.MACAddress, string.upper(data.MACAddress))
285+-- lu.assertEquals(np.BDF, huawei.BDFNumber.BDF)
286+-- lu.assertEquals(np.DriverName, '')
287+-- lu.assertEquals(np.DriverVersion, '')
288+ 
289+-- local ipv4_addrs = c_ipv4_address.get_addresses()
290+-- lu.assertEquals(#ipv4_addrs, 0)
291+-- local ipv6_addrs = c_ipv6_address.get_addresses()
292+-- lu.assertEquals(#ipv6_addrs, 0)
293+-- end
294+ 
295+-- function TEST_bma_eth:test_bma_update_speed_mbps_with_null()
296+-- local np = self.network_port_obj
297+-- local data = json.decode(test_data.EthernetInterface)
298+ 
299+-- -- 测试正常的 SpeedMbps 值
300+-- data.SpeedMbps = 1000
301+-- self.bma:add(self.url, data)
302+-- lu.assertEquals(np.SpeedMbps, 1000)
303+ 
304+-- -- 测试 SpeedMbps 为 json.null 时,应该设置为 4294967295
305+-- data.SpeedMbps = json.null
306+-- self.bma:add(self.url, data)
307+-- lu.assertEquals(np.SpeedMbps, 4294967295)
308+ 
309+-- -- 测试 SpeedMbps 从 json.null 恢复为有效值
310+-- data.SpeedMbps = 10000
311+-- self.bma:add(self.url, data)
312+-- lu.assertEquals(np.SpeedMbps, 10000)
313+ 
314+-- -- 测试 SpeedMbps 为 0 的情况
315+-- data.SpeedMbps = 0
316+-- self.bma:add(self.url, data)
317+-- lu.assertEquals(np.SpeedMbps, 0)
318+ 
319+-- -- 再次测试 json.null 确保逻辑稳定
320+-- data.SpeedMbps = json.null
321+-- self.bma:add(self.url, data)
322+-- lu.assertEquals(np.SpeedMbps, 4294967295)
323+-- end
324+ 
325+-- 覆盖 handler_eth.update_firmware_version_from_bma(经 update_network_card 调用)
326+local ETH_VIR_TYPE<const> = 6 -- 与 handler_eth.BUSINESSPORT_CARD_TYPE_VIR 一致
327+local NA<const> = 'N/A'
328+ 
329+local function stub_log_quiet()
330+ local saved_info, saved_error = log.info, log.error
331+ log.info = function() end
332+ log.error = function() end
333+ return function()
334+ log.info = saved_info
335+ log.error = saved_error
123 end336 end
124end337end
125 338 
126-function TEST_bma_eth:test_bma_update_ipv4_address()339+--- 构造最小 port / na / data,使 update_network_card 走到 update_firmware_version_from_bma
127- local data = json.decode(test_data.EthernetInterface)340+local function make_port_and_na(na_fw_initial)
128- 341+ local na = {
129- -- 装入初始化测试数据342+ NodeId = 'ut_na_1',
130- self.bma:add(self.url, data)343+ path = '/ut/na',
131- local old_ipv4_addrs = c_ipv4_address.get_addresses()344+ FirmwareVersion = na_fw_initial,
132- 345+ Model = 'ut_model_locked',
133- -- 修改旧的 ipv4 地址信息346+ Manufacturer = 'ut_mfr_locked',
134- data.IPv4Addresses[1].SubnetMask = '0.0.0.1'347+ DisplayName = 'ut_display',
135- -- 再插入一个新 ipv4 地址348+ DriverName = 'ut_drv',
136- data.IPv4Addresses[#data.IPv4Addresses + 1] = {349+ DriverVersion = 'ut_drv_ver',
137- Address = '127.0.0.0',350+ Description = 'ut_desc',
138- AddressOrigin = 'Static',351+ RootBDF = '0000:00:00.0',
139- Gateway = {'196.128.0.0'},
140- SubnetMask = '0.0.0.0'
141 }352 }
142- self.bma:add(self.url, data)353+ local port = {
143- 354+ Type = 0,
144- local new_ipv4_addrs = c_ipv4_address.get_addresses()355+ WorkloadType = 0,
145- lu.assertEquals(#new_ipv4_addrs, #old_ipv4_addrs + 1)356+ path = '/ut/port',
146- for _, v in ipairs(new_ipv4_addrs) do357+ CreatedByDeviceObject = false,
147- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))358+ get_parent = function()
148- end359+ return { NodeId = 'ut_na_1' }
149- 360+ end,
150- -- 删除第一个地址
151- table.remove(data.IPv4Addresses, 1)
152- self.bma:add(self.url, data)
153- local last_ipv4_addrs = c_ipv4_address.get_addresses()
154- lu.assertEquals(#last_ipv4_addrs, #new_ipv4_addrs - 1)
155- for _, v in ipairs(last_ipv4_addrs) do
156- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(data.IPv4Addresses, v.Address)))
157- end
158- 
159- -- 清空地址
160- data.IPv4Addresses = {}
161- self.bma:add(self.url, data)
162- lu.assertEquals(c_ipv4_address.get_addresses(), {})
163-end
164- 
165-function TEST_bma_eth:test_bma_add_and_update_ipv4_address()
166- local data = json.decode(test_data.EthernetInterface)
167- 
168- -- 装入初始化测试数据
169- self.bma:add(self.url, data)
170- local old_ipv4_addrs = c_ipv4_address.get_addresses()
171- 
172- -- 部分更新,new_data 仅包含要更新的信息
173- local new_data = {IPv4Addresses = test_utils.table_clone(data.IPv4Addresses)}
174- new_data.IPv4Addresses[1].SubnetMask = '0.0.0.1'
175- new_data.IPv4Addresses[#new_data.IPv4Addresses + 1] = {
176- Address = '127.0.0.0',
177- AddressOrigin = 'Static',
178- Gateway = {'196.128.0.0'},
179- SubnetMask = '0.0.0.0'
180 }361 }
181- self.bma:update(self.url, new_data)362+ local data = { ['@odata.id'] = '/redfish/v1/ut/EthernetInterfaces/0' }
182- 363+ return port, na, data
183- local new_ipv4_addrs = c_ipv4_address.get_addresses()
184- lu.assertEquals(#new_ipv4_addrs, #old_ipv4_addrs + 1)
185- for _, v in ipairs(new_ipv4_addrs) do
186- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(new_data.IPv4Addresses, v.Address)))
187- end
188- 
189- -- 删除第一个地址
190- table.remove(new_data.IPv4Addresses, 1)
191- self.bma:update(self.url, new_data)
192- local last_ipv4_addrs = c_ipv4_address.get_addresses()
193- lu.assertEquals(#last_ipv4_addrs, #new_ipv4_addrs - 1)
194- for _, v in ipairs(last_ipv4_addrs) do
195- lu.assertEquals(ipv4_obj(v), ipv4_obj(find_address(new_data.IPv4Addresses, v.Address)))
196- end
197- 
198- -- 清空地址
199- new_data.IPv4Addresses = {}
200- self.bma:update(self.url, new_data)
201- lu.assertEquals(c_ipv4_address.get_addresses(), {})
202end364end
203 365 
204-function TEST_bma_eth:test_bma_update_ipv6_address()366+function TEST_bma_eth:test_update_firmware_version_from_bma_early_return_when_nil()
205- local data = json.decode(test_data.EthernetInterface)367+ local port, na, data = make_port_and_na('must_keep')
368+ local oem_huawei = { FirmwareVersion = nil, NICName = 'n' }
206 369 
207- -- 装入初始化测试数据370+ local orig_find = c_network_adapter.collection.find
208- self.bma:add(self.url, data)371+ local orig_gi = card_mgmt.get_instance
209- local old_ipv6_addrs = c_ipv6_address.get_addresses()372+ local restore_log = stub_log_quiet()
373+ c_network_adapter.collection.find = function(_)
374+ return na
375+ end
376+ card_mgmt.get_instance = function()
377+ error('should not call card_mgmt when FirmwareVersion is nil')
378+ end
210 379 
211- -- 修改旧的 ipv6 地址信息380+ c_handler_eth:update_network_card(port, data, oem_huawei)
212- data.IPv6Addresses[1].PrefixLength = '128'381+ 
213- -- 再插入一个新 ipv6 地址382+ lu.assertEquals(na.FirmwareVersion, 'must_keep')
214- data.IPv6Addresses[#data.IPv6Addresses + 1] = {383+ c_network_adapter.collection.find = orig_find
215- Address = '8888:1871:1:0:f40:3935:cf5c:aaaa',384+ card_mgmt.get_instance = orig_gi
216- AddressOrigin = 'SLAAC',385+ restore_log()
217- AddressState = 'Deprecated',386+end
218- PrefixLength = '64'387+ 
388+function TEST_bma_eth:test_update_firmware_version_from_bma_sets_fw_and_calls_device_sync()
389+ local port, na, data = make_port_and_na('')
390+ local oem_huawei = { FirmwareVersion = 'BMA_FW_9.9', NICName = 'n' }
391+ local sync_calls = {}
392+ 
393+ local orig_find = c_network_adapter.collection.find
394+ local orig_gi = card_mgmt.get_instance
395+ local restore_log = stub_log_quiet()
396+ c_network_adapter.collection.find = function(_)
397+ return na
398+ end
399+ card_mgmt.get_instance = function()
400+ return {
401+ update_firmware_version_to_device_obj = function(_, na_arg, ver)
402+ sync_calls[#sync_calls + 1] = { na_arg = na_arg, ver = ver }
403+ end,
404+ }
405+ end
406+ 
407+ c_handler_eth:update_network_card(port, data, oem_huawei)
408+ 
409+ lu.assertEquals(na.FirmwareVersion, 'BMA_FW_9.9')
410+ lu.assertEquals(#sync_calls, 1)
411+ lu.assertIs(sync_calls[1].na_arg, na)
412+ lu.assertEquals(sync_calls[1].ver, 'BMA_FW_9.9')
413+ 
414+ c_network_adapter.collection.find = orig_find
415+ card_mgmt.get_instance = orig_gi
416+ restore_log()
417+end
418+ 
419+function TEST_bma_eth:test_update_firmware_version_from_bma_keeps_existing_configured_fw()
420+ local port, na, data = make_port_and_na('already_from_sr')
421+ local oem_huawei = { FirmwareVersion = 'BMA_SHOULD_NOT_REPLACE', NICName = 'n' }
422+ local sync_calls = {}
423+ 
424+ local orig_find = c_network_adapter.collection.find
425+ local orig_gi = card_mgmt.get_instance
426+ local restore_log = stub_log_quiet()
427+ c_network_adapter.collection.find = function(_)
428+ return na
429+ end
430+ card_mgmt.get_instance = function()
431+ return {
432+ update_firmware_version_to_device_obj = function(_, _, ver)
433+ sync_calls[#sync_calls + 1] = ver
434+ end,
435+ }
436+ end
437+ 
438+ c_handler_eth:update_network_card(port, data, oem_huawei)
439+ 
440+ lu.assertEquals(na.FirmwareVersion, 'already_from_sr')
441+ lu.assertEquals(#sync_calls, 1)
442+ lu.assertEquals(sync_calls[1], 'already_from_sr')
443+ 
444+ c_network_adapter.collection.find = orig_find
445+ card_mgmt.get_instance = orig_gi
446+ restore_log()
447+end
448+ 
449+function TEST_bma_eth:test_update_firmware_version_from_bma_json_null_maps_to_na()
450+ local port, na, data = make_port_and_na('')
451+ local oem_huawei = { FirmwareVersion = json.null, NICName = 'n' }
452+ local sync_calls = {}
453+ 
454+ local orig_find = c_network_adapter.collection.find
455+ local orig_gi = card_mgmt.get_instance
456+ local restore_log = stub_log_quiet()
457+ c_network_adapter.collection.find = function(_)
458+ return na
459+ end
460+ card_mgmt.get_instance = function()
461+ return {
462+ update_firmware_version_to_device_obj = function(_, _, ver)
463+ sync_calls[#sync_calls + 1] = ver
464+ end,
465+ }
466+ end
467+ 
468+ c_handler_eth:update_network_card(port, data, oem_huawei)
469+ 
470+ lu.assertEquals(na.FirmwareVersion, NA)
471+ lu.assertEquals(#sync_calls, 1)
472+ lu.assertEquals(sync_calls[1], NA)
473+ 
474+ c_network_adapter.collection.find = orig_find
475+ card_mgmt.get_instance = orig_gi
476+ restore_log()
477+end
478+ 
479+function TEST_bma_eth:test_update_firmware_version_from_bma_pcall_swallows_card_mgmt_error()
480+ local port, na, data = make_port_and_na('')
481+ local oem_huawei = { FirmwareVersion = 'FW_OK', NICName = 'n' }
482+ 
483+ local orig_find = c_network_adapter.collection.find
484+ local orig_gi = card_mgmt.get_instance
485+ local restore_log = stub_log_quiet()
486+ c_network_adapter.collection.find = function(_)
487+ return na
488+ end
489+ card_mgmt.get_instance = function()
490+ return {
491+ update_firmware_version_to_device_obj = function()
492+ error('dbus down')
493+ end,
494+ }
495+ end
496+ 
497+ local ok = pcall(function()
498+ c_handler_eth:update_network_card(port, data, oem_huawei)
499+ end)
500+ lu.assertTrue(ok)
501+ lu.assertEquals(na.FirmwareVersion, 'FW_OK')
502+ 
503+ c_network_adapter.collection.find = orig_find
504+ card_mgmt.get_instance = orig_gi
505+ restore_log()
506+end
507+ 
508+function TEST_bma_eth:test_update_network_card_skips_virtual_and_workload()
509+ local na = { NodeId = 'x', FirmwareVersion = '', Model = 'm', Manufacturer = 'mf' }
510+ local data = { ['@odata.id'] = '/x' }
511+ local oem_huawei = { FirmwareVersion = 'FW', NICName = 'n' }
512+ local touched = false
513+ 
514+ local orig_find = c_network_adapter.collection.find
515+ local orig_gi = card_mgmt.get_instance
516+ local restore_log = stub_log_quiet()
517+ c_network_adapter.collection.find = function()
518+ touched = true
519+ return na
520+ end
521+ card_mgmt.get_instance = function()
522+ error('should not run')
523+ end
524+ 
525+ local port_vir = {
526+ Type = ETH_VIR_TYPE,
527+ WorkloadType = 0,
528+ path = '/v',
529+ get_parent = function() return { NodeId = 'x' } end,
219 }530 }
220- self.bma:add(self.url, data)531+ c_handler_eth:update_network_card(port_vir, data, oem_huawei)
532+ lu.assertFalse(touched)
221 533 
222- local new_ipv6_addrs = c_ipv6_address.get_addresses()534+ local port_wl = {
223- lu.assertEquals(#new_ipv6_addrs, #old_ipv6_addrs + 1)535+ Type = 0,
224- for _, v in ipairs(new_ipv6_addrs) do536+ WorkloadType = 1,
225- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))537+ path = '/w',
226- end538+ get_parent = function() return { NodeId = 'x' } end,
539+ }
540+ c_handler_eth:update_network_card(port_wl, data, oem_huawei)
541+ lu.assertFalse(touched)
227 542 
228- -- 删除第一个地址543+ c_network_adapter.collection.find = orig_find
229- table.remove(data.IPv6Addresses, 1)544+ card_mgmt.get_instance = orig_gi
230- self.bma:add(self.url, data)545+ restore_log()
231- local last_ipv6_addrs = c_ipv6_address.get_addresses()
232- lu.assertEquals(#last_ipv6_addrs, #new_ipv6_addrs - 1)
233- for _, v in ipairs(last_ipv6_addrs) do
234- lu.assertEquals(ipv6_obj(v), ipv6_obj(find_address(data.IPv6Addresses, v.Address)))
235- end
236- 
237- -- 清空地址
238- data.IPv6Addresses = {}
239- self.bma:add(self.url, data)
240- lu.assertEquals(c_ipv6_address.get_addresses(), {})
241end546end
242 547 
243-function TEST_bma_eth:test_bma_add_team()548+-- 覆盖 update_full_duplex_from_bma / update_speed_mbps_from_bma / update_auto_negotiation_from_bma
244- local data = json.decode(test_data.Team)549+local function make_minimal_network_port()
245- local url = data['@odata.id']550+ return {
246- -- 装入初始化测试数据551+ path = '/ut/np',
247- self.bma:add(url, data)552+ Name = 'eno_ut',
248- local team_objs = c_network_bonding.collection:fetch({Id = 'team00'})553+ NetDevFuncType = 1,
249- for _, v in pairs(team_objs) do554+ WorkloadType = 0,
250- lu.assertEquals(v.Name, 'teamA')555+ PortID = 0,
251- end556+ NetworkAdapterId = 'ut_na',
252- -- ports更新测试557+ na_object_name = 'na_o',
253- data['Ports'] = {'eno1'}558+ np_object_name = 'np_o',
254- self.bma:add(url, data)559+ FullDuplex = 0,
255- team_objs = c_network_bonding.collection:fetch({Id = 'team00'})560+ SpeedMbps = 100,
256- for _, v in pairs(team_objs) do561+ AutoSpeedNegotiation = 0,
257- lu.assertEquals(v.Ports[1], 'eno1')562+ OSLinkStatus = 'N/A',
563+ set_link_status_numeric = function() end,
564+ update_ipv6_default_gateway = function() end,
565+ }
566+end
567+ 
568+local function stub_update_network_port_collateral()
569+ local saved = {
570+ bridge = c_handler_eth.update_physical_port_to_bridge_and_bonding,
571+ ip = c_handler_eth.update_ip_addresses,
572+ bdf = c_handler_eth.update_network_port_bdf,
573+ }
574+ c_handler_eth.update_physical_port_to_bridge_and_bonding = function() end
575+ c_handler_eth.update_ip_addresses = function() end
576+ c_handler_eth.update_network_port_bdf = function() end
577+ return function()
578+ c_handler_eth.update_physical_port_to_bridge_and_bonding = saved.bridge
579+ c_handler_eth.update_ip_addresses = saved.ip
580+ c_handler_eth.update_network_port_bdf = saved.bdf
258 end581 end
259end582end
260 583 
261-function TEST_bma_eth:test_bma_reset_eth()584+local function new_port_mgmt_recorder()
262- local na = self.network_adapter_obj585+ local rec = { duplex = {}, speed = {}, autoneg = {} }
263- local np = self.network_port_obj586+ local mgr = {
264- local data = json.decode(test_data.EthernetInterface)587+ set_link_status_to_device_obj = function() end,
265- local huawei = data.Oem.Huawei588+ update_bdf_to_device_obj = function() end,
266- 589+ update_full_duplex_to_device_obj = function(_, p, v)
267- self.bma:add(self.url, data)590+ rec.duplex[#rec.duplex + 1] = { port = p, val = v }
268- self.bma:on_reset()591+ end,
269- 592+ update_speed_mbps_to_device_obj = function(_, p, v)
270- lu.assertEquals(na.DisplayName, '')593+ rec.speed[#rec.speed + 1] = { port = p, val = v }
271- lu.assertEquals(na.FirmwareVersion, '')594+ end,
272- lu.assertEquals(na.DriverName, '')595+ update_auto_negotiation_to_device_obj = function(_, p, v)
273- lu.assertEquals(na.DriverVersion, '')596+ rec.autoneg[#rec.autoneg + 1] = { port = p, val = v }
274- lu.assertEquals(na.RootBDF, huawei.BDFNumber.RootBDF)597+ end,
275- 598+ }
276- lu.assertEquals(np.Name, '')599+ return mgr, rec
277- lu.assertEquals(np.OSLinkStatus, '')
278- lu.assertEquals(np.MACAddress, string.upper(data.MACAddress))
279- lu.assertEquals(np.BDF, huawei.BDFNumber.BDF)
280- lu.assertEquals(np.DriverName, '')
281- lu.assertEquals(np.DriverVersion, '')
282- 
283- local ipv4_addrs = c_ipv4_address.get_addresses()
284- lu.assertEquals(#ipv4_addrs, 0)
285- local ipv6_addrs = c_ipv6_address.get_addresses()
286- lu.assertEquals(#ipv6_addrs, 0)
287end600end
288 601 
289-function TEST_bma_eth:test_bma_update_speed_mbps_with_null()602+local function run_update_network_port(port, data, oem_huawei, recorder_factory)
290- local np = self.network_port_obj603+ local orig_pm = port_mgmt.get_instance
291- local data = json.decode(test_data.EthernetInterface)604+ local restore_collateral = stub_update_network_port_collateral()
292- 605+ local restore_log = stub_log_quiet()
293- -- 测试正常的 SpeedMbps 606+ local mgr, rec = recorder_factory()
294- data.SpeedMbps = 1000607+ port_mgmt.get_instance = function()
295- self.bma:add(self.url, data)608+ return mgr
296- lu.assertEquals(np.SpeedMbps, 1000)609+ end
297- 610+ c_handler_eth:update_network_port(port, data, oem_huawei)
298- -- 测试 SpeedMbps 为 json.null 时,应该设置为 4294967295611+ restore_collateral()
299- data.SpeedMbps = json.null612+ port_mgmt.get_instance = orig_pm
300- self.bma:add(self.url, data)613+ restore_log()
301- lu.assertEquals(np.SpeedMbps, 4294967295)614+ return rec
302- 615+end
303- -- 测试 SpeedMbps 从 json.null 恢复为有效值616+ 
304- data.SpeedMbps = 10000617+function TEST_bma_eth:test_update_full_duplex_from_bma_nil_skips()
305- self.bma:add(self.url, data)618+ local port = make_minimal_network_port()
306- lu.assertEquals(np.SpeedMbps, 10000)619+ port.FullDuplex = 88
307- 620+ local data = { ['@odata.id'] = '/redfish/v1/x' }
308- -- 测试 SpeedMbps 0 的情况621+ local oem_huawei = { NICName = port.Name }
309- data.SpeedMbps = 0622+ local rec = run_update_network_port(port, data, oem_huawei, new_port_mgmt_recorder)
310- self.bma:add(self.url, data)623+ lu.assertEquals(port.FullDuplex, 88)
311- lu.assertEquals(np.SpeedMbps, 0)624+ lu.assertEquals(#rec.duplex, 0)
312- 625+end
313- -- 再次测试 json.null 确保逻辑稳定626+ 
314- data.SpeedMbps = json.null627+function TEST_bma_eth:test_update_full_duplex_from_bma_json_null_true_false()
315- self.bma:add(self.url, data)628+ local oem_huawei = { NICName = 'eno_ut' }
316- lu.assertEquals(np.SpeedMbps, 4294967295)629+ 
630+ local port1 = make_minimal_network_port()
631+ local rec1 = run_update_network_port(port1,
632+ { ['@odata.id'] = '/x', FullDuplex = json.null }, oem_huawei, new_port_mgmt_recorder)
633+ lu.assertEquals(port1.FullDuplex, 255)
634+ lu.assertEquals(#rec1.duplex, 1)
635+ lu.assertEquals(rec1.duplex[1].val, 255)
636+ 
637+ local port2 = make_minimal_network_port()
638+ local rec2 = run_update_network_port(port2,
639+ { ['@odata.id'] = '/x', FullDuplex = true }, oem_huawei, new_port_mgmt_recorder)
640+ lu.assertEquals(port2.FullDuplex, 1)
641+ lu.assertEquals(rec2.duplex[1].val, 1)
642+ 
643+ local port3 = make_minimal_network_port()
644+ local rec3 = run_update_network_port(port3,
645+ { ['@odata.id'] = '/x', FullDuplex = false }, oem_huawei, new_port_mgmt_recorder)
646+ lu.assertEquals(port3.FullDuplex, 0)
647+ lu.assertEquals(rec3.duplex[1].val, 0)
648+end
649+ 
650+function TEST_bma_eth:test_update_full_duplex_from_bma_pcall_swallows_port_mgmt_error()
651+ local port = make_minimal_network_port()
652+ local data = { ['@odata.id'] = '/x', FullDuplex = true }
653+ local oem_huawei = { NICName = port.Name }
654+ local orig_pm = port_mgmt.get_instance
655+ local restore_collateral = stub_update_network_port_collateral()
656+ local restore_log = stub_log_quiet()
657+ port_mgmt.get_instance = function()
658+ return {
659+ set_link_status_to_device_obj = function() end,
660+ update_bdf_to_device_obj = function() end,
661+ update_full_duplex_to_device_obj = function()
662+ error('dbus')
663+ end,
664+ update_speed_mbps_to_device_obj = function() end,
665+ update_auto_negotiation_to_device_obj = function() end,
666+ }
667+ end
668+ local ok = pcall(function()
669+ c_handler_eth:update_network_port(port, data, oem_huawei)
670+ end)
671+ lu.assertTrue(ok)
672+ lu.assertEquals(port.FullDuplex, 1)
673+ restore_collateral()
674+ port_mgmt.get_instance = orig_pm
675+ restore_log()
676+end
677+ 
678+function TEST_bma_eth:test_update_speed_mbps_from_bma_nil_skips()
679+ local port = make_minimal_network_port()
680+ port.SpeedMbps = 333
681+ local data = { ['@odata.id'] = '/x' }
682+ local oem_huawei = { NICName = port.Name }
683+ local rec = run_update_network_port(port, data, oem_huawei, new_port_mgmt_recorder)
684+ lu.assertEquals(port.SpeedMbps, 333)
685+ lu.assertEquals(#rec.speed, 0)
686+end
687+ 
688+function TEST_bma_eth:test_update_speed_mbps_from_bma_json_null_and_numeric()
689+ local oem_huawei = { NICName = 'eno_ut' }
690+ 
691+ local port1 = make_minimal_network_port()
692+ local rec1 = run_update_network_port(port1,
693+ { ['@odata.id'] = '/x', SpeedMbps = json.null }, oem_huawei, new_port_mgmt_recorder)
694+ lu.assertEquals(port1.SpeedMbps, 4294967295)
695+ lu.assertEquals(#rec1.speed, 1)
696+ lu.assertEquals(rec1.speed[1].val, 4294967295)
697+ 
698+ local port2 = make_minimal_network_port()
699+ port2.SpeedMbps = 100
700+ local rec2 = run_update_network_port(port2,
701+ { ['@odata.id'] = '/x', SpeedMbps = 25000 }, oem_huawei, new_port_mgmt_recorder)
702+ lu.assertEquals(port2.SpeedMbps, 25000)
703+ lu.assertEquals(rec2.speed[1].val, 25000)
704+end
705+ 
706+function TEST_bma_eth:test_update_speed_mbps_from_bma_pcall_swallows_port_mgmt_error()
707+ local port = make_minimal_network_port()
708+ local data = { ['@odata.id'] = '/x', SpeedMbps = 5000 }
709+ local oem_huawei = { NICName = port.Name }
710+ local orig_pm = port_mgmt.get_instance
711+ local restore_collateral = stub_update_network_port_collateral()
712+ local restore_log = stub_log_quiet()
713+ port_mgmt.get_instance = function()
714+ return {
715+ set_link_status_to_device_obj = function() end,
716+ update_bdf_to_device_obj = function() end,
717+ update_full_duplex_to_device_obj = function() end,
718+ update_speed_mbps_to_device_obj = function()
719+ error('dbus')
720+ end,
721+ update_auto_negotiation_to_device_obj = function() end,
722+ }
723+ end
724+ local ok = pcall(function()
725+ c_handler_eth:update_network_port(port, data, oem_huawei)
726+ end)
727+ lu.assertTrue(ok)
728+ lu.assertEquals(port.SpeedMbps, 5000)
729+ restore_collateral()
730+ port_mgmt.get_instance = orig_pm
731+ restore_log()
732+end
733+ 
734+function TEST_bma_eth:test_update_auto_negotiation_from_bma_nil_skips()
735+ local port = make_minimal_network_port()
736+ port.AutoSpeedNegotiation = 44
737+ local data = { ['@odata.id'] = '/x' }
738+ local oem_huawei = { NICName = port.Name }
739+ local rec = run_update_network_port(port, data, oem_huawei, new_port_mgmt_recorder)
740+ lu.assertEquals(port.AutoSpeedNegotiation, 44)
741+ lu.assertEquals(#rec.autoneg, 0)
742+end
743+ 
744+function TEST_bma_eth:test_update_auto_negotiation_from_bma_json_null_true_false()
745+ local oem_huawei = { NICName = 'eno_ut' }
746+ 
747+ local port1 = make_minimal_network_port()
748+ local rec1 = run_update_network_port(port1,
749+ { ['@odata.id'] = '/x', AutoNeg = json.null }, oem_huawei, new_port_mgmt_recorder)
750+ lu.assertEquals(port1.AutoSpeedNegotiation, 255)
751+ lu.assertEquals(rec1.autoneg[1].val, 255)
752+ 
753+ local port2 = make_minimal_network_port()
754+ local rec2 = run_update_network_port(port2,
755+ { ['@odata.id'] = '/x', AutoNeg = true }, oem_huawei, new_port_mgmt_recorder)
756+ lu.assertEquals(port2.AutoSpeedNegotiation, 1)
757+ lu.assertEquals(rec2.autoneg[1].val, 1)
758+ 
759+ local port3 = make_minimal_network_port()
760+ local rec3 = run_update_network_port(port3,
761+ { ['@odata.id'] = '/x', AutoNeg = false }, oem_huawei, new_port_mgmt_recorder)
762+ lu.assertEquals(port3.AutoSpeedNegotiation, 0)
763+ lu.assertEquals(rec3.autoneg[1].val, 0)
764+end
765+ 
766+function TEST_bma_eth:test_update_auto_negotiation_from_bma_pcall_swallows_port_mgmt_error()
767+ local port = make_minimal_network_port()
768+ local data = { ['@odata.id'] = '/x', AutoNeg = true }
769+ local oem_huawei = { NICName = port.Name }
770+ local orig_pm = port_mgmt.get_instance
771+ local restore_collateral = stub_update_network_port_collateral()
772+ local restore_log = stub_log_quiet()
773+ port_mgmt.get_instance = function()
774+ return {
775+ set_link_status_to_device_obj = function() end,
776+ update_bdf_to_device_obj = function() end,
777+ update_full_duplex_to_device_obj = function() end,
778+ update_speed_mbps_to_device_obj = function() end,
779+ update_auto_negotiation_to_device_obj = function()
780+ error('dbus')
781+ end,
782+ }
783+ end
784+ local ok = pcall(function()
785+ c_handler_eth:update_network_port(port, data, oem_huawei)
786+ end)
787+ lu.assertTrue(ok)
788+ lu.assertEquals(port.AutoSpeedNegotiation, 1)
789+ restore_collateral()
790+ port_mgmt.get_instance = orig_pm
791+ restore_log()
317end792end