问题描述: 执行长时间 BMC 重启测试,通过 IPMI 下发的 Chassis Control Cold Reset 命令返回成功(CompletionCode=0x00),但 BMC 未在 1 分钟内实际重启。测试环境为 5290TX V2 服务器,固件版本 ipmcv3 v2.6.2.0,BIOS 版本 BLADE12-2.0.29。
测试环境:
-
机型:openUBMC
-
固件版本: 26.03
测试步骤:
-
通过 IPMI 工具向 BMC 下发 Cold Reset 命令(Chassis Control Command)
-
记录 IPMI 返回结果
-
等待 BMC 在 1 分钟内完成重启
预期结果:IPMI 返回成功(CompletionCode=0x00),BMC 在 1 分钟内重启完成 实际结果:IPMI 返回成功(CompletionCode=0x00),但 BMC 未在 1 分钟内显示重启,实际 BMC 进程未退出,系统继续正常运行。最终 bmc_reset count: 0 确认 BMC 硬件从未重启。
二、根因分析
2.1 完整调用链路追踪
IPMI Chassis Control Cold Reset
→ ipmi_cold_reset() [ipmi_functions.lua:21-37]
→ powerapi:system_reset(ctx, 'ForceRestart', 'ChassisControlCommand') [powerapi.lua:199-278]
→ execute_hardreset() [powerapi.lua:131-141]
→ force_reset:force_restart() [force_reset.lua:48-59]
设置 ForceRst=1 到对象(Host 侧热复位)
设置 sys_reset_flag=true(记录是 BMC 主动发起的复位)
→ maca 框架同时发起 GracefulReset(BMC 自身重启流程)
关键发现:force_restart() 只是对 Host 系统侧的硬件对象设置 ForceRst=1,这是发给 CPLD 的热复位信号,用于复位 CPU 等主机设备。它不重启 BMC 本身。BMC 自身的重启由 maca 框架层的 GracefulReset 流程控制。
2.2 日志时间线(framework.log)
td {white-space:nowrap;border:0.5pt solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}| 时间 | 事件 | 分析 |
|---|---|---|
| 0:05:08 | [ssdp]HealthCheck failed (2 times) | ssdp 服务已处于异常状态 |
| 05:23.0 | GracefulReset begin, BMC reset type: normal system | IPMI Cold Reset 命令到达 |
| 0:05:24 | 33个服务完成 prepare 阶段(全部 <200ms) | 正常服务快速完成准备 |
| 0:05:34 | prepare reboot timeout, components: ssdp | ssdp 未响应 Prepare 请求,触发超时 |
| 0:05:34 | 33个服务完成 process 阶段(全部 <100ms) | 正常服务完成处理 |
| 00:05:34~00:06:38 | 等待 ssdp 64秒 | bmc_upgrade 调用 ssdp 的 MicroComponent.Reboot.Process 等待 |
| 0:06:38 | service[bmc.kepler.bmc_upgrade] request timeout: …method[Process], used time[64s] | Process 接口超时 |
| 0:06:38 | service[bmc.kepler.bmc_upgrade] request timeout: …method[Prepare], used time[74s] | Prepare 接口超时(先发起的,后返回) |
| 0:06:38 | ssdp 进程因 D-Bus NoReply 异常退出 | Message recipient disconnected from message bus without replying |
| 0:06:39 | GracefulReset process fail, skip it | 框架跳过 process 失败 |
| 0:06:42 | start to reboot action, stop all scanners | 进入 ACTION 阶段 |
| 0:06:48 | GracefulReset action fail, skip it | ACTION 阶段也失败,但标记 “successfully” |
| 最终 | BMC 进程未退出,继续正常运行 | bmc_reset count: 0 确认 BMC 硬件从未重启 |
2.3 maca 框架 strings 分析
从 maca 框架的编译后 init.lua(通过 strings 命令分析)提取到关键代码字符串:
-
%s process fail, skip it— process 失败后跳过 -
%s action fail, skip it— action 失败后跳过 -
%s successfully— 无论 process/action 是否失败,最终都打印成功 -
excute_reboot_operation— 实际执行 BMC 重启的函数 -
force_reset/force_reset_with_cause— 强制重启函数(已存在) -
Force reset BMC successfully!— 强制重启成功消息 -
reboot+/bin/systemctl— 最终执行 systemctl reboot
关键结论:框架中存在 force_reset 和 excute_reboot_operation 函数,但当 GracefulReset process 失败时,仅仅 skip it 进入 action 阶段,没有 fallback 到 force_reset。
2.4 mc_stream.log 确认
BMC 所有服务在 00:06:38(GracefulReset process fail)之后仍然继续初始化,直到 00:09:02 全部完成。这证实了 BMC 进程未退出,而是继续正常运行。
2.5 根因总结
-
直接原因:ssdp 服务在 GracefulReset 开始时已处于异常 HealthCheck 状态,导致其
MicroComponent.Reboot.Prepare(74秒超时)和MicroComponent.Reboot.Process(64秒超时)接口均超时,使 GracefulReset 的 process 阶段失败 -
深层原因:maca 框架在 process 失败后走
skip it分支 → action 也失败 → 仅打印successfully就结束流程。框架未在 GracefulReset 失败后触发任何 fallback 重启机制(如调用已有的force_reset函数执行/bin/systemctl reboot) -
复现概率 1/47 的原因:ssdp HealthCheck failed 是偶发的,仅在重启命令到达时 ssdp 恰好处于异常状态时触发此问题