南向 IPMI 追踪能力

概述

南向 IPMI 追踪(TraceIpmi)用于在 BMC 与主机/ME 等南向设备通信时,按通道、NetFn、Cmd 等条件抓取 BT、IPMB 等介质上的原始报文,并输出为可读的十六进制日志,便于现场调试与问题定位。

模块核心组成:

  • trace_ipmi_obj:追踪能力对象,承载配置属性与报文处理逻辑
  • ipmi_trace_hook:传输层与追踪对象之间的轻量回调桥接
  • channel_context:在 send/recv 路径上采集线路上下文并上报 hook

追踪仅在显式开启后生效,默认关闭,不影响正常 IPMI 通信性能。传输层架构见 transport_architecture.md


总体设计

┌─────────────────────────────────────────────────────────────────────┐
│                         trace_ipmi_obj                              │
│  - Trace 接口配置(通道 / NetFn / Cmd / 日志类型)                    │
│  - monitor_ipmi_message:过滤、格式化、敏感掩码、落盘/本地日志          │
└───────────────────────────────┬─────────────────────────────────────┘
                                │ on_register 注册回调
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                      ipmi_trace_hook(全局回调)                      │
│  set_ipmi_trace_callback / report_ipmi_trace                        │
└───────────────────────────────┬─────────────────────────────────────┘
                                │ send / recv 路径调用
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                       channel_context                               │
│  process_send_data  → serialize 后 report(trace_direction::send)   │
│  read_dev_data_loop → 原始字节 report(trace_direction::recv)        │
└───────────────────────────────┬─────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│              bt_service / ipmb_service + driver + protocol          │
└─────────────────────────────────────────────────────────────────────┘

设计要点

  • Hook 与传输层解耦:channel_context 只调用 report_ipmi_trace,不直接依赖 trace_ipmi_obj
  • 对象自注册:trace_ipmi_obj::on_register() 向 hook 注册 monitor_ipmi_message 回调
  • 线路上下文与逻辑消息分离:trace_data 为完整线路字节流;ipmi_message 提供 NetFn/Cmd、ctx 等逻辑字段

TraceIpmi 对象

Class Name: TraceIpmi Object Path: /bmc/kepler/Debug/IpmiCore/TraceIpmi

对象通过 discover_objects() 注册到对象自发现表,由 MDS/CSR 配置实例化。

Interfaces

Interface Description
bmc.kepler.Debug.IpmiCore.TraceIpmi 南向追踪配置与 Trace 方法

Properties (bmc.kepler.Debug.IpmiCore.TraceIpmi)

Property Type Default Description
EnableTrace bool false 追踪使能开关,由 Trace 方法写入
Channel string "" 追踪通道,支持 btipmbedmaipmbeth
Netfn uint8 0 过滤用 NetFn;0xFF 表示不过滤
Cmd uint8 0 过滤用 Cmd;0xFF 表示不过滤
Filter string "" 预留过滤字段,当前以十六进制字符串形式保存(如 0a-ff-00-
LogType string "" 日志输出方式:file 写文件,local 本地日志

属性均为只读暴露,配置统一通过 Trace 方法下发。

Methods (bmc.kepler.Debug.IpmiCore.TraceIpmi)

Method Parameters Return Description
Trace EnableTrace, Channel, Netfn, Cmd, Filter, LogType void 配置并开启/关闭南向追踪

Trace 方法参数说明

Parameter Type Description
EnableTrace bool 是否开启追踪
Channel string 通道名,枚举:bt / ipmb / edma / ipmbeth
Netfn uint8 目标 NetFn,0xFF 表示匹配任意 NetFn
Cmd uint8 目标 Cmd,0xFF 表示匹配任意 Cmd
Filter string 原始过滤字节流;接口侧转换为 xx- 格式写入 Filter 属性
LogType string filelocal;非法值拒绝配置并保持关闭状态

权限Trace 方法需要 BasicSetting;对象属性读取需要 ReadOnly(见 gen/model.json)。


追踪 Hook 机制

ipmi_trace_hook

位于 src/service/core/ipmi_trace_hook.{h,cpp},提供进程内全局回调注册:

API Description
set_ipmi_trace_callback(cb) 注册/替换追踪回调;trace_ipmi_obj::on_register 时绑定
report_ipmi_trace(msg, trace_data, dir) 传输层上报入口;无回调时直接返回

回调签名:

void(const ipmi_message& msg,
     const std::vector<uint8_t>& trace_data,
     trace_direction dir);

trace_direction 取值:send(BMC 发出)、recv(BMC 收到)。

channel_context 调用点

路径 时机 trace_data 来源 方向
process_send_data 协议序列化之后、驱动写入之前 protocol_->serialize(...) 结果 send
read_dev_data_loop 驱动读入之后、反序列化入队之前 驱动 read 的原始字节 recv

差异说明

  • send:使用协议层序列化后的完整报文,与线路上实际发送内容一致
  • recv:使用驱动读到的原始字节,在反序列化为 ipmi_message 之前上报,保留线路全貌

channel_context 在填充通用 ctx 时写入 ctx_key::REQ_SERVICE_NAME(如 bt_serviceipmb_service),供前缀构造时校验通道与服务一致性。


追踪处理流程

1. 外部调用 Trace 方法配置 EnableTrace / Channel / NetFn / Cmd / LogType
   ↓
2. 传输层 channel_context 在 send 或 recv 路径调用 report_ipmi_trace
   ↓
3. trace_ipmi_obj::monitor_ipmi_message
   ├─ EnableTrace=false → 直接返回
   ├─ build_trace_prefix 失败(通道/服务不匹配)→ 返回
   ├─ NetFn/Cmd 过滤不匹配 → 返回
   ├─ trace_data 为空 → 返回
   └─ 格式化日志
       ├─ 时间戳 + 前缀 + 十六进制数据
       ├─ 敏感掩码(见下文)
       ├─ 超长截断(MAX_TRACE_LEN=256 字节)
       └─ 按 LogType 输出(file / local)

时序(send 方向)

channel_context    protocol    ipmi_trace_hook    trace_ipmi_obj    /tmp/ipmi.txt
      │               │              │                  │                 │
      │ serialize     │              │                  │                 │
      ├──────────────>│              │                  │                 │
      │ report(send)  │              │                  │                 │
      ├─────────────────────────────>│ monitor          │                 │
      │               │              ├─────────────────>│                 │
      │               │              │                  │ trace_by_file   │
      │               │              │                  ├────────────────>│
      │ driver write  │              │                  │                 │
      ├──────────────>│              │                  │                 │

过滤与匹配规则

追踪是否记录一条报文,需依次通过以下检查:

序号 检查项 规则
1 使能 EnableTrace == true
2 通道 Channel 非空,且 msg.ctx()[REQ_SERVICE_NAME] 包含通道名(如 bt 匹配 bt_service
3 NetFn 配置为 0xFF 或等于 msgdest_netfn_lun >> 2
4 Cmd 配置为 0xFF 或等于 msgcmd
5 数据 trace_data 非空

通配示例

  • 追踪 BT 通道全部命令:Channel=bt, Netfn=0xFF, Cmd=0xFF
  • 仅追踪 Set Watchdog(0x06/0x24):Channel=bt, Netfn=0x06, Cmd=0x24

日志前缀格式

前缀由 build_trace_prefix 生成,用于区分通道实例与方向:

通道 格式 示例
BT bt-{iface}-{send|recv} bt-0-send
IPMB ipmb-{iface}-{send|recv}--0x{src}->0x{dest} ipmb-0-recv--0x20->0x2c
EDMA edma-{send|recv} edma-recv
  • ifacemsg.get_interface_id(),对应通道实例编号
  • IPMB 的 src/dest 取自 ipmi_data.header.src_addr / dest_addr

当前前缀构造已实现 BTIPMBEDMAipmbeth 在 MDS 枚举中声明,前缀逻辑待扩展。


敏感数据掩码

当路由结果标记响应为敏感(msg.ctx()[RSP_SENSITIVE] == true,由 service_managerroute_request 路径写入)时,对 payload 做脱敏输出:

消息类型 判断方式 掩码规则
请求(NetFn 偶数) netfn & 0x01 == 0 头部之后、敏感起始位置之前正常输出;其余字节输出 **
响应(NetFn 奇数) netfn & 0x01 == 1 仅输出通道头部长度,后续全部 **

通道头部长度get_header_len):

Channel Header Len
bt 4
edma 5
ipmb 6

敏感命令精细匹配依赖内部表 m_sensitive_ipmicmds(NetFn + Cmd + filter 字节匹配,0xFF 为通配)。该表当前尚未从 Filter 属性或 CSR 填充,精细脱敏规则为预留能力;在表为空时,请求侧敏感掩码退化为输出完整 trace_data


日志输出

file 模式

  • 目标文件:/tmp/ipmi.txt
  • 不存在时创建,权限 0664,属主 root:204(ADMIN_GID)
  • 单行格式:[YYYY-MM-DD HH:MM:SS.mmm]{prefix} ---- {hex bytes...}
  • 文件超过 5MB 时截断重写,避免无限增长
  • 每条记录末尾追加换行

输出示例

[2026-06-06 10:15:30.123]bt-0-send ---- 20 18 c8 81 04 01 02 03
[2026-06-06 10:15:30.456]ipmb-0-recv--0x20->0x2c ---- 2c 18 06 00 20 00 00 00
[2026-06-06 10:15:30.789]edma-recv ---- 20 18 c8 81 04 01 02 03

local 模式

  • 调用 trace_by_local_log,计划对接框架 mdbctl_log 接口
  • 当前为空实现,配置 LogType=local 时格式化完成但不输出

长度限制

  • 单条日志最多展示 256 字节十六进制数据(MAX_TRACE_LEN
  • 超出部分以 ... 结尾截断

关键点说明

  • 默认关闭EnableTrace 默认为 false,未配置时不产生日志开销
  • 单例回调:全局仅一个 ipmi_trace_callback,由首个注册的 trace_ipmi_obj 占用
  • recv 用原始字节:recv 路径的 trace_data 为驱动原始读数,与 send 路径序列化结果可能在封包细节上存在差异,均代表各方向线路真实数据
  • Filter 预留Filter 属性与 Trace 入参已定义,用于后续按 payload 前缀精细过滤/脱敏;当前仅持久化为十六进制字符串
  • local 日志待实现trace_by_local_log 尚未对接框架日志接口
  • 通道扩展ipmbeth 的前缀格式与 hook 覆盖范围随传输服务扩展逐步补齐