// 此模板仅供参考,如果不适用可以修改
问题描述
BMC上不显示以太网卡的连接视图,无交换机信息,包括交换机名称、交换机连接ID、交换机连接端口ID以及交换机端口VLAN ID。
环境信息
-
操作系统:[如 Ubuntu 24.04]
-
软件版本:[如 OpenUBMC2512]
-
硬件配置:[如 CPU、内存等]
重现步骤
-
登录BMC web
-
系统管理-系统信息-网络适配器-选中网络设备,选中以太网卡设备,点击端口属性下方隐藏标志
-
查看指定网卡的连接视图
期望结果
端口隐藏信息中有连接视图,显示交换机信息
实际结果
端口隐藏信息中无连接视图,不显示交换机信息
代码
1.网卡SP681支持MCTP和LLDP,且对应字段已经设置为true
2.交换机相关字段的配置
mdb_interface/json/intf/mdb/bmc/dev/NetworkPort/LLDPReceive.json
network_adapter/gen/class/model.lua
network_adapter/src/lualib/device/class/network_port.lua
local lldp_receive_mds_name_map<const> = {
ChassisId = 'chassis_id',
ChassisIdSubtype = 'chassis_id_subtype',
PortId = 'port_id',
PortIdSubtype = 'port_id_subtype',
SystemName = 'system_name',
ManagementVlanId = 'vlan_id'
}
local default_lldp_receive_data<const> = {
ChassisId = '',
ChassisIdSubtype = '',
PortId = '',
PortIdSubtype = '',
SystemName = '',
ManagementVlanId = 0xFFFF
}
local function set_lldp_for_hi182x(port, enable)
local ok, ret
if enable then
-- 先尝试新命令字
ok, ret = pcall(function()
return port.ncsi_config_obj
:SetOnLLDPTxEnable({ channel_id = port:get_port_id(), package_id = port.package_id })
:value()
end)
if not ok or not ret then
-- 新命令字失败,则尝试旧命令字
ok, ret = pcall(function()
return port.ncsi_config_obj
:SetOnLLDPTxEnableOld({
channel_id = port:get_port_id(),
package_id = port.package_id,
})
:value()
end)
end
return ok, ret
end
-- 先尝试新命令字
ok, ret = pcall(function()
return port.ncsi_config_obj
:SetOffLLDPTxEnable({ channel_id = port:get_port_id(), package_id = port.package_id })
:value()
end)
if not ok or not ret then
-- 新命令字失败,则尝试旧命令字
ok, ret = pcall(function()
return port.ncsi_config_obj
:SetOffLLDPTxEnableOld({ channel_id = port:get_port_id(), package_id = port.package_id })
:value()
end)
end
return ok, ret
end
function c_network_port:set_LLDP_capability_by_ncsi(enable, parent)
local ok, ret
if parent and device_comm_fun.is_hi182x_model(parent.Model) then
ok, ret = set_lldp_for_hi182x(self, enable)
elseif parent and LLDP_SUPPORTED_MELLANOX_MODELS[parent.Model] then
ok, ret = set_lldp_for_mellanox(self, enable, parent)
elseif parent and LLDP_SUPPORTED_WANGXUN_MODELS[parent.Model] then
ok, ret = set_lldp_for_wangxun(self, enable)
end
if not ok or not ret then
log:error('set LLDP capability failed for port %s', self.NodeId)
end
return ok, ret
end
function c_network_port:set_LLDP_capability_by_mcu(enable)
local ctx = context.get_context_or_default()
local dpu_cards = client:GetDPUCardObjects()
local position = self:get_position()
local cur_dpu, ok, ret
for _, dpu_card in pairs(dpu_cards) do
if dpu_card.extra_params.Position == position then
cur_dpu = dpu_card
break
end
end
if not cur_dpu then
log:error('not find dpu card on position[%s]', position)
return false, false
end
ok, ret = pcall(function()
return cur_dpu:SetLLDPStatus(ctx, self:get_port_id(), enable and 1 or 0)
end)
if not ok then
log:error('unable to set LLDP capability for port %s, error: %s', self:get_port_id(), ret)
return false, false
end
return true, true
end
-- redfish调用此函数设置LLDP使能
function c_network_port:redfish_set_lldp_capability(enable)
log:notice('set LLDP capability for port %s, enable: %s', self.NodeId, enable)
local parent = self:get_parent()
local ctx = context.get_context()
-- 网卡不支持lldp使能
if not parent.SupportedLLDP then
log:error('not support set LLDP capability for port %s', self.NodeId)
self:log_lldp_operation(enable, ctx, false)
error(custom_messages.ConfigPortLLDPErr())
end
local ok, ret
if self.WorkloadType == LOADED_NIC_OS then
ok, ret = self:set_LLDP_capability_by_mcu(enable)
elseif self.oem_smbus_config_obj and next(self.oem_smbus_config_obj) ~= nil then
ok, ret = self.oem_smbus_config_obj:SetPortLLDPEnable(self, enable)
else
ok, ret = self:set_LLDP_capability_by_ncsi(enable, parent)
end
if not ok or not ret then
log:error('set LLDP capability failed for port %s', self.NodeId)
self:log_lldp_operation(enable, ctx, false)
error(custom_messages.ConfigPortLLDPErr())
end
self:log_lldp_operation(enable, ctx, true)
log:notice('%s port %s LLDP successfully', enable and 'enable' or 'disable', self.NodeId)
end
function c_network_port:update_LLDP_enabled_by_mcu()
local ctx = context.get_context_or_default()
local dpu_cards = client:GetDPUCardObjects()
local position = self:get_position()
local cur_dpu
for _, dpu_card in pairs(dpu_cards) do
if dpu_card.extra_params.Position == position then
cur_dpu = dpu_card
break
end
end
if not cur_dpu then
log:error('not find dpu card on position[%s]', position)
return
end
local ok, status = pcall(function()
return cur_dpu:GetLLDPStatus(ctx, self:get_port_id())
end)
if not ok then
log:error('unable to get LLDP capability for port %s, error: %s', self:get_port_id(), status)
return
end
self.LLDPEnabled = status == 1 and true or false
end
function c_network_port:enable_lldp_over_mctp()
self:next_tick(function()
-- 最多尝试5次,每次间隔1分钟
local max_retries = 5
local retry_count = 0
local retry_interval_ticks = 6000 -- 1分钟
local ok, ret
while retry_count < max_retries do
retry_count = retry_count + 1
ok, ret = pcall(function()
return self.ncsi_config_obj
:SetOnLLDPOverMCTPEnable({
channel_id = self:get_port_id(),
package_id = self.package_id,
})
:value()
end)
if ok and ret then
log:notice('%s enable lldp over mctp successfully, retry_count: %d', self.NodeId, retry_count)
return
end
if retry_count < max_retries then
log:warn(
'enable lldp over mctp failed for port %s, retry %d/%d, will retry after 2 minutes',
self.NodeId,
retry_count,
max_retries
)
skynet.sleep(retry_interval_ticks)
end
end
log:error('enable lldp over mctp failed for port %s after %d retries', self.NodeId, max_retries)
end)
end
function c_network_port:update_lldp_tx_enabled_by_ncsi()
local s
local parent = self:get_parent()
if parent and device_comm_fun.is_hi182x_model(parent.Model) then
s = self.ncsi_config_obj:GetLLDPTxEnable({ channel_id = self:get_port_id(), package_id = self.package_id })
elseif parent and (LLDP_SUPPORTED_MELLANOX_MODELS[parent.Model] or LLDP_SUPPORTED_WANGXUN_MODELS[parent.Model]) then
s = self.ncsi_config_obj:GetLLDPCapability({ channel_id = self:get_port_id(), package_id = self.package_id })
end
self:connect_signal(s.on_data_change, function(data)
self.LLDPEnabled = data
log:notice('%s update lldp tx enabled to %s by ncsi', self.NodeId, data)
end)
table.insert(self.schedulers, s)
s:start()
log:notice('%s update lldp tx enabled by ncsi start', self.NodeId)
end
function c_network_port:update_ncsi_properties()
self:next_tick(self.update_ncsi_port_stats, self)
self:next_tick(self.update_ncsi_link_status, self)
self:next_tick(self.update_BDF_by_ncsi, self)
self:next_tick(self.update_MAC_by_ncsi, self)
self:next_tick(self.update_DCBX_by_ncsi, self)
self:next_tick(self.update_default_MAC_by_ncsi, self)
if self.WorkloadType == LOADED_NIC_OS then
self:next_tick(self.update_LLDP_enabled_by_mcu, self)
else
self:next_tick(self.update_lldp_tx_enabled_by_ncsi, self)
end
local op = self:get_optical_module()
if op then
op:update_ncsi_properties(self.ncsi_config_obj, self.package_id)
end
end
function c_network_port:register_property_changed_callback()
local link_status = self.LinkStatusNumeric == 1 and 'Connected' or
self.LinkStatusNumeric == 0 and 'Disconnected' or INVALID_DATA_STRING
self:set_link_status(link_status)
self:connect_signal(self.on_property_changed, function(name, value)
if property_changed_switch[name] then
self:next_tick(property_changed_switch[name], self, value)
end
end)
if self['bmc.kepler.Systems.NetworkPort'] then
self:connect_signal(self['bmc.kepler.Systems.NetworkPort'].property_before_change, function(name, value)
if name == 'LLDPEnabled' then
self:redfish_set_lldp_capability(value)
end
end)
end
end
function c_network_port:ctor()
self.schedulers = {}
self.lldp_config_obj = {}
self.ncsi_config_obj = {}
self.smbus_schedulers = {}
self.oem_smbus_config_obj = {}
self.package_id = 0
self.na_object_name = ''
self.np_object_name = ''
self.lldp_clear_task = false
self.tasks = c_tasks.new()
self.vlans = false
self.get_ncsi_link_status_succeess = false
self.npu_ipv4_info = {}
self.npu_ipv4_obj = false
-- 此表用于临时保存非bma获取的属性,用于bma断开后恢复,当前仅LinkStatus使用
self.t_port_prop_without_bma = {}
self.ncsi_get_linkstatus_retry_count = 0
self.is_npu_heartbeat_loss = false
self.is_dmp_status_ready = false
self.mac_change = signal.new()
self.record_flag = 0
self.hccs_flag = 2
self.link_up_cnt = 0
self.link_down_cnt = 0
self.link_up_timestamp = {}
self.link_down_timestamp = {}
self.per_module_log_cnt = 0
self.npu_port_log_buffer = {}
self.npu_port_cdr_info_abnormal = false
self.children = {}
self.parent = {}
self.device_path = ''
self.hccs_info = {
npu_id = 0,
health_status = 0,
lane_mode = {},
link_lane_list = {},
link_speed = {},
tx_packets = {},
tx_bytes = {},
rx_packets = {},
rx_bytes = {},
retry_count = {},
error_count = {},
first_error_lane = 255,
snr_max = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
snr_min = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
half_height_max = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
half_height_min = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
}
self.get_properties_res = {}
self.bdf_task_is_running = false
end
rackmount/interface_config/web_backend/mapping_config/System/NetworkAdapter.json
连接视图
3.LLDP接收信息接口属性说明
| 属性名 | 类型 | 可读写 | 描述 | 等级定义 |
|---|---|---|---|---|
| ChassisId | String | 只读 | 从网络交换机接收到的Chassis ID;交换机(机箱)的唯一标识(交换机连接ID) | L1: 基本静态信息 |
| ChassisIdSubtype | String | 只读 | 从网络交换机接收到的Chassis ID类型:1、Agentld;2、ChassisComp;3、IfAlias;4、IfName;5、LocalAssign;6、MacAddr;7、NetworkAddr;8、NotTransmitted;9、PortComp | L1: 基本类型信息 |
| PortId | String | 只读 | 从网络交换机接收到的端口ID;交换机端口的唯一标识 | L1: 基本静态信息 |
| PortIdSubtype | String | 只读 | 从网络交换机接收到的端口ID类型:1、Agentld;2、ChassisComp;3、IfAlias;4、IfName;5、LocalAssign;6、MacAddr;7、NetworkAddr;8、NotTransmitted;9、PortComp | L1: 基本类型信息 |
| SystemName | String | 只读 | 网络交换机名称 | L1: 基本静态信息 |
| ManagementVlanId | U16 | 只读 | 从网络交换机接收到的VLAN ID;交换机的管理 VLAN ID | L1: 基本静态信息 |
尝试过的解决方案
1.通过postman修改LLDPEnabled属性为true
2.查看日志
在设置LLDPEnabled属性为true后,依旧报Can’t find system description from LLDP
3.抓包LLDP报文
抓包LLDP报文成功,找到ChassisId、ChassisIdSubtype、PortId、PortIdSubtype、SystemName和System Description
没有ManagementVlanId,但是ManagementVlanId默认为0
4.追踪抓取通信报文
用tracemctp Endpoint_65_2 start抓取BMC 与 SP681 网卡之间,通过 MCTP 通道传输的 NCSI 管理报文
报文中没有lldp相关信息
% tracemctp Endpoint_65_2 start2.txt (435.3 KB)
确定Endpoint
BDF 地址
BDF=“0000:41:00.1”
把 BDF 映射到 phy_addr
MCTP 的物理地址(phy_addr)和 PCIe 的 BDF 有对应关系。0000:41:00.1 里的设备号是 0x41,换算成十进制就是 65。
在 MCTP 注册信息里找 phy_addr=65 的条目
idx:12, module_name = network_adapter, phy_addr = 65, msg_src_eid = 24, msg_type = 126, pid = 5611, process_tag = 3224632059 idx:13, module_name = network_adapter, phy_addr = 65, msg_src_eid = 24, msg_type = 1, pid = 5611, process_tag = 3224632059 idx:14, module_name = network_adapter, phy_addr = 65, msg_src_eid = 24, msg_type = 2, pid = 5611, process_tag = 3224632059
phy_addr = 65对应的 EID 是 24,而msg_type = 2正好是 NCSI over MCTP,也就是 LLDP 数据上报用的消息类型。
5.修改LLDPOverNCSIEnabled
platform.sr中LLDPOverNCSIEnabled为0,修改为1后,没有变化。
求助
1.app.log中bmc_core的Ildp_proc.c(338)一直报错:Can’t find system description from LLDP 是什么原因
2.LLDP报文中有相应字段,但无法解析和正确显示,如何解决
3.NetworkAdapter_1_01011B01的LLDPSupported=false,而且网卡资源中并没有LLDPSupported这个属性,是什么原因
4.LLDPSupported和SupportedLLDP字段有什么区别?
mdb_interface/json/intf/mdb/bmc/kepler/Systems/NetworkAdapter.json
5.LLDPSupported和vpd/vendor/Huawei/Server/Kunpeng/openUBMC/platform/platform.sr中的LLDPSupport又有什么区别
6.请问各位的BMC有没有正确显示交换机信息?可以发截图看一下吗?



















