【求助】NC-SIoverMCTPoverSMBus超时(米尔3093开发板I2C-8)

问题描述

OpenUBMC通过MCTP over SMBus通信。MCTP Set EID命令通信正常。但是适配使用Hi182x的网卡NC-SI over MCTP,就出现“method call timeout”。

如下是在component_drivers的chip和bus层增加elog的现象:

1、增加log

在component_drivers的如下文件的函数中增加打印:

bus层:drivers/internal/bus/bus_i2c/i2c.cpp的bus_i2c::normal_read()增加打印。

chip层: drivers/internal/chip/chip_base/chip.cpp的chip_base::data_access()中增加打印。

2、 【正常】MCTP 控制报文交互正常,成功创建endpoint。

~ ~ $ busctl --user tree bmc.kepler.mctpd 中有

[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp
[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp/Endpoint
[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp/Endpoint/0103_50
[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp/Endpoint/0103_50/2
[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp/MctpBinding
[2026-03-16 16:24:16] /bmc/kepler/Systems/1/Mctp/Routing
[2026-03-16 16:24:16] /bmc/kepler/mctpd
[2026-03-16 16:24:16] /bmc/kepler/mctpd/MicroComponent
[2026-03-16 16:24:16] /bmc/kepler/mctpd/MicroComponent/Debug

3、【异常】使用Hi182x的网卡NC-SI驱动进行网卡管理,MCTPD报timeout超时:

3.1 修改component_drivers: drivers/pcie_nic_card/hisi/hi182x/hi182x_card.cpp中的hi182x_card::start_ncsi_protocol(),使得及时BDF是0,也创建mctp对象。

3.2 component_drivers: libraries/mctp/mctp.cpp中增加request日志。

最终app.log中的日志

a) NC-SI over MCTP发送Request

image

b) chip层写Request: (没有添加写Request的详细数据LOG)

image

c) chip和bus层读Response:bus层将网卡回应的数据全部读回了,chip层也从bus层全部拿到了Response。

d) 15秒后MCTP层报timeout:()

component_drivers主机libraries/mctp/mctp.cpp的mctp::request()函数中调用service->timeout_call()设置的超时是15秒

image

环境信息

  • 操作系统:Ubuntu 24.04

  • 软件版本:OpenUBMC2512,没有SP1。参考《南向适配网迅网卡经验分享》进行自己网卡的SMBus适配,使用的OpenUBMC master,网卡纯slave。MCTP over SMBus帧中“Command Code”是0x1F。

  • 硬件配置:米尔3093开发板,使用I2C-8,网卡csr中driver和mctp相关配置:

“Unit”: {
“Type”: “PCIeNicCard”,
“Name”: “PCIeNicCard_1”,
“Compatible”: [“hisi_1822”, “hisi_182x”]
},

“Chip_SmbusChip”: {
“Address”: 100,
“AddrWidth”: 1,
“OffsetWidth”: 1,
“WriteTmout”: 1000,
“ReadTmout”: 1000,
“HealthStatus”: 0,
“ReadRetryTimes”: 3,
“DrvWriteDelay”: 255,
“WriteInterval”:255,
“ReadInterval”:255
},

“MctpBinding_1”: {
“BmcSMBusEid”: 8,
“BmcSMBusPhyAddr”: 16
},

“Endpoint_1”: {
“TargetEid”: “${Slot} |> expr($1 + 8)”,
“TargetPhyAddr”: 50,
“MessageType”: 2,
“MediumType”: 128,
“RefChip”: “#/Chip_SmbusChip”
},

重现步骤

  1. 网卡先启动,准备好SMBus总线上应答MCTP控制报文Request、NC-SI over MCTP 标准/OEM命令

  2. 启动MYIR 3093开发板,直到启动完成,导出app.log分析

期望结果

NC-SI over MCTP的命令与MCTP控制报文一样能够及时送达MCTPD。

实际结果

貌似MCTPD及时收到了控制报文(Set EID)的Response,而NC-SI over MCTP的Response超时了。

尝试过的解决方案

1、怀疑I2C总线读到的数据长度(129个)超过了Response的实际程度、造成上层解析出问题。修改网卡侧的I2C读响应处理、在没有数据时就不回应,结果造成总线挂死。观察《南向适配网迅网卡经验分享》中的tracmctp的截图,其SMBus_OEM Capture [RECV]中也是读取了129字节。 推测这个长度应该不影响MCTPD的解析。

2、怀疑网卡SMBus响应读Response时没有回送MCTP over SMBus的“Command Code” 0x1F;但修改后MCTP的Set EID Response就过不去,创建Endpoint失败。

内容大小竟然有限制,补充1、3.1和3.2的修改截图:

bus层:drivers/internal/bus/bus_i2c/i2c.cpp的bus_i2c::normal_read()增加打印

chip层: drivers/internal/chip/chip_base/chip.cpp的chip_base::data_access()中增加打印。

~ ~ $ busctl --user tree bmc.kepler.mctpd 中有

3.1 修改component_drivers: drivers/pcie_nic_card/hisi/hi182x/hi182x_card.cpp中的hi182x_card::start_ncsi_protocol(),使得即使BDF是0,也创建mctp对象。

3.2 component_drivers: libraries/mctp/mctp.cpp中增加request日志。

答案内容由AI生成,仅供参考:

总结与结论

项目 分析结论
MCTP 控制通路是否正常 :white_check_mark: 正常,Set EID 成功,Endpoint 已创建
NC-SI 请求是否发出 :white_check_mark: 是,mctp::request() 成功触发
I2C 层是否收到响应 :white_check_mark: 是,返回 129 字节数据
根本原因定位 :red_question_mark: 主要在 MCTP 协议层处理逻辑,可能为:
1. 消息类型(MessageType)不匹配
2. MediumType 配置错误(SMBus_OEM 未支持)
3. smbus_write_read_service 未触发回调
4. mctpd 忽略了响应包
非 I2C 硬件问题 :white_check_mark: 排除物理层故障
点击此处查看详细分析解答

NC-SI over MCTP over SMBus 超时问题分析与排查

问题概述

用户在使用 米尔3093开发板(搭载 OpenUBMC 2512 版本)进行 Hi182x 网卡适配时,通过 MCTP over SMBus 协议进行 NC-SI(NC-SI over MCTP)通信出现 method call timeout 异常,表现为:

  • :white_check_mark: MCTP 控制报文(如 Set Endpoint ID)通信正常,能够成功创建 MCTP Endpoint;
  • :cross_mark: NC-SI over MCTP 命令调用失败mctpd 报告“method call timeout”(15秒超时);
  • :white_check_mark: 下层 I2C/SMBus 层已正确读取到完整的 Response 数据(129字节),I2C_Driver 返回正常;
  • :cross_mark: 但上层 mctpd 组件未正确处理响应,最终导致业务层请求超时。

该问题表现出典型的 “底层通信成功、上层协议处理失败” 的特征。


系统架构与通信流程回顾

1. 协议栈结构

+----------------------------+
|    NC-SI over MCTP (业务)   |
+----------------------------+
|      MCTP 协议层 (MCTPD)     |
+----------------------------+
|     SMBus 传输层 (I2C)      |
+----------------------------+
|       Hi182x 网卡 (Slave)    |
  • MCTP Over SMBus 是一种将 MCTP 协议封装在 SMBus Write-Read 事务中传输的机制。
  • 通信基于 SMBus 的 Block Write - Block Read Process Call 模式:
    • 写操作:发送 MCTP 请求帧(含 Command Code 0x1F)
    • 读操作:从设备读取 MCTP 响应帧(含返回数据)

2. 关键组件职责

组件 职责
I2C_Driver 执行物理 I2C 读写,返回原始字节流
Chip_SmbusChip_0103_dev 代表 SMBus 从设备节点,与网卡通信
mctpd 管理 MCTP Endpoint、处理 MCTP 消息编解码、超时控制
create_mctp_endpoint_for_smbus 创建 MCTP over SMBus 的通信 Endpoint

故障现象分析

:white_check_mark: 成功场景:MCTP Set EID 命令

根据日志,MCTP Set Endpoint ID 命令流程成功执行:

  1. 主机发送 MCTP 控制命令
  2. Chip_Smbuschip_0103 成功返回 129 字节响应
  3. mctpd 成功解析并创建 Endpoint
  4. /bmc/kepler/Systems/1/Mctp/Endpoint/0103_50 路径可见

:backhand_index_pointing_right: 表明 MCTP over SMBus 的基础通信链路是通的

:cross_mark: 异常场景:NC-SI over MCTP 超时

尽管:

  • I2C 层返回成功(I2c read success, data length: 129
  • 数据内容完整可读(hex dump 可见 MCTP 响应头 1e 65 ...
  • mctp::request() 设置了 15s 超时

但最终 mctpd 仍抛出异常:

daemon ERROR: mctp.cpp(76): mctp::request exception, shm method call timeout

可能原因深度分析

:white_check_mark: 已排查或非根本原因

排查项 结论
I2C 数据长度是否异常(129字节) :cross_mark: 否。129字节是标准 SMBus Block Read 最大长度(1 byte len + 128 byte data),符合规范;且《南向适配网迅网卡经验分享》中也出现相同长度。
是否缺少 Command Code(0x1F) :cross_mark: 否。实验表明若网卡不返回该字段,连 Set EID 都无法通过,而当前 Set EID 已成功。
总线冲突或挂死 :cross_mark: 否。总线可正常处理 Set EID 和 NC-SI 请求,无永久性故障。

:warning: 潜在根本原因分析

1. mctpd 上层未正确“唤醒”或“回调”完成请求

  • 现象:I2C_Driver 已收到 Response,但 mctpd 仍超时。
  • 原因推测:
    • mctpd 发起请求后进入等待状态。
    • SMBus 中断或事件处理完成后,未触发正确的 Response 回调函数
    • 可能是:smbus_write_read_service.lua 或其底层驱动未将 Response 正确传递给 mctpd 消息循环。
  • 支持证据:
    {"entity1": "mctpd", "entity2": "smbus_write_read_service.lua", "description": "mctpd relied on smbus_write_read_service.lua for SMBUS operations, which reported an invalid byte count."}
    

:backhand_index_pointing_right: 存在 smbus_write_read_service.lua 处理异常的历史记录,可能导致 Response 被丢弃或错误处理。


2. SMBus 响应帧格式与 mctpd 解析器不兼容

虽然数据量为129字节,但其内容结构需严格符合 MCTP over SMBus + NC-SI 的封装规范。

查看 NC-SI 响应示例首字节:

1e 65 01 08 ...
  • 0x1E = 包头长度(Length)
  • 0x65 = MCTP_Message_Type = MCTP_MESSAGE_TYPE_NCSI (0x02),但此处值为 0x65
  • 问题:MCTP 消息类型字段异常

标准定义:

  • MCTP_MESSAGE_TYPE_NCSI = 0x02
  • 应在 MCTP Header 中明确指出

但实际抓包显示可能未正确设置此字段,或厂商私有编码未被 mctpd 正确识别。

:backhand_index_pointing_right:mctpd 仅监听类型为 0x02 的消息,而 Hi182x 返回了非标准类型,则响应会被忽略 → 导致“看不见响应”从而超时。


3. Endpoint 配置错误,medium_type 或 msg_type 不匹配

关键配置:

"Endpoint_1": {
  "TargetEid": "...",
  "TargetPhyAddr": 50,
  "MessageType": 2,           // 应为 MCTP_MESSAGE_TYPE_NCSI
  "MediumType": 128,          // 128 = SMBus_OEM?
  "RefChip": "#/Chip_SmbusChip"
}
  • MessageType=2 :check_mark: 正确(对应 NC-SI over MCTP)
  • MediumType=128 :red_question_mark: 值为 SMBus_OEM?需确认 OpenUBMC 是否支持

根据文档:MCTP 支持 PCIe(0x0F)SMBus(0x02)SMBus_OEM(0x80) [注意:0x80 是 128]

:red_exclamation_mark: 若 Hi182x 使用的是 SMBus_OEM (128) 协议模式,而 mctpd 的处理逻辑未启用或不兼容该模式,则无法解包。


4. 请求/响应事件未绑定同一 Transaction Context

  • mctpd 可能使用 Transaction IDSequence Number 匹配请求与响应。
  • 若响应中未携带有效 Sequence Number,或编码格式不一致(如大端/小端),可能导致无法关联响应。
  • 特别是 Hi182x 的实现若与 Mellanox / Broadcom 等主流网卡不符,容易出现兼容性问题。

5. 中断延迟导致 timeout_call 提前触发

  • 用户指出 timeout_call 设置为 15s,但日志显示实际在短时间内即超时。
  • 可能是:
    • timeout_call 参数传参错误导致实际超时极短;
    • 或 D-Bus 异步调用机制被阻塞,事件未能及时派发。

解决方案建议

:white_check_mark: 方案一:验证并修复 MCTP 消息类型字段

目标:确保网卡返回的 MCTP 响应中 Message Type 字段为标准 0x02(NC-SI)。

操作步骤

  1. 使用 tracemctp 工具捕获 MCTP over SMBus 流量:
    tracemctp start
    # 执行 NC-SI 命令
    tracemctp stop
    
  2. 查看 Response 是否携带有效的 MCTP Header,尤其是:
    • Byte offset 2: IC / TO (usually 0x01)
    • Byte offset 3: Packet SNA / Header Reserved
    • Byte offset 4: Message Type → 必须为 0x02
  3. 若非 0x02,请调整网卡固件或驱动将其设为标准类型。

:white_check_mark: 方案二:检查 MediumType 配置兼容性

目标:确认 MediumType=128 是否为 OpenUBMC 支持的 SMBus_OEM 模式。

操作步骤

  1. 修改 Endpoint 配置尝试不同组合:
    "MediumType": 2   // 尝试标准 SMBus 而非 SMBus_OEM
    
  2. 重新启动 mctpd,测试 NC-SI 命令是否成功。
  3. 参考:
    | 协议               | MediumType |
    |--------------------|------------|
    | MCTP over PCIe     | 0x0F       |
    | MCTP over SMBus    | 0x02       |
    | MCTP over SMBus_OEM| 0x80 (128) |
    

:white_check_mark: 方案三:调试 smbus_write_read_service.lua

目标:确认响应是否在 Lua 层被正确接收并转发给 mctpd

操作步骤

  1. smbus_write_read_service.lua 中增加日志输出,打印所有 read 成功后的 buffer;
  2. 特别关注:
    if #data > 0 then
        print("SMBus READ -> ", to_hex(data))
    end
    
  3. 若读取到了数据但未上报给 mctpd,说明存在事件缺失。

:white_check_mark: 方案四:启用 mctpd 内部 trace 日志

目标:观察 mctpd 是否收到了 Response 消息。

操作

  1. 启用 mctpd 详细日志:
    busctl set-property bmc.kepler.mctpd.Debug Level s debug
    
  2. 或修改 init.lua 中 log level 为 DEBUG
  3. 检查日志中是否有类似:
    • mctp_engine: received packet from phy_addr=50
    • unhandled message type: 0x65

:white_check_mark: 方案五:升级或同步适配代码至最新稳定版本

  • 用户使用的是 master 分支,可能存在未修复 bug。
  • 建议:
    • 升级到官方发布的稳定版本(如含 SP1 的 2512);
    • 或对比《南向适配网迅网卡经验分享》文档中的 Endpoint 配置与驱动代码,保证一致性。

总结与结论

项目 分析结论
MCTP 控制通路是否正常 :white_check_mark: 正常,Set EID 成功,Endpoint 已创建
NC-SI 请求是否发出 :white_check_mark: 是,mctp::request() 成功触发
I2C 层是否收到响应 :white_check_mark: 是,返回 129 字节数据
根本原因定位 :red_question_mark: 主要在 MCTP 协议层处理逻辑,可能为:
1. 消息类型(MessageType)不匹配
2. MediumType 配置错误(SMBus_OEM 未支持)
3. smbus_write_read_service 未触发回调
4. mctpd 忽略了响应包
非 I2C 硬件问题 :white_check_mark: 排除物理层故障

推荐解决路径

  1. 立即行动
    • 使用 tracemctp 抓包分析 Response 的 MCTP Header。
  2. 核心验证
    • 确保 Message Type = 0x02,若非,请修改网卡行为。
  3. 配置调整
    • 尝试设置 MediumType = 2(标准 SMBus)替代 128
  4. 日志增强
    • smbus_write_read_service.luamctpd 中增加 trace 输出。
  5. 最终确认
    • 若上述无效,可尝试将 Hi182x 替换为已知兼容的网卡(如网迅 WX)做横向对比。

:hammer_and_wrench: 建议反馈给社区:百信-罗昊 等贡献者在类似问题(如 Topic 4949)中有丰富经验,可在其帖下引用此案例寻求进一步支持。

是必现的吗

必现的

请教《南向适配网迅网卡经验分享》的作者 @net_swift_tianwen 他没遇到这个情况。

按理来说,MCTP的控制报文Set EID能通,NC-SI over MCTP over SMBus,不应该在MCTP层出错。

MCTPD的源码没有开源,自己也没办法分析原因。:weary_face:

我正好在定位一个差不多的问题,也是mctp不通的,不过他那个是pcie的,而且是概率超时。我定位下那个问题的原因,再看看是不是同类问题。

好的,万分感谢。

补充OpenUBMC的启动app.log

app-260316-1.zip (38.7 KB)

好的,我看下

你好!这个链接的信息可能对你解决本问题有所帮助,请参考,谢谢!

我看了下日志,发现单次返回的数据负载超过了64字节,BMC的mctp传输单元是64字节,超过导致数据解封失败。导致部分命令失败。

当前是使用的SMBus_OEM,都是BMC主动发送请求、读取应答。请问对于超过64字节的应答、需要网卡这么怎么应答才好?

我记得之前SMBus_OEM的命令基本不会超过64字节,是有什么特殊的命令吗?

我是在参考《南向适配网迅网卡经验分享》,基于MYIR3093开发板I2C_8实现对我们自己网卡的NC-SI over MCTP over SMBus/I2C的访问。

当前BMC侧结合参考component_drivers组件的Hisi182x的csr添加我们自己网卡配置、直接使用的“Hi182x”驱动(中间创建mctp时直接注释掉对PCIe BDF的检查、强制创建了)。然后Hi182x驱动就有华为的NC-SI OEM命令发出来、NC-SI OEM的应答好些都超过64字节了。

请问你前面回复里说的 “发现单次返回的数据负载超过了64字节”,是在哪个LOG文件里、关键词是什么的? 我调整一下我们网卡应答、硬把超过64字节的NC-SI OEM应答在MCTP层切割开试试(通过设置MCTP头部的SOM、EOM)。

smbus oem response byte count is invalid

能帮看看这个NCSI over MCTP over SMBus**_OEM**的报文内容是不是有错么? 第1个报文就超时了,在app.log中这个时间内页没找到mctpd或者smbus的相关ERROR信息。搞不清哪个字段有问题

BMC SMBus slave address:0x10 (7bits), EID: 0x08

网卡SMbus slave address:0x32 (7bits), EID 0x1E

**BMC发送的请求报文:**64 1f 1e 21 01 1e 08 c8 02 00 01 00 01 01 1f 00 04 00 00 00 00 00 00 00 00 00 00 00 01 ff ff fe da 7b — 这个在app.log的第1347行,我字节加的i2c.cpp打印。

**网卡响应BMC读应答的内容:**1e 65 01 08 1e c0 02 00 01 00 01 81 1f 00 04 00 00 00 00 00 00 00 00 00 00 00 00 ff ff 7e db b0 — 这个在app.log的第1359行,不含最前面的64 1f。 最后的0xb0是按照最前面是0x20 1f …计算的

这个报文是component_drivers里pcie_nic_card下网卡驱动xxx_card.cpp中start_ncsi_protocol()函数里执行的disable_hardware_arbittration(id, 0x1F), 发送NC-SI的“select package”命令。

最终这个mctp超时在25秒后,app.log的第1960行。(不知道为啥不是component_driver的mctp.cpp中函数mctp::request()里设置的15秒 )

有2个想不通的疑点:

  1. 如果是SMBus层CRC计算不对,按理说最前面的响应BMC的Set EID不应该通过、成功创建网卡的Endpoint设备树。 app.log第1315行 mctpd在收到Set EID的响应报文后创建Endpoint。
  2. 南向适配网迅网卡经验分享》中有一个“SMBus_OEM capture [RECV]”截图,我对里面的报文验算最后的CRC,不管怎么换第1个字节的值(0x20、0x21、0x92、0x93),都没算到0x3E。使用的在线CRC计算器(链接),查看“CRC8/SMBUS”的计算值,第一次用需要往下拉、或者网页内ctrl+F搜索一下SMBUS。

附件和说明:

20260409.zip (84.5 KB)

《COM3-MYIR(2026-4-9 14_48_43).txt》 是MYIR3093的串口LOG,现在tracemctp可以抓到应答报文了。不过里面没有上面的报文,上面报文出现得比较早,没来得及进命令行开启trace。

《COM5-网卡(2026-4-9 14_50_20).txt》是我们网卡MCU在SMBus的上被写Request、被读Response的内容。

期望您的帮助,谢谢

crc计算的时候是在前面补3个字节,地址(64) 命令字(1F)地址|1(65).也就是64 1f 65 1e 65 01 08 1e c0 02 00 01 00 01 81 1f 00 04 00 00 00 00 00 00 00 00 00 00 00 00 ff ff 7e db b0,最后计算的crc

:crab::crab:

网卡侧根据这个算法计算待读取SMBus数据的CRC,在BMC层的NC-SI层能收到内容了。