mctpd

版本信息

项目内容
组件版本1.130.12
首发版本openUBMC 26.09
文档作者openUBMC 社区
最后更新2026-09-15
许可证Mulan PSL v2

1. 组件概述

1.1 组件简介

mctpd 是 openUBMC 的 MCTP(Management Component Transport Protocol,管理组件传输协议)路由与通道管理组件。它以独立 Skynet 应用运行,D-Bus 服务名为 bmc.kepler.mctpd,通过资源协作接口为 BMC 与平台管理子系统之间的部件通信提供 Endpoint、路由表和 Binding 对象。

MCTP 由 DMTF PMCI 工作组定义,是一种独立于底层物理总线的数据链路层协议。业务组件(如 network_adapterstorage)通过打包进 /opt/bmc/lualibmctp_lib 创建 Transport 并获取 Endpoint,再调用 Request / Send 完成报文收发。

组件不提供 IPMI 命令。C 层 libmctp / l_mctp(Lua 模块 mctp.core)是协议栈实现,仅供 mctpd 进程内部使用,不作为其他组件的公开 API。

1.2 解决什么问题

BMC 需要通过 PCIe VDM 或 SMBus 与网卡、NVMe、RAID 卡、IMU 等管理部件交换 PLDM、NC-SI、NVMe-MI、SPDM 等消息。mctpd 把物理介质差异、分帧、自发现和路由维护收敛到统一服务:

  • 主机上电后完成 MCTP Endpoint Discovery,维护 Owner / BMC 的 EID 与物理地址。
  • 周期性从 IMU 获取路由表,并按路由是否存在决定是否为业务 Transport 创建 PCIe Endpoint
  • 为 SMBus / SMBus_OEM 路径按 CSR 创建 Endpoint,经 hwproxy SMBus 插件访问 Chip。
  • 向业务暴露同一套 Request(等待响应)和 Send(只发不收)方法。

1.3 核心功能

  • 核心功能一:MCTP 通道与 Endpoint 管理

    支持 Request / Send 两种消息模式;按 MessageType 创建 MCTP Control、PLDM、NC-SI、NVMe、SPDM、Vendor Defined-PCI Endpoint,未知类型回落到通用 Endpoint。

  • 核心功能二:多物理介质

    PCIe VDM(MediumType=0x0F)走 mctp 驱动与 IMU;SMBus(0x02)和 SMBus_OEM(0x80)走 hwproxy 用户态驱动。C 层另有 serial_protocol,但 Endpoint 创建表未列出 Serial 介质,业务创建路径源码未覆盖。

  • 核心功能三:自发现与路由

    监听 compute 的 Pmu.Status 和 bios 的 SmBios.SmBiosStatus,上电后打开驱动、启动 worker,处理 IMU 的 Prepare/Discovery/Set Endpoint ID,并每隔 5s 更新路由表。

1.4 关键术语表

术语解释
MCTPManagement Component Transport Protocol,独立于物理介质的管理部件传输协议。
EIDEndpoint ID,MCTP 端点逻辑地址。
PhyAddr物理地址。PCIe 场景由 PCI BDF 换算;SMBus 场景为 7bit 从地址。
Endpoint某一 MessageType + 物理地址上的通信端点,提供 Request / Send
Transport业务组件在本进程资源树上注册的通道对象;mctpd 仅在对应路由存在时为其创建 Endpoint。
IMU平台侧 MCTP bus owner(接口描述中也称 ME),负责 discovery 与路由分发。
MessageType上层协议类型,如 0x01 PLDM、0x02 NC-SI、0x04 NVMe。
MediumType物理介质类型:0x0F PCIe、0x02 SMBus、0x80 SMBus_OEM。

1.5 外部交互边界图

mctpd 通过资源协作接口对外发布 Binding、Endpoint、Routing、Debug 接口,同时订阅 Pmu / SmBios / Chip / SOC.Env,并监听业务侧 PCIeTransport

systemd 单元 mctpd.serviceframework.service 之后启动,依赖 dbus.serviceframework.servicepersistence.service,工作目录 /opt/bmc/apps/mctpd。构建依赖 libmc4luapersistence;构建选项 chipv2_enable 选择 chipv1 / chipv2 驱动配置。


2. API 使用说明与示例

对外发布的 API 为资源协作接口,服务名 bmc.kepler.mctpd。路径中的 SystemId 默认取 1(实际集合来自 bmc.kepler.Managers.SOC.EnvSystemIds)。均可通过 busctl / mdbctl 调试。

方法首参 a{ss} 为框架调用上下文;命令行调试可传空字典 0。权限取自 mds/model.json(默认 ConfigureSelfTraceMessageDiagnoseMgmt)。

bash
# 查看资源协作接口
busctl --user tree bmc.kepler.mctpd

目前可创建的 Endpoint 如下。未在表中的 MessageType 会创建通用 Endpoint,由调用方自行封装上层协议。

名称MessageTypeCode支持的物理层以及 MediumTypeCode代码中描述
MCTP Control0x00PCIe(0x0F)、SMBus(0x02)、SMBus_OEM(0x80)MCTP_MESSAGE_TYPE_MCTP_CTRL
Platform Level Data Model0x01同上MCTP_MESSAGE_TYPE_PLDM
NC-SI over MCTP0x02同上MCTP_MESSAGE_TYPE_NCSI
NVMe over MCTP0x04同上MCTP_MESSAGE_TYPE_NVME
SPDM over MCTP0x05同上MCTP_MESSAGE_TYPE_SPDM
Vendor Defined-PCI0x7E同上MCTP_MESSAGE_TYPE_VDPCI

mctp_lib 还导出 MCTP_MESSAGE_TYPE_ETHERNET0x03)、MCTP_MESSAGE_TYPE_SECUREDMSG0x06)、MCTP_MESSAGE_TYPE_VDIANA0x7F)常量,但仓库未给出对应专用 Endpoint 类。

2.1 bmc.kepler.Systems.Mctp.MctpBinding.PCIe

功能说明

查询 PCIe 介质上 Owner(IMU/ME)与 BMC 的 EID、物理地址,以及自发现 / 路由表就绪状态。

路径/bmc/kepler/Systems/${SystemId}/Mctp/MctpBinding

参数说明

属性类型读写说明
OwnerEidy只读ME/IMU 的 EID
OwnerPhyAddrq只读ME/IMU 的 PCIe 物理地址
BmcEidy只读BMC 的 EID
BmcPhyAddrq只读BMC 的 PCIe 物理地址
DiscoverFinishedb只读是否完成过 Endpoint Discovery
RoutingTableReadyb只读路由表是否就绪

返回值与异常

属性只读。OS 未上电或未完成 discovery 时,BmcEid / BmcPhyAddr 可为 0。Lua 辅助函数 mctp_lib.get_mctp_pcie_binding 在二者之一为 0 时不返回对象。

应用场景

业务在创建 PCIe Endpoint 前确认 MCTP 链路已建立。

限制条件

需要调用方在 mds/service.json 中声明对 bmc.kepler.Systems.Mctp.MctpBinding.PCIe 的依赖。

调试示例

bash
busctl --user introspect bmc.kepler.mctpd \
    /bmc/kepler/Systems/1/Mctp/MctpBinding
lua
local mctp_lib = require('mctp_lib')
local obj = mctp_lib.get_mctp_pcie_binding(bus)  -- OS 未上电时可能为 nil

2.2 bmc.kepler.Systems.Mctp.MctpBinding.SMBus

功能说明

CSR 配置的 SMBus Binding:BMC 在 SMBus 上使用的 EID 和物理地址。模型属性名为 BmcSMBusEid / BmcSMBusPhyAddr,接口侧对应 BmcEid / BmcPhyAddr

路径/bmc/kepler/Systems/${SystemId}/Mctp/MctpBinding

参数说明

属性类型读写说明
BmcEid(CSR:BmcSMBusEidyCSR 配置SMBus 协议使用的 BMC EID
BmcPhyAddr(CSR:BmcSMBusPhyAddryCSR 配置SMBus 协议使用的 BMC 物理地址

返回值与异常

由 CSR 的 MctpBinding_* 对象加载;未配置时 SMBus Endpoint 无法完成 Set Endpoint ID。

应用场景

网卡/硬盘走 SMBus 或 SMBus_OEM 时,与 Endpoint_*Chip_* 一起出现在机型 CSR 中。

限制条件

SMBus 类型 Endpoint 还需关联 bmc.kepler.Chip.BlockIORefChip)。插在硬盘背板上时,CPLD 需支持 SMBus 通信;SMBus_OEM 不依赖 CPLD 版本(见组件 README)。

调试示例

json
"MctpBinding_1": {
    "BmcSMBusEid": 8,
    "BmcSMBusPhyAddr": 16
}

2.3 bmc.kepler.Systems.Mctp.PCIeEndpoint

功能说明

单个 MCTP Endpoint 的身份属性、报文收发方法,以及接收信号。尽管接口名含 PCIe,SMBus / SMBus_OEM Endpoint 也使用同一接口。

路径

  • PCIe:/bmc/kepler/Systems/${SystemId}/Mctp/Endpoint/${phyaddr}/${MsgType}
  • SMBus:/bmc/kepler/Systems/${SystemId}/Mctp/Endpoint/${position}_${phyaddr}/${MsgType}position 为 CSR GroupPosition,用于区分同一总线上相同物理地址)

参数说明

属性类型读写默认值说明
ServiceNames只读注册通道的模块名
TargetEidy只读 / CSR对端 EID
TargetPhyAddrq只读 / CSR对端物理地址
MessageTypey只读 / CSR上层协议类型
MediumTypey只读 / CSR150x0F0x02 SMBus,0x0F PCIe,0x80 SMBus_OEM
Statusy只读00 初始;1 Endpoint 发现完成。发出 PropertiesChanged

CSR 额外属性(不在 PCIeEndpoint 接口上,属于对象模型):

属性类型默认值说明
RefChipU8[]关联 bmc.kepler.Chip.BlockIO
RetryLimitU320SMBus Set Endpoint ID 失败重试上限
RetryDelaySecondU3210重试间隔(秒)
方法D-Bus 签名入参出参说明
Requesta{ss}ayia{ss}a{ss}ay上下文、DataTimeoutMsReqHeaderFiledsRspHeaderValidatorsData发送并等待响应
Senda{ss}aya{ss} → 空上下文、DataReqHeaderFileds只发送,不等待响应
信号签名说明
OnMessagea{ss}ayEndpoint 收到数据时发出
MessageReceiveda{ss}ayOnMessage 同时转发同一份 Data

ReqHeaderFileds / RspHeaderValidatorsa{ss}。当前实现支持:

协议请求头字段(填充)响应头校验
NC-SIPacketTypeChannelIdPackageIdPacketType
NVMeICMsgTypeCmdSlotMsgType(README 说明)
PLDMPldmTypeCommandCodeCommandCode
SPDM可由 mctpd 封装,也可由调用方自带报文(不传 ctx)见 README
VDPCI厂商头已包含在 Data 中,ctx 传 {}{}

返回值与异常

Request 成功返回响应字节数组。失败时抛异常,消息定义见 mds/errors.json

错误名HTTPIPMI含义
kepler.mctpd.InvalidMctpRequest4000xFF请求非法
kepler.mctpd.MctpEndpointReset4000xFFEndpoint 已复位
kepler.mctpd.MctpRequestTimeout4000xFF请求超时
kepler.mctpd.MctpInvalidResponse4000xFF响应 packet_type 与期望不符

内部引擎在“上一请求未完成”时返回发送失败,不会并行排队同一 key。超时日志为 mctp_engine: request timeout

应用场景

network_adapter、storage 等通过 Endpoint 发送 NC-SI / PLDM / NVMe-MI 等报文。上层协议建议优先使用 libmgmt_protocol 封装,而不是直接拼二进制。

限制条件

  • PCIe Endpoint 必须先有对应物理地址的路由条目,否则 mctpd 不会根据 Transport 创建 Endpoint。
  • SMBus Endpoint 依赖 CSR 的 Binding、Endpoint、Chip。
  • RequestTimeoutMs 单位为毫秒(Lua Endpoint 实现传入 mctp_engine:request)。

调试示例

lua
-- NC-SI:需要返回值
local ok, rsp_data_bin = pcall(endpoint.Request, endpoint, context, request_data_bin, timeout, ncsi_req_ctx, ncsi_rsp_ctx)
-- 不需要返回值
local ok = pcall(endpoint.Send, endpoint, context, request_data_bin, timeout, ncsi_req_ctx)
bash
busctl --user introspect bmc.kepler.mctpd \
    /bmc/kepler/Systems/1/Mctp/Endpoint/150/2

2.4 bmc.kepler.Release.Mctp

功能说明

跟踪指定 Endpoint 的收发报文(维护 CLI tracemctp)。

路径:与 Endpoint 对象相同,/bmc/kepler/Systems/${SystemId}/Mctp/Endpoint/${Id}/${MsgType}

参数说明

方法签名入参说明
TraceMessagea{ss}s → 空Actionstart / stop开始或停止跟踪该 Endpoint 报文

权限:DiagnoseMgmt

返回值与异常

对象路径无法解析为已知 Endpoint 时抛错(unknown endpoint path / unknown endpoint)。

应用场景

一键收集或维护 CLI 抓取某 Endpoint 收发数据。

限制条件

仅对已创建的 Endpoint 生效;PCIe 路径在 worker 收包处按 is_trace 打印,SMBus 路径在 smbus 协议分发处打印。

调试示例

bash
busctl --user call bmc.kepler.mctpd \
    /bmc/kepler/Systems/1/Mctp/Endpoint/150/2 \
    bmc.kepler.Release.Mctp TraceMessage a{ss}s 0 start

2.5 bmc.kepler.Systems.Mctp.PCIeRoutingEntry

功能说明

单条 MCTP 路由表项,由 IMU 返回的路由信息上树。

路径/bmc/kepler/Systems/${SystemId}/Mctp/Routing/${phyaddr}

参数说明

属性类型读写说明
EidRangeSizey只读EID 范围大小
StartingEidy只读起始 EID
EntryTypey只读路由类型
PhysTransportBindingIdy只读物理通道绑定 ID
MediaTypeIdy只读物理介质类型
PhysAddressay只读物理地址(Endpoint 条目仅一个地址)

返回值与异常

只读;路由删除时对象下树。

应用场景

确认网卡、盘、RAID 等设备的 phyaddr 是否已出现在路由中。没有对应路由时,mctpd 不会为该地址创建 PCIe Endpoint。

限制条件

PCIe 路由来自上电后 IMU 的 Get Routing Table;硬件未响应 discovery 则不会出现对应条目。

调试示例

bash
busctl --user tree bmc.kepler.mctpd | grep Routing

2.6 bmc.kepler.Release.Mctp.Routing

功能说明

一次性导出当前路由表。

路径/bmc/kepler/Systems/${SystemId}/Mctp/Routing

参数说明

方法签名出参说明
GetRouteTablea{ss}aa{ss}Result:字典数组每项含 EIDPHYADDRPHYSICAL_MEDIA_IDENTIFIER

返回值与异常

成功返回数组;字段值为十六进制字符串,例如 EID=0x09PHYADDR=0x0096PHYSICAL_MEDIA_IDENTIFIER=0x0f(...)

应用场景

维护诊断、一键收集之外的在线查询。

限制条件

未上电或路由未就绪时结果可能为空。

调试示例

bash
busctl --user call bmc.kepler.mctpd \
    /bmc/kepler/Systems/1/Mctp/Routing \
    bmc.kepler.Release.Mctp.Routing GetRouteTable a{ss} 0

2.7 bmc.kepler.Debug.Mctp

功能说明

设置 MCTP 传输单元大小(默认实现值为 MCTP_MSG_TRANSFER_UNIT_SIZE = 64)。

路径/bmc/kepler/Systems/${SystemId}/Mctp

参数说明

方法签名入参说明
SetTransmissionUnitSizea{ss}q → 空SizeU16设置分帧传输单元大小

成功后写 notice 日志,并记录 log:operation

返回值与异常

成功无返回。非法上下文由框架校验。

应用场景

调试分帧或适配超大 NVMe-MI 报文时调整 MTU。

限制条件

调试接口,变更立即作用于该 System 的 mctp_protocol.max_size。取值范围源码未覆盖额外校验。

调试示例

bash
busctl --user call bmc.kepler.mctpd \
    /bmc/kepler/Systems/1/Mctp \
    bmc.kepler.Debug.Mctp SetTransmissionUnitSize a{ss}q 0 64

2.8 bmc.kepler.Systems.Mctp.PCIeTransport

功能说明

该接口由调用方进程通过 mctp_lib 注册,不由 mctpd 进程创建。mctpd 订阅 InterfacesAdded,仅当 TargetPhyAddr 已在路由表中时创建对应 Endpoint。

路径/bmc/kepler/Systems/${SystemId}/Mctp/Transport/${phyaddr|position_phyaddr}/${MsgType}(位于调用方资源树)

参数说明

属性类型读写说明
ServiceNames只读注册通道的模块名
TargetEidy只读对端 EID(创建时先填 0,Endpoint 就绪后由 mctp_lib 回写)
TargetPhyAddrq只读对端物理地址
MessageTypey只读协议类型

返回值与异常

无方法。调用方需在 mds/service.json 中声明 bmc.kepler.Systems.Mctp.PCIeTransportbmc.kepler.Systems.Mctp.PCIeEndpoint

应用场景

业务创建通道意图;与 Endpoint 配对使用。

限制条件

本进程为自己注册的 Control Transport 不会挂到资源树(module_name 等于 mctpd 自身时跳过)。

调试示例

见 2.9 get_endpoint_and_transport

2.9 mctp_lib Lua API

功能说明

公开模块路径:include/mctp_lib/init.lua(打包后 require('mctp_lib'))。用于路径构造、创建 Transport、等待 Endpoint、BDF 换算。

参数说明

函数参数返回值说明
get_mctp_path(system_id)system_id 缺省 '1'字符串/bmc/kepler/Systems/{id}/Mctp
get_mctp_routing(system_id)同上字符串.../Routing
get_mctp_transport(system_id)同上字符串.../Transport
get_mctp_endpoint(system_id)同上字符串.../Endpoint
create_mctp_endpoint_path(phy_addr, msg_type, position, system_id)SMBus 需 position字符串完整 Endpoint 路径
get_endpoint_and_transport(bus, module_name, phy_addr, msg_type, position, system_id)PCIe 不传 positionendpoint, transport创建 Transport 并等待 Endpoint
get_endpoint_and_transport_with_timeout(bus, module_name, ep_info, timeout)ep_infophy_addr/msg_type/position/system_id同上带等待超时
get_mctp_pcie_binding(bus, system_id)Binding 或 nilBmcEidBmcPhyAddr 均非 0 才返回
get_pcie_endpoint(bus, phy_addr, msg_type, system_id)Endpoint对象未上树则失败
get_smbus_endpoint(bus, position, phy_addr, msg_type, system_id)Endpoint对象未上树则失败
bdf_to_phy_addr(bus_num, dev_num, func_num)PCI BDFuint16网络字节序:device:5 | function:3 | bus:8

导出常量:MCTP_MESSAGE_TYPE_*PHY_MEDIUM_PCI / PHY_MEDIUM_SMBUS / PHY_MEDIUM_SMBUS_OEMENDPOINT_IS_DISCOVERY、接口名 PCIE_ENDPOINT_INTERFACE 等。

get_endpoint_and_transport_with_timeouttimeout 传入 skynet.sleep,单位为 0.01 秒。缺省或 timeout<=0 时使用 100 * 60 * 5(5 分钟)。无超时版本会 skynet.wait() 直到 Endpoint 创建信号。

返回值与异常

等待 Endpoint 超时或信号不匹配时 error('unmatch endpoint creation signal...')ep_infonilerror('get endpoint and transport failed, endpoint info is nil')

应用场景

业务组件在检测到主机上电、MCTP Binding 就绪后建立通道。

限制条件

必须在调用方 service.json 中引用对应接口。SMBus 必须传入 CSR GroupPosition

调试示例

lua
local mctp_lib = require('mctp_lib')
local phy_addr = mctp_lib.bdf_to_phy_addr(self.Bus, self.Device, self.Function)
local ok, endpoint, transport = pcall(
    mctp_lib.get_endpoint_and_transport,
    bus, MODULE_NAME, phy_addr, msg_type, position
)

3. 组件扩展案例

3.1 扩展能力概述

组件按 MessageType 注册 Endpoint 工厂,未知类型走 ep_general。SMBus 访问通过 include/hwproxy/plugins/smbus 插件。芯片差异由 src/config/chipv1chipv2 及 Conan 选项 chipv2_enable 切换。机型通过 CSR 增加 SMBus Endpoint,无需改 mctpd 代码。

3.2 扩展点说明

  • 新上层协议 Endpoint:在 src/lualib/mctp_endpoints/ 新增模块,于 init.luac_mctp_endpoints:initregister
  • CSR SMBus Endpoint:配置 MctpBinding_*Endpoint_*Chip_*,并在 ManagementTopology 总线下挂 Chip。
  • hwproxy SMBus 命令include/hwproxy/plugins/smbus/cmds.lua
  • 驱动/dump 配置src/config/chipv1|chipv2/mctp_drv_config.luamctp_dump.lua
  • C 协议栈src/lualib-src/libmctp/ 的 upper / transport / physical 分层(protocol::pop / push)。不要手工修改带生成标记的 gen/ 文件。

3.3 二次开发指导

3.3.1 业务侧接入(推荐)

  1. 在调用方 mds/service.json 声明 bmc.kepler.Systems.Mctp.PCIeTransportbmc.kepler.Systems.Mctp.PCIeEndpoint(查询 Binding 时再声明 MctpBinding.PCIe)。
  2. local mctp_lib = require('mctp_lib')
  3. PCIe:用 bdf_to_phy_addr 得到 phyaddr,调用 get_endpoint_and_transport
  4. pcall(endpoint.Request, ...) 收发;NC-SI / NVMe / PLDM 优先走 libmgmt_protocol

验证方法busctl --user tree bmc.kepler.mctpd 看到对应 Endpoint;日志出现 add eid infocreate endpoint

注意事项:没有路由就不会创建 PCIe Endpoint;不要假设 Transport 一注册 Endpoint 立刻存在。

3.3.2 新增 MessageType 专用 Endpoint

ep_factory[msg_type] 注册实现 request / send / get_msg_type 的类。未注册时 init.lua 会创建 c_ep_generalset_msg_type

验证方法:补充 test/unit/test_endpoint/ 后执行 bingo test

3.3.3 SMBus CSR 样例

json
"Endpoint_1": {
    "TargetEid": "${Slot} |> expr(8 + $1)",
    "TargetPhyAddr": 73,
    "MessageType": 2,
    "MediumType": 128,
    "RefChip": "#/Chip_SmbusChip",
    "RetryLimit": 10,
    "RetryDelaySecond": 10
}

RetryLimit0 时,Set Endpoint ID 失败不会重试(retry_count >= retry_limit 立即返回)。


4. 日志说明

组件使用 mc.logging。进程日志出现在宿主 Skynet 日志中,模块关键字以 mctpd / mctp_engine / mctp_mdb_mgmt 等为主。

4.1 一键日志收集

mctp_app:init 注册 mc.mdb.micro_component.debug.on_dump,回调 mctp_dump:log_dump_cb。执行一键收集时生成 mctp_info,内容包括:

收集项内容
EID 表各 System 的 Endpoint 注册信息
路由表[MCTP ROUTE TABLE Info]EID / PHYADDR / PHYSICAL_MEDIA_IDENTIFIER
发送接收状态寄存器chipv1:0x0CD300240x0CD0E094;异常态包括 Invalid padding、PCIe backpressure

4.2 关键日志信息

级别典型日志含义
noticepmu status change to 1, OS Power ON主机上电,启动 discovery
noticeset owner_eid=..., owner_phy_addr=...收到 discovery,记录 IMU 地址
noticeset bmc_eid=..., bmc_phy_addr=...完成 Set Endpoint ID
noticestart update route table开始向 IMU 拉路由
noticeadd routing entry, phys_address=...新增路由并上树
noticeadd eid info / create endpoint为业务 Transport 创建 Endpoint
erroropen mctp device failed打开 mctp 驱动失败
errorrequest timeoutRequest 等待响应超时
errorMCTP discovery retry limit reachedSMBus Set EID 超过 RetryLimit
debug协议层 unmatch crc / check sum / incorrect payload size / unexpected fragment size / vdm header error响应被静默丢弃

5. 问题定界指南

5.1 典型问题定界

现象是否属于 mctpd判断要点
PCIe MCTP 报文发不通可能上电、discovery、路由、Transport、Endpoint 是否齐全
Request 超时可能request timeout 日志;对端无应答或校验丢包
路由中无预期 phyaddr可能需联合硬件IMU 未收到该设备 discovery
SMBus Endpoint 不上树可能CSR Binding/Chip/RetryLimit
RAID/网卡信息为空但 OS 已上电可能Binding 的 BmcEid/BmcPhyAddr 是否非 0
IPMI 命令失败本组件无 IPMI 接口

5.2 最小化复现与证据收集

  1. 记录 SystemId、phyaddr、MessageType、MediumType、模块名和 TimeoutMs
  2. busctl --user tree bmc.kepler.mctpd,检查 Binding、Routing、Endpoint。
  3. 抓取 Power ONset owner_eidset bmc_eidadd routing entrycreate endpoint 日志。
  4. 执行一键收集,保存 mctp_info
  5. 协议校验问题时检索 4.2 节 debug 关键字。

5.3 错误码速查表

资源协作错误mds/errors.json):见 2.3

内部返回码mctp_def.lua,Lua 引擎使用,不直接出现在 D-Bus 完成码中):

符号含义
E_OK0成功
E_TIMEOUT-1超时
E_ERROR-2一般错误
E_SEND_FAILED-3未发出(含上一请求未完成)

5.4 调试/复现方法

bash
busctl --user tree bmc.kepler.mctpd
busctl --user introspect bmc.kepler.mctpd /bmc/kepler/Systems/1/Mctp/MctpBinding
busctl --user call bmc.kepler.mctpd /bmc/kepler/Systems/1/Mctp/Routing \
    bmc.kepler.Release.Mctp.Routing GetRouteTable a{ss} 0
  • 对单个 Endpoint 调用 TraceMessage start 后复现收发。
  • PCIe 链路:BMC → mctp 驱动 → IMU → 对端。若需证明已交给驱动,在发往驱动前增加日志(维护讨论帖见特性文档)。
  • 单元 / 集成测试:test/unit/test/integration/test_app.lua

6. 常见问题解答

Q1:如何区分 SMBus Endpoint 和 PCIe Endpoint?

  • 问题描述:资源树上有多条 Endpoint,路径形态不同。
  • 一句话答案:PCIe 用纯 phyaddr;SMBus 用 position_phyaddr
  • 根因说明:SMBus 来自 CSR,9545 分路下同一总线可出现相同物理地址,必须用 GroupPosition 区分。
  • 解决方案:按路径判断,例如 .../Endpoint/171/4 为 PCIe,.../Endpoint/0101020E_29/4 为 SMBus。
  • 规避方案:创建时 PCIe 不要传 position,SMBus 必须传 CSR 的 GroupPosition。
  • 适用版本:1.130.12。

Q2:为什么 MCTP 报文发不通(PCIe)?

  • 问题描述:业务 Request 失败或一直超时。
  • 一句话答案:按上电 → discovery → 路由 → Transport → Endpoint 逐级确认。
  • 根因说明:未上电则不开驱动;无 IMU discovery 则无 EID;无路由则不创建 Endpoint;无 Transport 则 mctpd 不知道业务需要哪条通道。
  • 解决方案:查 Power ONset owner_eid / set bmc_eidadd routing entrycreate endpoint;确认调用方已注册 Transport 且 phyaddr 在路由内。
  • 规避方案:上电完成且 RoutingTableReady=true 后再 get_endpoint_and_transport
  • 适用版本:1.130.12。

Q3:Request 报超时,但抓包看到有响应?

  • 问题描述:对端已回包,业务仍收到 timeout。
  • 一句话答案:响应可能在协议校验失败后被丢弃。
  • 根因说明:CRC、checksum、分片长度、序号、VDM 头或 payload 长度不匹配时,C 层会打 debug 日志并丢弃,Lua 侧只能等到超时。
  • 解决方案:检索 nvme_protocol: unmatch crcncsi_protocol: check summctp_protocol: unexpected fragment sizepcie_vdm_protocol: vdm header error 等。
  • 规避方案:用 TraceMessage 对照收发内容与协议规范。
  • 适用版本:1.130.12。

Q4:get_endpoint_and_transport 一直不返回?

  • 问题描述:创建 Transport 后协程挂起。
  • 一句话答案:无超时版本会一直等到 Endpoint 创建信号。
  • 根因说明:对应 phyaddr 不在路由中时 mctpd 不会创建 Endpoint,skynet.wait() 不会结束。
  • 解决方案:改用 get_endpoint_and_transport_with_timeout;先确认 Routing 与 Binding。超时参数单位是 skynet.sleep 的 0.01 秒,不是毫秒。
  • 规避方案:仅在 RoutingTableReady 为 true 且目标 phyaddr 已上树后调用。
  • 适用版本:1.130.12。

Q5:SMBus Set Endpoint ID 反复失败?

  • 问题描述:日志出现 MCTP discovery failed, delay ... to retryretry limit reached
  • 一句话答案:检查 Chip、Binding 和 RetryLimit
  • 根因说明:Set EID 经 hwproxy 发到 Chip;失败次数达到 CSR RetryLimit(默认 0 表示不重试)后停止。
  • 解决方案:核对 BmcSMBusEid/BmcSMBusPhyAddr、Chip 地址位宽与总线拓扑,必要时增大 RetryLimit / RetryDelaySecond
  • 规避方案:硬件未就绪时不要把 RetryLimit 设得过大造成日志风暴。
  • 适用版本:1.130.12。