IPMI通道(BT/IPMB)不通问题分析
更新时间: 2026/08/11
在Gitcode上查看源码

问题背景

  • 单板类型:NA
  • 软件版本:NA
  • 涉及功能:IPMI 通道通信,包括 BT 通道和 IPMB 通道。
  • 触发条件:IPMI 命令通过 BT 或 IPMB 通道执行失败,表现为命令无响应或超时。
  • 业务表现:IPMI 命令通过 BT/IPMB 通道无法正常通信。

涉及功能

  • IPMI 消息的路由和转发
  • BT/IPMB 通道的通信管理
  • 与 BMC 固件层的交互

架构说明

消息路由整体流程

物理设备文件(/dev/bt, /dev/ipmb)
    → 驱动层(IOCTL 读写)
    → 协议层(序列化/反序列化)
    → 通道上下文(消息队列管理)
    → 路由过滤器链(防火墙 → lockdown → 路由分发)
    → 应用层dispatch(D-Bus RPC)
    → 响应封装
    → 驱动层write

消息经异步队列处理后依次经过防火墙过滤、lockdown 过滤、路由分发,最后经 D-Bus 发送请求到命令处理进程,等待响应后原路返回。

通道 ID 与通道类型的对应关系

通道 ID (hex)通道名通道类型对应服务
0x0Ech_sys / ch_presentBT 系统接口bt_service
0x15ch_btc1BT 通道1bt_service
0x16ch_btc2BT 通道2bt_service
0x06ch_ipmb_smIPMB 通道ipmb_service
0x08ch_edmaPCIe EDMAedma_service

通道类型中,BT 通道属于 host 类型,IPMB 通道属于 ME 类型。

BT 通道内部实现

设备文件:/dev/bt(LPC/ESPI 模式)或 /dev/btc(PCIe/Localbus 模式)。

BT 协议帧格式:

Byte 0:   data_len      (后续数据长度)
Byte 1:   netfn(6bit) | lun(2bit)
Byte 2:   seq          (序列号)
Byte 3:   cmd          (命令码)
Byte 4+:  payload      (载荷数据)

BMC 源地址固定为 0x61

每个 BT 通道启动两个独立线程:一个处理发送队列和接收队列中的消息,一个持续从设备文件读取数据并压入接收队列。待处理请求以 message_id 为 key 存储,超时后触发重试逻辑。

IPMB 通道内部实现

设备文件:/dev/ipmb

IPMB 协议直接透传标准 IPMI 消息帧,驱动层额外做 checksum1 和 checksum2 的校验。

桥接响应机制(BT 特有)

BT 通道支持从其他通道(如 IPMB)桥接响应回主机。当收到来自非 BT 通道的响应需要经 BT 回传给主机时,先将响应缓存,再触发 ATN 中断通知主机,主机主动读取时优先返回缓存数据。

关键日志信息

1. 驱动加载、卸载关键日志

BT 驱动加载日志

正常加载时应看到类似以下日志:

text
# dmesg | grep bt
[    1.234567] bt: BT interface driver loaded
[    1.234789] bt: BT device registered at /dev/bt-ipmi-0
[    1.235012] bt: Interrupt configured for BT channel

驱动加载失败时可能出现的日志:

text
# dmesg | grep bt
[    1.234567] bt: BT interface driver loading failed: -5
[    1.234789] bt: Failed to request IRQ for BT channel
[    1.235012] bt: Device not found at expected MMIO address

open() 失败时的错误码含义:errno=2(ENOENT,设备文件不存在)、errno=13(EACCES,权限不足)。

IPMB 驱动加载日志

正常加载时:

text
# dmesg | grep ipmb
[    1.345678] ipmb: IPMB interface driver loaded
[    1.345890] ipmb: IPMB bus initialized, bus_id=0
[    1.346012] ipmb: I2C adapter registered for IPMB channel

驱动异常时的日志:

text
# dmesg | grep ipmb
[    1.345678] ipmb: Failed to initialize I2C bus: -121 (EREMOTEIO)
[    1.345890] ipmb: IPMB bus timeout during initialization
[    1.346012] ipmb: IPMB device not responding at address 0x10

errno=-121(EREMOTEIO)表示 I2C 设备无响应(ACK 超时或 NACK)。

驱动卸载日志

正常卸载:

text
# dmesg | grep -E "bt|ipmb"
[  100.123456] bt: BT interface driver unloaded
[  100.123678] ipmb: IPMB interface driver unloaded

2. 设备文件读写状态关键日志

BT 设备文件状态

检查设备文件存在性:

bash
ls -la /dev/bt /dev/btc
# 正常输出(ipmi_mgmt):crw------- 1 root root 246, 0 /dev/bt
# 正常输出(ipmi_core):crw------- 1 root root 246, 0 /dev/btc 或 /dev/bt

设备文件异常时的系统日志:

text
[  100.234567] bt: Device file /dev/bt not found
[  100.234789] bt: Permission denied accessing BT device
[  100.235012] bt: ioctl(BT_CMD_INIT) failed: No such device (ret=-19)

读写测试:

bash
# 检查 BT 设备类型
cat /sys/class/ipmi/ipmi0/type
# 输出应为: KCS 或 BT

# 检查 BT 设备状态
cat /sys/class/ipmi/ipmi0/location
# 输出示例: "BT SMIC Interface at 0xE4, IRQ 10"

IPMB 设备文件状态

bash
ls -la /dev/ipmb
# 正常输出:crw------- 1 root root 247, 0 /dev/ipmb

设备异常时的日志:

text
[  100.345678] ipmb: Device file /dev/ipmb not initialized
[  100.345890] ipmb: ioctl(IPMB_CMD_INIT) failed: I/O error (ret=-5)
[  100.345901] ipmb: Failed to open IPMB device: No such device (fd=-1)

3. 关键数据收发的查看方式

使用 ipmitool 发送测试命令

bash
# BT 通道测试(带内)- ipmitool 通过 /dev/ipmi0 发送
ipmitool -I open raw 0x06 0x01

# IPMB 通道测试
ipmitool -I ipmb raw 0x06 0x01

# 查询通道统计信息(Get Channel Authentication Capabilities, NetFn=0x06 Cmd=0x38)
ipmitool raw 0x06 0x38 0x00 0x00 0x04 0x00 0x00

# 查询通道统计
ipmitool raw 0x0c 0x02 0x01

# 查询通道状态
ipmitool raw 0x0c 0x04 0x07

抓取 IPMI 通信报文

bash
# 使用 tshark 抓取 IPMI over LAN 报文
tshark -i eth0 -Y "ipmi" -w /tmp/ipmi_capture.pcap

# 使用trace工具抓取 BT 通道数据
mdbctl traceipmi start file bt

查看通道收发统计

bash
# 查看 IPMI 通道统计信息
ipmitool channel info

# 查看各通道收发计数
ipmitool raw 0x0c 0x02 0x01

IPMI 服务日志

正常收发日志:

text
# ipmi_mgmt 格式示例
2025-07-15 10:30:12.123456 ipmi_mgmt INFO: bt_driver: ioctl(BT_CMD_WRITE) ok, size=8
2025-07-15 10:30:12.124567 ipmi_mgmt INFO: channel_context: recv msg, interface_id=0, size=8

# ipmi_core 格式示例
2025-07-15 10:30:12.123456 ipmi_core NOTICE: [bt] send msg: netfn=0x06 seq=0x01 cmd=0x01
2025-07-15 10:30:12.124567 ipmi_core NOTICE: [bt] recv msg: netfn=0x07 seq=0x01 cmd=0x01 cc=0x00

收发异常日志:

text
# BT 发超时
2025-07-15 10:30:12.123456 ipmi_mgmt ERROR: bt_driver: ioctl(BT_CMD_WRITE) failed: Connection timed out (ret=-110)

# BT 读超时
2025-07-15 10:30:12.234567 ipmi_mgmt WARN: channel_context: read_dev_data timeout after 1000 jiffies

# IPMB 总线忙
2025-07-15 10:30:13.123456 ipmi_mgmt WARN: ipmb_driver: write failed: Remote I/O error (ret=-121), retry 1/3
2025-07-15 10:30:13.234567 ipmi_mgmt ERROR: ipmb_driver: write failed after 3 retries

# IPMB NACK / 设备无响应
2025-07-15 10:30:13.345678 ipmi_mgmt ERROR: ipmb_driver: ioctl(IPMB_CMD_WRITE) failed: I/O error (ret=-5)

4. IPMB 自检信息日志

IPMB 初始化自检

系统启动时 IPMB 自检日志:

text
2025-07-15 08:00:01.123456 ipmi_mgmt INFO: ipmb_driver: IPMB self-test started
2025-07-15 08:00:01.234567 ipmi_mgmt INFO: ipmb_driver: bus_id=0 self-test OK
2025-07-15 08:00:01.345678 ipmi_mgmt INFO: ipmb_driver: bus_id=1 self-test OK
2025-07-15 08:00:01.456789 ipmi_mgmt INFO: ipmb_driver: IPMB self-test completed

IPMB 总线繁忙(Busy)

当 IPMB 总线繁忙时,日志显示:

text
2025-07-15 10:30:12.123456 ipmi_mgmt WARN: ipmb_driver: get_status: bus busy, retry 1/3
2025-07-15 10:30:12.234567 ipmi_mgmt WARN: ipmb_driver: get_status: bus busy, retry 2/3
2025-07-15 10:30:12.345678 ipmi_mgmt ERROR: ipmb_driver: bus busy timeout after 3 retries
2025-07-15 10:30:12.456789 ipmi_mgmt ERROR: ipmb_driver: write failed: Bus busy (ret=-16, errno=EBUSY)

IPMB 设备无响应(NACK)

设备未响应时日志(errno=-121 EREMOTEIO):

text
2025-07-15 10:30:13.123456 ipmi_mgmt WARN: ipmb_driver: write: NACK received from address 0x10
2025-07-15 10:30:13.234567 ipmi_mgmt ERROR: ipmb_driver: ioctl(IPMB_CMD_WRITE) failed: Remote I/O error (ret=-121)
2025-07-15 10:30:13.345678 ipmi_mgmt ERROR: ipmb_driver: Transaction timeout: no response from target

IPMB 通道状态查询

bash
# 查询 IPMB 通道状态(Get Channel Info command)
ipmitool raw 0x0c 0x04 0x06

# 查询结果解读(返回字节含义):
# Byte 0: 通道 Medium 类型,0x6C = IPMB
# Byte 1: 通道 Protocol 类型
# Byte 3-4: 通道支持的最大 payload size

5. 需移交硬件领域定位的场景

硬件相关问题

场景移交条件
BT 控制器硬件故障IOCTL 持续返回 -ENODEV 或 -EIO,排除软件配置问题后仍无法恢复
IPMB 总线硬件损坏IPMB 自检报总线短路、开路或持续 NACK,I2C 电气特性异常
通信接口芯片故障IOCTL 命令完全无响应,errno=ENODEV,排除软件问题后示波器测量信号异常
物理连接问题IPMB 总线连接断开或接触不良,I2C 扫描找不到目标地址

软件无法解决的场景

  • IOCTL 持续返回 ENODEV (-19):设备文件存在但内核驱动无响应
  • IOCTL 持续返回 EIO (-5):设备文件读写硬件层失败,无具体错误原因
  • 中断信号异常/proc/interrupts 显示 BT 中断计数不增长
  • IPMB 总线持续 EBUSY (-16):持续 bus busy 日志,重启后问题依旧
  • IPMB 总线持续 EREMOTEIO (-121):持续 NACK,目标地址无响应

移交前自查清单

移交硬件领域前,请确保已完成以下排查:

  1. 确认驱动已正确加载(dmesg 无 ENODEV/EIO 相关报错)
  2. 确认设备文件存在且权限正确(ls -la /dev/bt /dev/btc /dev/ipmb
  3. 确认 IOCTL INIT 命令成功执行(ioctl(fd, BT_CMD_INIT) 返回 >=0)
  4. 确认系统中断配置正确(cat /proc/interrupts | grep -E "bt|ipmb"
  5. 保存相关日志文件:
    • dmesg 输出
    • /tmp/ipmi_capture.pcap(如有抓包)

根因分析与排查步骤

排查流程图

IPMI 命令不通
    ├─ BT 通道(系统接口)
    │   ├─ dmesg | grep bt 有 ERROR ?
    │   │   ├─ YES → 检查内核模块是否加载 lsmod | grep bt
    │   │   │           检查设备文件 /dev/bt 或 /dev/btc 是否存在
    │   │   │           检查 IOCTL INIT 是否成功
    │   │   └─ NO → 查服务日志
    │   │           ├─ write timeout → 检查 ATN 信号和主机侧响应
    │   │           ├─ read timeout → 检查主机是否已启动或发送数据
    │   │           └─ bridge response miss → 检查 channel_context 缓存
    │   └─ ipmitool -I open raw 0x06 0x01 测试

    └─ IPMB 通道(I2C 总线)
        ├─ dmesg | grep ipmb 有 ERROR ?
        │   ├─ YES → 检查 /dev/ipmb 是否存在
        │   │         检查 IOCTL INIT 返回值
        │   │         检查 bus_id/slave_addr 配置是否匹配硬件
        │   └─ NO → 查服务日志
        │           ├─ EREMOTEIO (-121) → 目标地址无响应,检查目标设备
        │           ├─ EBUSY (-16) → 总线忙,尝试 force reset
        │           └─ EIO (-5) → I2C 传输错误,检查 SCL/SDA 信号
        └─ ipmitool -I ipmb raw 0x06 0x01 测试

根因分类速查表

症状根因类别关键日志特征排查命令
BT 设备文件不存在内核模块未加载ENOENTlsmod | grep bt
BT write timeoutATN 信号未触发或主机未响应ETIMEDOUT (-110)ipmitool -I open raw 0x06 0x01
BT 读不到数据主机未发送或驱动读失败read timeoutcat /proc/interrupts | grep bt
IPMB 设备文件不存在IPMB 内核驱动未加载ENOENTlsmod | grep ipmb
IPMB EREMOTEIO目标设备无响应(NACK)-121i2cdetect -y <bus_id>
IPMB EBUSY总线被其他设备占用-16ipmitool raw 0x0c 0x04 0x07
IPMB EIOI2C 传输物理层错误-5示波器测 SCL/SDA
消息路由丢失消息队列溢出或 D-Bus 超时dispatch timeout
桥接响应丢失响应缓存 TTL 超时bridge timeout
通道权限不足通道 privilege 掩码限制no privilegeipmitool channel info

BT 通道深度排查

bash
# Step 1: 检查内核模块
lsmod | grep -E "btc_drv|bt_drv"

# Step 2: 检查设备文件
ls -la /dev/bt /dev/btc 2>/dev/null || echo "设备文件不存在"

# Step 3: 检查中断
cat /proc/interrupts | grep -E "bt|btc"
# 中断计数应随每次 IPMI 交互递增

# Step 4: 使用 strace 跟踪系统调用(注意:可能影响性能)
strace -f -e trace=ioctl ipmitool -I open raw 0x06 0x01 2>&1 | grep -E "BT_CMD|bt"

# Step 5: 检查通道上下文线程状态
cat /proc/$(pidof ipmi_mgmt或ipmi_core)/status | grep -E "Name|State|Threads"

# Step 6: BT ATN 信号手动触发测试
# 通过 ioctl BT_CMD_SETATN 手动触发 ATN,观察主机侧是否有响应

IPMB 通道深度排查

bash
# Step 1: 检查内核模块
lsmod | grep ipmb

# Step 2: 检查设备文件
ls -la /dev/ipmb

# Step 3: I2C 总线扫描(确认目标地址可见)
i2cdetect -y <bus_id>
# 例如:i2cdetect -y 0

# Step 4: 检查 IPMB 配置参数
# 从 MDS 或配置文件读取 bus_id、speed、slave_addr
# 确认与硬件跳线和 BMC 地址拨码一致

# Step 5: 手动读取 IPMB 状态寄存器
# 通过 IPMB_CMD_GET_STATUS ioctl 查看 bus busy 等状态位

# Step 6: IPMB 总线 force reset
# 发送 IPMB_CMD_RESET ioctl 重置总线

# Step 7: I2C 速率检查
# 确认 IPMB 总线速率是否与 IPMB 规范要求的 100kHz 或 400kHz 匹配

常见问题快速排查

BT 通道不通

bash
# 1. 检查驱动加载
dmesg | grep bt

# 2. 检查设备文件
ls -la /dev/bt /dev/btc

# 3. 检查中断
cat /proc/interrupts | grep bt

# 4. 测试通信
ipmitool -I open raw 0x06 0x01

IPMB 通道不通

bash
# 1. 检查驱动加载
dmesg | grep ipmb

# 2. 检查设备文件
ls -la /dev/ipmb

# 3. 检查 I2C 总线
i2cdetect -l | grep ipmb

# 4. 测试通信
ipmitool -I ipmb raw 0x06 0x01

# 5. 检查总线状态
dmesg | grep -E "EREMOTEIO|EBUSY|EIO"

# 6. 检查 BMC 从地址配置
# IPMB 规范要求 BMC 从地址为 0x20,确认配置文件中 slave_addr=0x20

相关命令汇总

命令用途
dmesg | grep -E "bt|ipmb"查看驱动加载日志
lsmod | grep -E "btc_drv|bt_drv|ipmb"检查内核模块是否加载
ls -la /dev/bt /dev/btc /dev/ipmb检查设备文件
cat /proc/interrupts | grep -E "bt|ipmb"检查中断状态
ipmitool channel info查看通道信息
ipmitool -I open raw 0x06 0x01测试 BT 通道(系统接口)
ipmitool -I ipmb raw 0x06 0x01测试 IPMB 通道
ipmitool raw 0x0c 0x02 0x01获取通道统计
ipmitool raw 0x0c 0x04 0x06获取 IPMB 通道信息
i2cdetect -y <bus_id>扫描 IPMB I2C 总线设备
strace -f -e trace=ioctl ipmitool -I open raw 0x06 0x01跟踪 BT IOCTL 调用