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_adapter、storage)通过打包进 /opt/bmc/lualib 的 mctp_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创建 PCIeEndpoint。 - 为 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 关键术语表
| 术语 | 解释 |
|---|---|
| MCTP | Management Component Transport Protocol,独立于物理介质的管理部件传输协议。 |
| EID | Endpoint 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.service 在 framework.service 之后启动,依赖 dbus.service、framework.service、persistence.service,工作目录 /opt/bmc/apps/mctpd。构建依赖 libmc4lua、persistence;构建选项 chipv2_enable 选择 chipv1 / chipv2 驱动配置。
2. API 使用说明与示例
对外发布的 API 为资源协作接口,服务名 bmc.kepler.mctpd。路径中的 SystemId 默认取 1(实际集合来自 bmc.kepler.Managers.SOC.Env 的 SystemIds)。均可通过 busctl / mdbctl 调试。
方法首参 a{ss} 为框架调用上下文;命令行调试可传空字典 0。权限取自 mds/model.json(默认 ConfigureSelf;TraceMessage 为 DiagnoseMgmt)。
# 查看资源协作接口
busctl --user tree bmc.kepler.mctpd目前可创建的 Endpoint 如下。未在表中的 MessageType 会创建通用 Endpoint,由调用方自行封装上层协议。
| 名称 | MessageTypeCode | 支持的物理层以及 MediumTypeCode | 代码中描述 |
|---|---|---|---|
| MCTP Control | 0x00 | PCIe(0x0F)、SMBus(0x02)、SMBus_OEM(0x80) | MCTP_MESSAGE_TYPE_MCTP_CTRL |
| Platform Level Data Model | 0x01 | 同上 | MCTP_MESSAGE_TYPE_PLDM |
| NC-SI over MCTP | 0x02 | 同上 | MCTP_MESSAGE_TYPE_NCSI |
| NVMe over MCTP | 0x04 | 同上 | MCTP_MESSAGE_TYPE_NVME |
| SPDM over MCTP | 0x05 | 同上 | MCTP_MESSAGE_TYPE_SPDM |
| Vendor Defined-PCI | 0x7E | 同上 | MCTP_MESSAGE_TYPE_VDPCI |
mctp_lib 还导出 MCTP_MESSAGE_TYPE_ETHERNET(0x03)、MCTP_MESSAGE_TYPE_SECUREDMSG(0x06)、MCTP_MESSAGE_TYPE_VDIANA(0x7F)常量,但仓库未给出对应专用 Endpoint 类。
2.1 bmc.kepler.Systems.Mctp.MctpBinding.PCIe
功能说明
查询 PCIe 介质上 Owner(IMU/ME)与 BMC 的 EID、物理地址,以及自发现 / 路由表就绪状态。
路径:/bmc/kepler/Systems/${SystemId}/Mctp/MctpBinding
参数说明
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
OwnerEid | y | 只读 | ME/IMU 的 EID |
OwnerPhyAddr | q | 只读 | ME/IMU 的 PCIe 物理地址 |
BmcEid | y | 只读 | BMC 的 EID |
BmcPhyAddr | q | 只读 | BMC 的 PCIe 物理地址 |
DiscoverFinished | b | 只读 | 是否完成过 Endpoint Discovery |
RoutingTableReady | b | 只读 | 路由表是否就绪 |
返回值与异常
属性只读。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 的依赖。
调试示例
busctl --user introspect bmc.kepler.mctpd \
/bmc/kepler/Systems/1/Mctp/MctpBindinglocal mctp_lib = require('mctp_lib')
local obj = mctp_lib.get_mctp_pcie_binding(bus) -- OS 未上电时可能为 nil2.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:BmcSMBusEid) | y | CSR 配置 | SMBus 协议使用的 BMC EID |
BmcPhyAddr(CSR:BmcSMBusPhyAddr) | y | CSR 配置 | SMBus 协议使用的 BMC 物理地址 |
返回值与异常
由 CSR 的 MctpBinding_* 对象加载;未配置时 SMBus Endpoint 无法完成 Set Endpoint ID。
应用场景
网卡/硬盘走 SMBus 或 SMBus_OEM 时,与 Endpoint_*、Chip_* 一起出现在机型 CSR 中。
限制条件
SMBus 类型 Endpoint 还需关联 bmc.kepler.Chip.BlockIO(RefChip)。插在硬盘背板上时,CPLD 需支持 SMBus 通信;SMBus_OEM 不依赖 CPLD 版本(见组件 README)。
调试示例
"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为 CSRGroupPosition,用于区分同一总线上相同物理地址)
参数说明
| 属性 | 类型 | 读写 | 默认值 | 说明 |
|---|---|---|---|---|
ServiceName | s | 只读 | — | 注册通道的模块名 |
TargetEid | y | 只读 / CSR | — | 对端 EID |
TargetPhyAddr | q | 只读 / CSR | — | 对端物理地址 |
MessageType | y | 只读 / CSR | — | 上层协议类型 |
MediumType | y | 只读 / CSR | 15(0x0F) | 0x02 SMBus,0x0F PCIe,0x80 SMBus_OEM |
Status | y | 只读 | 0 | 0 初始;1 Endpoint 发现完成。发出 PropertiesChanged |
CSR 额外属性(不在 PCIeEndpoint 接口上,属于对象模型):
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
RefChip | U8[] | — | 关联 bmc.kepler.Chip.BlockIO |
RetryLimit | U32 | 0 | SMBus Set Endpoint ID 失败重试上限 |
RetryDelaySecond | U32 | 10 | 重试间隔(秒) |
| 方法 | D-Bus 签名 | 入参 | 出参 | 说明 |
|---|---|---|---|---|
Request | a{ss}ayia{ss}a{ss} → ay | 上下文、Data、TimeoutMs、ReqHeaderFileds、RspHeaderValidators | Data | 发送并等待响应 |
Send | a{ss}aya{ss} → 空 | 上下文、Data、ReqHeaderFileds | 无 | 只发送,不等待响应 |
| 信号 | 签名 | 说明 |
|---|---|---|
OnMessage | a{ss}ay | Endpoint 收到数据时发出 |
MessageReceived | a{ss}ay | 与 OnMessage 同时转发同一份 Data |
ReqHeaderFileds / RspHeaderValidators 为 a{ss}。当前实现支持:
| 协议 | 请求头字段(填充) | 响应头校验 |
|---|---|---|
| NC-SI | PacketType、ChannelId、PackageId | PacketType |
| NVMe | IC、MsgType、CmdSlot | MsgType(README 说明) |
| PLDM | PldmType、CommandCode | CommandCode |
| SPDM | 可由 mctpd 封装,也可由调用方自带报文(不传 ctx) | 见 README |
| VDPCI | 厂商头已包含在 Data 中,ctx 传 {} | {} |
返回值与异常
Request 成功返回响应字节数组。失败时抛异常,消息定义见 mds/errors.json:
| 错误名 | HTTP | IPMI | 含义 |
|---|---|---|---|
kepler.mctpd.InvalidMctpRequest | 400 | 0xFF | 请求非法 |
kepler.mctpd.MctpEndpointReset | 400 | 0xFF | Endpoint 已复位 |
kepler.mctpd.MctpRequestTimeout | 400 | 0xFF | 请求超时 |
kepler.mctpd.MctpInvalidResponse | 400 | 0xFF | 响应 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。
Request的TimeoutMs单位为毫秒(Lua Endpoint 实现传入mctp_engine:request)。
调试示例
-- 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)busctl --user introspect bmc.kepler.mctpd \
/bmc/kepler/Systems/1/Mctp/Endpoint/150/22.4 bmc.kepler.Release.Mctp
功能说明
跟踪指定 Endpoint 的收发报文(维护 CLI tracemctp)。
路径:与 Endpoint 对象相同,/bmc/kepler/Systems/${SystemId}/Mctp/Endpoint/${Id}/${MsgType}
参数说明
| 方法 | 签名 | 入参 | 说明 |
|---|---|---|---|
TraceMessage | a{ss}s → 空 | Action:start / stop | 开始或停止跟踪该 Endpoint 报文 |
权限:DiagnoseMgmt。
返回值与异常
对象路径无法解析为已知 Endpoint 时抛错(unknown endpoint path / unknown endpoint)。
应用场景
一键收集或维护 CLI 抓取某 Endpoint 收发数据。
限制条件
仅对已创建的 Endpoint 生效;PCIe 路径在 worker 收包处按 is_trace 打印,SMBus 路径在 smbus 协议分发处打印。
调试示例
busctl --user call bmc.kepler.mctpd \
/bmc/kepler/Systems/1/Mctp/Endpoint/150/2 \
bmc.kepler.Release.Mctp TraceMessage a{ss}s 0 start2.5 bmc.kepler.Systems.Mctp.PCIeRoutingEntry
功能说明
单条 MCTP 路由表项,由 IMU 返回的路由信息上树。
路径:/bmc/kepler/Systems/${SystemId}/Mctp/Routing/${phyaddr}
参数说明
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
EidRangeSize | y | 只读 | EID 范围大小 |
StartingEid | y | 只读 | 起始 EID |
EntryType | y | 只读 | 路由类型 |
PhysTransportBindingId | y | 只读 | 物理通道绑定 ID |
MediaTypeId | y | 只读 | 物理介质类型 |
PhysAddress | ay | 只读 | 物理地址(Endpoint 条目仅一个地址) |
返回值与异常
只读;路由删除时对象下树。
应用场景
确认网卡、盘、RAID 等设备的 phyaddr 是否已出现在路由中。没有对应路由时,mctpd 不会为该地址创建 PCIe Endpoint。
限制条件
PCIe 路由来自上电后 IMU 的 Get Routing Table;硬件未响应 discovery 则不会出现对应条目。
调试示例
busctl --user tree bmc.kepler.mctpd | grep Routing2.6 bmc.kepler.Release.Mctp.Routing
功能说明
一次性导出当前路由表。
路径:/bmc/kepler/Systems/${SystemId}/Mctp/Routing
参数说明
| 方法 | 签名 | 出参 | 说明 |
|---|---|---|---|
GetRouteTable | a{ss} → aa{ss} | Result:字典数组 | 每项含 EID、PHYADDR、PHYSICAL_MEDIA_IDENTIFIER |
返回值与异常
成功返回数组;字段值为十六进制字符串,例如 EID=0x09、PHYADDR=0x0096、PHYSICAL_MEDIA_IDENTIFIER=0x0f(...)。
应用场景
维护诊断、一键收集之外的在线查询。
限制条件
未上电或路由未就绪时结果可能为空。
调试示例
busctl --user call bmc.kepler.mctpd \
/bmc/kepler/Systems/1/Mctp/Routing \
bmc.kepler.Release.Mctp.Routing GetRouteTable a{ss} 02.7 bmc.kepler.Debug.Mctp
功能说明
设置 MCTP 传输单元大小(默认实现值为 MCTP_MSG_TRANSFER_UNIT_SIZE = 64)。
路径:/bmc/kepler/Systems/${SystemId}/Mctp
参数说明
| 方法 | 签名 | 入参 | 说明 |
|---|---|---|---|
SetTransmissionUnitSize | a{ss}q → 空 | Size:U16 | 设置分帧传输单元大小 |
成功后写 notice 日志,并记录 log:operation。
返回值与异常
成功无返回。非法上下文由框架校验。
应用场景
调试分帧或适配超大 NVMe-MI 报文时调整 MTU。
限制条件
调试接口,变更立即作用于该 System 的 mctp_protocol.max_size。取值范围源码未覆盖额外校验。
调试示例
busctl --user call bmc.kepler.mctpd \
/bmc/kepler/Systems/1/Mctp \
bmc.kepler.Debug.Mctp SetTransmissionUnitSize a{ss}q 0 642.8 bmc.kepler.Systems.Mctp.PCIeTransport
功能说明
该接口由调用方进程通过 mctp_lib 注册,不由 mctpd 进程创建。mctpd 订阅 InterfacesAdded,仅当 TargetPhyAddr 已在路由表中时创建对应 Endpoint。
路径:/bmc/kepler/Systems/${SystemId}/Mctp/Transport/${phyaddr|position_phyaddr}/${MsgType}(位于调用方资源树)
参数说明
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
ServiceName | s | 只读 | 注册通道的模块名 |
TargetEid | y | 只读 | 对端 EID(创建时先填 0,Endpoint 就绪后由 mctp_lib 回写) |
TargetPhyAddr | q | 只读 | 对端物理地址 |
MessageType | y | 只读 | 协议类型 |
返回值与异常
无方法。调用方需在 mds/service.json 中声明 bmc.kepler.Systems.Mctp.PCIeTransport 与 bmc.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 不传 position | endpoint, transport | 创建 Transport 并等待 Endpoint |
get_endpoint_and_transport_with_timeout(bus, module_name, ep_info, timeout) | ep_info 含 phy_addr/msg_type/position/system_id | 同上 | 带等待超时 |
get_mctp_pcie_binding(bus, system_id) | — | Binding 或 nil | BmcEid 与 BmcPhyAddr 均非 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 BDF | uint16 | 网络字节序:device:5 | function:3 | bus:8 |
导出常量:MCTP_MESSAGE_TYPE_*、PHY_MEDIUM_PCI / PHY_MEDIUM_SMBUS / PHY_MEDIUM_SMBUS_OEM、ENDPOINT_IS_DISCOVERY、接口名 PCIE_ENDPOINT_INTERFACE 等。
get_endpoint_and_transport_with_timeout 的 timeout 传入 skynet.sleep,单位为 0.01 秒。缺省或 timeout<=0 时使用 100 * 60 * 5(5 分钟)。无超时版本会 skynet.wait() 直到 Endpoint 创建信号。
返回值与异常
等待 Endpoint 超时或信号不匹配时 error('unmatch endpoint creation signal...')。ep_info 为 nil 时 error('get endpoint and transport failed, endpoint info is nil')。
应用场景
业务组件在检测到主机上电、MCTP Binding 就绪后建立通道。
限制条件
必须在调用方 service.json 中引用对应接口。SMBus 必须传入 CSR GroupPosition。
调试示例
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/chipv1 与 chipv2 及 Conan 选项 chipv2_enable 切换。机型通过 CSR 增加 SMBus Endpoint,无需改 mctpd 代码。
3.2 扩展点说明
- 新上层协议 Endpoint:在
src/lualib/mctp_endpoints/新增模块,于init.lua的c_mctp_endpoints:init中register。 - CSR SMBus Endpoint:配置
MctpBinding_*、Endpoint_*、Chip_*,并在 ManagementTopology 总线下挂 Chip。 - hwproxy SMBus 命令:
include/hwproxy/plugins/smbus/cmds.lua。 - 驱动/dump 配置:
src/config/chipv1|chipv2/mctp_drv_config.lua、mctp_dump.lua。 - C 协议栈:
src/lualib-src/libmctp/的 upper / transport / physical 分层(protocol::pop/push)。不要手工修改带生成标记的gen/文件。
3.3 二次开发指导
3.3.1 业务侧接入(推荐)
- 在调用方
mds/service.json声明bmc.kepler.Systems.Mctp.PCIeTransport、bmc.kepler.Systems.Mctp.PCIeEndpoint(查询 Binding 时再声明MctpBinding.PCIe)。 local mctp_lib = require('mctp_lib')。- PCIe:用
bdf_to_phy_addr得到 phyaddr,调用get_endpoint_and_transport。 - 用
pcall(endpoint.Request, ...)收发;NC-SI / NVMe / PLDM 优先走libmgmt_protocol。
验证方法:busctl --user tree bmc.kepler.mctpd 看到对应 Endpoint;日志出现 add eid info、create endpoint。
注意事项:没有路由就不会创建 PCIe Endpoint;不要假设 Transport 一注册 Endpoint 立刻存在。
3.3.2 新增 MessageType 专用 Endpoint
在 ep_factory[msg_type] 注册实现 request / send / get_msg_type 的类。未注册时 init.lua 会创建 c_ep_general 并 set_msg_type。
验证方法:补充 test/unit/test_endpoint/ 后执行 bingo test。
3.3.3 SMBus CSR 样例
"Endpoint_1": {
"TargetEid": "${Slot} |> expr(8 + $1)",
"TargetPhyAddr": 73,
"MessageType": 2,
"MediumType": 128,
"RefChip": "#/Chip_SmbusChip",
"RetryLimit": 10,
"RetryDelaySecond": 10
}RetryLimit 为 0 时,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:0x0CD30024、0x0CD0E094;异常态包括 Invalid padding、PCIe backpressure |
4.2 关键日志信息
| 级别 | 典型日志 | 含义 |
|---|---|---|
| notice | pmu status change to 1, OS Power ON | 主机上电,启动 discovery |
| notice | set owner_eid=..., owner_phy_addr=... | 收到 discovery,记录 IMU 地址 |
| notice | set bmc_eid=..., bmc_phy_addr=... | 完成 Set Endpoint ID |
| notice | start update route table | 开始向 IMU 拉路由 |
| notice | add routing entry, phys_address=... | 新增路由并上树 |
| notice | add eid info / create endpoint | 为业务 Transport 创建 Endpoint |
| error | open mctp device failed | 打开 mctp 驱动失败 |
| error | request timeout | Request 等待响应超时 |
| error | MCTP discovery retry limit reached | SMBus 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 最小化复现与证据收集
- 记录 SystemId、phyaddr、MessageType、MediumType、模块名和
TimeoutMs。 busctl --user tree bmc.kepler.mctpd,检查 Binding、Routing、Endpoint。- 抓取
Power ON、set owner_eid、set bmc_eid、add routing entry、create endpoint日志。 - 执行一键收集,保存
mctp_info。 - 协议校验问题时检索 4.2 节 debug 关键字。
5.3 错误码速查表
资源协作错误(mds/errors.json):见 2.3。
内部返回码(mctp_def.lua,Lua 引擎使用,不直接出现在 D-Bus 完成码中):
| 符号 | 值 | 含义 |
|---|---|---|
E_OK | 0 | 成功 |
E_TIMEOUT | -1 | 超时 |
E_ERROR | -2 | 一般错误 |
E_SEND_FAILED | -3 | 未发出(含上一请求未完成) |
5.4 调试/复现方法
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 ON、set owner_eid/set bmc_eid、add routing entry、create 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 crc、ncsi_protocol: check sum、mctp_protocol: unexpected fragment size、pcie_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 retry或retry limit reached。 - 一句话答案:检查 Chip、Binding 和
RetryLimit。 - 根因说明:Set EID 经 hwproxy 发到 Chip;失败次数达到 CSR
RetryLimit(默认 0 表示不重试)后停止。 - 解决方案:核对
BmcSMBusEid/BmcSMBusPhyAddr、Chip 地址位宽与总线拓扑,必要时增大RetryLimit/RetryDelaySecond。 - 规避方案:硬件未就绪时不要把
RetryLimit设得过大造成日志风暴。 - 适用版本:1.130.12。