mctp over pcie通信超时

问题描述

通过调用mctp的Request接口来给设备发送mctp请求,结果返回超时失败;相关的超时时间设置为30s,且通过tracemctp命令可看到BMC Send完之后立刻就会有回复,而且是回收到4个回复;

问题

1.目前来看BMC侧是收到了对端的回复,但是应用侧接口没收到数据因此超时,请问该问题有哪些排查方向和手段?
2.如果BMC使用Send接口发送命令后,不接收对端的响应内容,是否会导致底层mctp数据堆积导致后续的应答也不会被传递到应用侧?

打印截图和log


tracemctp_155_126.txt (10.2 KB)

答案内容由AI生成,仅供参考:
根据您提供的信息,BMC侧通过 tracemctp 已确认收到了对端返回的4个响应报文,但应用层调用 mctp.Request 接口仍然超时(超时时间30s)。这表明响应报文在到达应用层之前可能被中间层(如 mctpd 驱动、路由模块或协议解析层)丢弃或未正确转发。以下是从知识和排查经验中总结的排查方向及手段:


1. 检查 mctpd 是否静默丢弃响应报文

现象:响应报文已经通过底层PCIe捕获(tracemctp 可见),但 mctpd 未将其递交给应用层。
可能原因:响应报文结构错误(如校验失败、格式不匹配),导致 mctpd 在协议解析阶段丢弃。

排查方法

  • 开启 mctpd 的详细日志(日志级别调整为 DEBUG 或 NOTICE),观察是否有类似“drop response”、“checksum mismatch”、“unexpected message type”等关键字。
  • 参考社区经验:

    “如果加上打印后发现报文收发都有打印,但是 BMC 还是报请求超时,则需要结合日志具体分析响应报文是否存在结构上的问题导致校验不通过,被 mctpd 静默丢弃。”
    (来源:文档片段 mctpd使用说明


2. 验证响应报文是否与请求匹配(消息ID / Tag)

问题:您收到4个回复,但可能这些回复并不是针对您发送的那条请求(例如请求和响应的消息ID、Tag不匹配),或者响应被 mctpd 路由到了其他协程。

排查方法

  • 对比 tracemctp 捕获的 请求报文响应报文,确认响应中的 Tag(或 MessageID)字段是否与请求一致。
  • 检查响应报文中的 destination EID 是否指向正确的 BMC EID(通常 BmcEid 为 10)。

3. 确认应用侧是否通过正确的协程/接口等待响应

说明mctp.Request 接口内部可能使用协程等待响应。若响应被另一个协程(如监听信号的回调)接收而未转发回调用协程,会导致超时。

排查方法

  • 检查调用 mctp.Request 的代码是否使用了正确的 context 参数(通常为 skynet 协程 ID)。
  • 查看应用日志中是否有其他协程同时收到了响应(例如通过“signal”订阅收到的响应数据),确认响应是否被错误分发。

4. 检查 MCTP 路由表是否完整

场景:即使对端回复了,但如果 mctpd 的路由表中没有正确的返回路径,响应可能无法被转发到 BMC 的应用层。

排查方法

  • 使用 mdbctl 查看 MCTP 路由状态:
    mdbctl lsobj /bmc/kepler/Systems/1/Mctp/Endpoint
    
  • 确认目标设备对应的 Endpoint 对象状态正常(Status=1 表示活跃)。
  • 参考故障案例:

    “PCIe协议的Endpoint消息链路为 BMC → mctp驱动 → IMU → Endpoint,若需要澄清非BMC问题,需要在BMC发往驱动前加下日志打印,确定BMC将报文给了驱动。”
    (来源:文档片段 mctpd使用说明


5. 使用 tracemctp 进行更细致的报文分析

您已经使用了 tracemctp 看到了基本收发,但可以进一步分析:

  • tracemctp 输出中观察 [SEND][RECV]时间戳,确认响应是立即返回还是有延迟。
  • 注意 tracemctp 是否只捕获了 PCIe 层的原始数据,而 mctpd 可能在此之上又做了一层封装。可以尝试在 mctpd 内部加打印,确认响应是否进入 mctpd 处理流程。

6. 检查底层驱动与硬件链路

虽然 tracemctp 捕获到了响应,但驱动层面可能仍有丢包或错误:

  • 检查 PCIe 硬件链路状态(Link Status、错误计数器)。
  • 在 BMC 的 mctp 驱动日志中查找 ERRWARN,例如:
    pciesw_mctp_wrapper ERROR: Endpoint.Request failed: -5(Input/output error)
    
    但您的场景是 收到响应后超时,所以驱动层面问题可能性较小。

7. 参考已知的 MctpRequestTimeout 案例分析

社区中有多例类似超时问题,其中 huangzhiyu 曾建议:

“用 tracemctp 看下报文有没有回响应的”
(来源:文档片段 topic 6008

而您已经确认收到了响应,因此重点转向响应为何未送达应用层。另一位用户 Net_Swift_Tianwen 也遇到过 kepler.mctpd.MctpRequestTimeout,并通过 tracemctp 成功捕获了 UBMC 的收发行为(来源:知识图谱)。说明该工具可用于定界,但需要结合日志进一步定位应用层未接收的原因。


总结排查步骤

步骤 操作 目的
1 开启 mctpd DEBUG 日志,检查有无 drop / error 信息 确认响应是否在 mctpd 被丢弃
2 比对请求和响应的 Tag / EID 字段 验证响应是否匹配本次请求
3 检查应用侧是否使用正确的协程调用接口 排除响应被其他协程截获
4 使用 mdbctl 查看 Endpoint 和路由表状态 确认路由路径正常
5 mctpd 源码中增加打印(日志级别 DEBUG) 跟踪响应从 PCIe 到应用层的完整流程
6 查看 mctp::request 函数的超时实现(默认15s) 确认您设置的30s是否被正确传递
7 如果以上均无效,可尝试使用 get_endpoint_and_transport_with_timeout 接口(提供超时参数)重新创建 Endpoint 后重试 排查根因是否为 Endpoint 创建阶段的问题

关键提示:根据 mctpd使用说明 文档,当报文收发均有打印但依然超时时,需优先分析响应报文的结构合法性(如长度、校验、字段偏移),因为 mctpd 可能会丢包却不在日志中明确提示。建议您将 tracemctp 捕获的完整报文与对端设备规范进行比对。

请求[SEND]报文字节序如下:
7F 00 00 03 ----- 对应协议规定4~7字节
07 10 00 72 ----- 对应协议规定0~3字节
C9 0C 0A 01 ----- 对应协议规定12~15字节
B4 1A 00 9B ----- 对应协议规定8~11字节
因硬件原因导致字节打印出来看着不大符合逻辑,但问题不大,原理是相通的


根据协议文档,C9的低3bit是msg tag,即1。响应报文中同一字节位置的值是88,即msg tag是0,这表示响应的报文并非发送期望的。

我们发送mctp报文是异步的,发完后挂起等待响应,不阻塞其他请求发送。当有响应返回时会根据报文的信息确认是哪个的响应。这个问题我建议多看看mctp协议文档,里面都有写每个字节对应什么信息。

更新下当前的现状:
流程1.BMC通过Request方法发送请求,对端进行响应,应用层正常处理接收的响应数据;

流程2. BMC通过Send方法发送请求,对端进行响应,由于返回的MsgTag不对,导致应用层无法处理数据

针对 流程2: BMC通过Request方法发送请求,对端进行响应,返回的MsgTag仍然不对,应用层无法处理数据

请问:
针对流程2来说因为当前对端的固件无法更新,因此不管用Send还是Request方法对端都会返回MsgTag不正确的应答数据,但是BMC必须要根据该应答的数据才能进行下一步流程,请问是否能有办法实现呢?

大佬,这边最新的进展如下:
我使用busctl --user monitor 抓取sw芯片对于的endpont的交互流程:



这三个是符合预期,能与tracemctp的打印对应起来;

tracemctp可以BMC收到SW最后发送过来的数据,但是在dbus monitor中一直没查看到上相关的signal或者信息;

通过手动发送MessageReceived的busctl命令,可以看到busctl monitor 中相关的打印并且bmc中注册的回调函数也正常触发;说明当前BMC注册的关于155 endPoint的MessageReceived的信号是成功的;

当前我这边怀疑很有可能是mctpd组件的问题,请帮忙确认分析下,多谢!

你们是怎么监听的,用的什么方法

主要是部分代码用的是openbmc的写法导致signal没注册上,因此对端发送了mctp 报文过来后底层没有发送signal,后续参考component_driver组件重写了代码就可以了

好吧