InfiniBand 专题【左扬精讲】—— InfiniBand Fabric 诊断:ibdiagnet 的原理、输出解读与 Dump 文件分析
InfiniBand 专题【左扬精讲】—— InfiniBand Fabric 诊断:ibdiagnet 的原理、输出解读与 Dump 文件分析
本系列前十六篇都在讲"子网怎么建起来、怎么跑下去",但没有一篇讲过:建好之后,你凭什么断定它是健康的?InfiniBand 的子网不是插上就能用的——它必须由子网管理器逐个节点配置、逐条链路编程之后才进入 Active 状态。而 SM 只管"配",不管"验"。SM 说配好了,和这条链路真的把包原封不动送到了,是两件完全不同的事。
本篇是 InfiniBand 专题【左扬精讲】系列的第 17 篇,主题是 Fabric 诊断:为什么必须主动巡检、ibdiagnet 用什么机制发现问题、输出报告的每个阶段在判什么、以及那些默认落在 /var/tmp/ibdiagnet2/ 里的 dump 文件分别能回答什么问题。全文按"为什么需要 → 工具原理 → 输出解读 → Dump 文件 → 进阶用法"的顺序展开,所有阶段名、选项语义、dump 文件清单与输出样例全部引自 NVIDIA 官方 ibdiagnet 文档与 ibdiagnet(1) man page。
本篇与本系列第十五、第十六篇是互补关系,值得先说清边界:那两篇讲的是"主动加压"(perftest)与"被动抓包"(ibdump + Wireshark),本篇讲的是"设备与 fabric 自身上报的状态与计数器"。前两者的共同前提是"先有一个已知健康的 fabric"—否则测出来的数字没有参照系,而本篇正是建立这个前提的那一步。反过来,本篇第八节讲的 port_xmit_wait 判读,在那两篇里是配对出现的——本篇讲"这个计数器高说明什么",第十五篇《打流与性能基线》讲"打流时它为什么应该有值、低负载下不该增长",两篇必须一起读。
本篇的核心命题只有一句:ibdiagnet 不是"跑一下看有没有报错"的健康检查,而是一台把 fabric 的全部可观测状态一次性采集成 dump 文件的采集器——它的产出不是"通过 / 不通过"这个结论,而是"出问题时的完整取证材料"。理解了这一点,"为什么每次排查都要重新跑一遍并把整个目录打包发出来"就不再是流程上的繁琐,而是这个工具的设计本意。
开篇必读:课程口语转写里的十一组高频误听,本文全部按真实标识符纠正
本篇素材来自一段英文课程的口语转写,转写引擎对专有名词、命令名与缩写的还原率很低。以下对照是全文可复现性的前提——照着转写稿敲命令一定敲不通:
| # | 转写稿里的说法 | 真实写法 | 说明 |
|---|---|---|---|
| 1 | "ib dia go nate" / "ib diag on ant" / "ib diagonal" | ibdiagnet | 一个单词,中间没有空格、没有下划线。它是本篇唯一的主角 |
| 2 | "ib utils two" / "ib utils 2" | ibutils2 | 提供 ibdiagnet 的软件包名。配置文件目录 /etc/ibutils2/ 同源 |
| 3 | "doc ao fed" / "o fed" | DOCA-OFED / MLNX_OFED | 转写稿把 Mellanox 与 DOCA 混成了同一个词。NVIDIA 固件工具集对两种发行版都提供 |
| 4 | "invidia" | NVIDIA | 转写引擎把 NVIDIA 反复听成了另一个词 |
| 5 | "in finite band" | InfiniBand | 转写引擎把 finite 与 Infini 混为一谈,这是全篇最系统性的误听 |
| 6 | "gou WI ds" / "gou ids" | GUID | Global Unique Identifier。转写稿在多处在 GUID 与"节点"之间来回换词 |
| 7 | "lid gou IDS" | GUID,不是 LID | 本篇最关键的一处纠正。课程列举检查项时口误成"LID 的重复检查",实际该项是 Duplicated GUIDs Detection;LID 重复检查是另一项独立功能 LIDs Check(见第五节) |
| 8 | "in nate logical state" / "an knit logical state" | INIT logical state | 不是" innate / 天然的"。INIT 是端口逻辑状态机的四态之一(Down / Init / Armed / Active) |
| 9 | "port ex im ate weight counter" / "air counters" / "five counters" | port_xmit_wait | 本篇第二处关键纠正。这是计数器名 port_xmit_wait,转写引擎把它拆成了三个不存在的词。详见第九节 |
| 10 | "be r" / "high bit error rate" | BER = Bit Error Rate | Bit Error Rate 本身是对的,转写稿只是把它拆开念;官方定义见第十二节 |
| 11 | "dash pc" 用来"重置计数器" | -pc / --pc | 拼写正确,但要注意它重置的是全 fabric 的规范计数器,会清掉别人的历史,第九节讲清使用前提 |
另外有一处表述需要收紧:转写稿说 dump 文件的默认位置是 /var/tmp/ibdiagnet2/,并说"可以用 -o 改到别处"。前半句只对较新版本成立——旧版 ibdiagnet(1) man page 明确写的是默认输出目录为 /tmp,dump 文件名也没有 2 后缀(ibdiagnet.lst 而非 ibdiagnet2.lst)。因此"文件名带不带 2、默认目录是哪个",取决于装的是哪个版本,必须现场确认,不能想当然——详见第八节与 FAQ Q4。
InfiniBandFabric 诊断ibdiagnetibutils2Directed RouteDiscoveryLIDs CheckLinks CheckPM Countersport_xmit_waitPortCountersExtendedBERFECCredit Loop-P 阈值--pm_pause_time-pcdump 文件db_csvIBNL拓扑基线SHARPSHIELDARRail 优化ibstatibnetdiscoverDOCA-OFED
★ 学完这一篇你能掌握什么(渐进式路径:1→2→3→4 不可跳跃)
- 第 1 步 · 分清"配好"与"健康"(第一节、第二节)
• What:业务对网络的三类依赖——不宕机、够快、别丢包;以及课程列出的五类会导致服务中断的网络问题
• How:能说出课程点出的第一线诊断工具族(链路/自管理/路由)与 fabric 级工具族各管什么,并解释为什么需要"一个工具做很多事"而不是"很多工具各管一段"
• Why:理解 "主动监控是在故障对最终用户可见之前发现并消除威胁"——事后抓包永远只能证明已经发生的事- 第 2 步 · 掌握工具原理与前置能力(第三节、第四节)
• What:ibdiagnet 用定向路由包扫描 fabric;ibdiagnet 与 ibutils2 包名、--version / -h / --vars 三个自检命令
• How:能说明多 HCA 主机上 ibdiagnet 默认用第一个活动接口,并用 -i / -p / -g 显式指定目标端口
• Why:理解 "为什么 ibdiagnet 能发现设备而别的工具不能"——它不需要被扫描设备主动配合,它自己发包- 第 3 步 · 读懂屏幕输出(第五节、第六节、第七节、第八节、第九节)
• What:无参数运行的 12 个阶段;官方 20 项功能;输出的阶段分隔线结构与 -I- / -W- / -E- 三种前缀含义
• How:能解读 Discovery 节点数、LIDs Check、Links Check、SM Check、Port Counters 两采样点差值、Nodes Info 固件告警、Speed/Width 降级,最后读 Summary 汇总表
• Why:理解 "为什么 port_xmit_wait 高要查、symbol_error 高也要查,但 port_rcv_pkts 高不用查"——三类计数器的健康判据方向根本不同- 第 4 步 · 用好 dump 文件与进阶功能(第十节至第十四节)
• What:旧版 13 个文件 / 新版 30 个文件的差异;db_csv 是可复用的主档;ibnetdiscover 格式的拓扑文件用于基线比对
• How:能用 -w 导出拓扑做基线、用 -t 比对、能用 --discovery_only + -f 跳过发现加速重复诊断
• Why:理解 "为什么要把拓扑文件当基线而不是当结果"——单次拓扑图只能说明"现在是这样",基线才能说明"和上次不一样"★ 阅读前提 & 本篇不涉及的内容
- 前置知识:本系列第八篇《子网初始化:拓扑发现、LID 分配、路径计算与子网激活》中的 SMP 报文、LID 分配规则、Min Hop 路径计算、端口物理与逻辑状态机——本篇第五节的 LIDs Check 与 Links Check 检查的正是那两套机制的产出物;本系列第九篇《SM 监控与拓扑变化:选举、故障切换、扫描与重收敛》中的 ibstat 字段判读与 Trap 机制;本系列第十篇《拓扑与路由引擎:Fabric 拓扑、路由引擎、自适应路由与信用环》中的信用环成因——-r 的信用环检查直接建立在该篇结论之上;本系列第十四篇《HCA 固件升级:工具链、版本识别、固件烧录与验证》中的PSID 与固件版本字段——本篇第十节 Nodes Info 输出的正是同一组字段。本篇不重复解释这些内容
- 信息来源:本篇出现的全部阶段名、选项语义、dump 文件清单、默认值、计数器名称、错误码、错误与告警输出样例,均引自文末「参考资料」列出的 NVIDIA ibdiagnet User Manual、ibdiagnet(1) man page 与 NVIDIA 文档站 Dump Files 页面;本篇不含任何未经上述来源核实的工具行为描述
- 本篇不涉及:ibdiagnet 各功能模块的内部实现算法(发现扩散的具体时序、转发表校验的数学判定)、SHARP 树形结构的计算与聚合语义、SHIELD 计数器的具体含义、拥塞控制(--congestion_control)与快速恢复(--fast_recovery)的调参方法、线缆诊断插件(--get_cable_info)与 PHY 诊断插件(--get_phy_info)的输出解析、--ppcc PPCC 拥塞控制算法文件格式
📑 本节目录(按"为什么需要 → 工具原理 → 输出解读 → Dump 文件 → 进阶用法"的顺序)
- 一、开篇必读:十一组误听与一处需要收紧的表述
- 二、为什么需要 Fabric 诊断:故障的可见性总是滞后于故障的发生
- 三、ibdiagnet 的定位与工作原理:为什么定向路由是它的基础
- 四、运行前的四个准备:版本、自检、多 HCA 选卡、配置预置
- 五、屏幕输出的骨架:12 个默认阶段与官方 20 项功能
- 六、Discovery 阶段:一切结论的证据从这一行开始
- 七、LIDs / Links / SM 三个检查阶段:分别对应前序三篇的三套机制
- 八、Port Counters 阶段:两次采样取差值,以及三类计数器的判读方向
- 九、Speed/Width Check 与 Nodes Information:降级链路与固件不齐
- 十、Summary 汇总表:读出"哪个阶段出了问题"而不是"有问题"
- 十一、Dump 文件全景:旧版 13 个与新版 30 个文件分别能回答什么
- 十二、进阶用法一:阈值告警、路由校验、BER 与拓扑基线比对
- 十三、进阶用法二:加速重复诊断(-f)与按 scope 缩小范围
- 十四、把它接进运维流程:什么该周期做、什么该按需做
- 十五、FAQ 高频问答(20 组)
- 十六、Roadmap 后续预告
一、开篇必读:十一组误听与一处需要收紧的表述
本节已在开头的 note-block 中完整给出十一组对照表,此处不重复,只讲为什么这张表必须放在最前面。
本系列前面几篇的主角是 ibstat、ibroute、smpquery,它们全部是只读查询,敲错了最坏结果是"命令报错"。而 ibdiagnet 是本系列第一个会在大子网上产生大量管理流量、并会清零全网计数器的工具。误听带来的两类实际后果要提前说清:
- 敲错选项名 → 命令不执行或执行了你不想要的动作。ibdiagnet -pc 会重置全 fabric 的规范端口计数器,这不是"只读诊断"能顺手做的事
- 误以为工具名是多个词 → 根本敲不出来。ib dia go nate 这样的写法在任何 shell 里都是语法错误
因此本篇的组织方式与 ib-14 一致:先把所有标识符的"出处"讲清楚,再讲命令与输出。第九节的 port_xmit_wait、第五节的 Duplicated GUIDs Detection 与 LIDs Check 的分家,是本篇实际操作中最容易张冠李戴的两处。
本节关键记忆:3 组高危误听 + 1 个必须现场确认的版本差异
- 3 组高危误听:ibdiagnet 是一个词;GUID 重复检查 ≠ LID 重复检查(是两个独立阶段);port_xmit_wait 是一个计数器名,不是三个词
- 1 个必须现场确认的差异:dump 文件名带不带 2、默认目录是 /tmp 还是 /var/tmp/ibdiagnet2/,取决于装的是哪个版本——转写稿只说了新版本的行为
- 1 个写入型选项要先记住:-pc 重置全 fabric 计数器,不是本机只读查询
二、为什么需要 Fabric 诊断:故障的可见性总是滞后于故障的发生
What — 课程给出的业务前提与五类网络问题
课程开篇给的判断是一句很朴素但很重的话:业务严重依赖基于网络的服务,因此必须尽力把网络停机时间降到最低(businesses rely heavily on network based services, hence it is critical to minimize network downtime)。紧接着它点出问题的另一半:网络本身易于产生多种会严重影响性能的错误(a network is prone to many errors that can seriously impact its performance)。
这两句合起来定义了 Fabric 诊断的存在理由:故障的成因与故障的可见性之间,天然存在一个时间差。课程随后把这个差值填上了具体内容——
主动监控(proactive monitoring)包含两件事:一是主动发现并消除威胁,二是主动诊断并排查那些在最终用户察觉之前就已经存在的网络问题。关键词是 before they are evident to the end user。
课程列出的五类网络问题,逐条对应到 InfiniBand 的具体成因:
| 课程列举的问题 | 在 InfiniBand fabric 上的具体形态 | 本篇哪一节会展开 |
|---|---|---|
| 线缆故障:线缆损坏、变短或被物理损伤 | 光模块或线缆失效导致端口不通;更常见的是误码而非断链,此时链路仍然 Active,靠状态判读发现不了 | 第十二节 --ber_test / --get_phy_info |
| 端口故障:设备所连端口物理 down 或故障 | 端口停在 Init 而非 Active;或链路反复震荡(flapping) | 第七节 Links Check |
| 配置问题:错误的路由问题或其他配置问题会影响服务 | 转发表算错导致绕路;LMC 配错导致有效带宽下降;信用环导致死锁 | 第十二节 -r |
| 软件兼容性问题或版本失配会中断数据传输 | 固件版本在 fabric 内不统一;驱动与固件接口不一致 | 第九节 Nodes Information |
| 链路超额订阅:过载造成拥塞与丢包 | 上行链路利用率接近 1;port_xmit_wait 持续增长 | 第八节 Port Counters |
这五类里,只有第二类是"状态能直接告诉你"的。其余四类的共同特征是:链路是 Active 的、端口状态是正常的、业务可能只是"慢了一点"或"偶尔丢包"。这就是"故障的可见性滞后于故障的发生"在 InfiniBand 上的具体形态。
2.1 两层工具的分工:为什么最后要落到"一个工具做很多事"
Why — 单点工具各管一段,fabrica 级工具才能给出完整证据
课程在讲完问题清单后,做了一个明确的分层:在整个课程体系中,已经介绍过很多 DOCA-OFED 工具,它们可以作为 Fabric 诊断的第一线工具(we've introduced many DOCA-OFED utilities that can be used as the first line tools for fabric diagnostics);另外还可以用一组 fabric 级工具来诊断连通性问题或性能问题(we can use the following fabric level utilities to diagnose a connectivity or a performance issue)。
课程同时给出了这两组工具的元评价,这句话是理解本篇的钥匙:每一个命令都监控 Fabric 中的某一个特定方面;然而在某些场景下,用一个具备很多功能的工具来执行 Fabric 诊断会更高效(each of the commands monitors a specific aspect in the fabric. however, in some cases it's more efficient to use a single tool with many features that performs fabric diagnostics)。
这两句话组合起来,规定了 ibdiagnet 的存在方式。它不是要替代第一线工具,而是要替代"人工把十几个第一线工具各跑一遍再拼凑结论"这个动作。这个判断在实践中的含义很具体:
- 问题定位时用第一线工具——因为它能给出最直接、最聚焦的证据
- 问题不明或需要全网取证时用 ibdiagnet——因为它一次跑完就把所有可观测面都采了一遍,并且把结果落成了文件,可以离线反复分析
请注意课程的措辞是 in some cases(在某些场景下),不是 always。这是准确的:定位到具体链路之后,仍然应该切回 ibstat / ibqueryerrors 这类更聚焦的工具,见第十四节。
把上面的分析往下推一层,会得到一个对排障方法论影响很大的结论。InfiniBand 的端口状态机(本系列第八篇)只报告"这条链路当前是否处于 Active 状态",它不报告"这条链路过去 24 小时有没有误码、有没有因为下游缓冲不足而排队"。这两件事在协议层面是分开的:
状态机判定的是链路当前能否传数据。它由训练序列与 dummy packet + VCRC 校验驱动,是一个瞬时判定,判定完成之后就不再随时间更新历史。它的输出是一个枚举值,不是计数器。
计数器记录的是链路在整个生命周期里做过什么。symbol_error_counter 累计的是物理层接收时校验出比特错的数量;port_xmit_wait 累计的是包在发送缓冲里等待的时间;port_xmit_discard 累计的是因本地原因被丢弃的包。它们不会因为"链路现在是 Active"而归零,也不会因为"链路现在是 Active"就证明自己为零。
这个分离直接推出两条操作规则,本篇后面反复用到:第一,看状态不能代替看计数器,看计数器也不能代替看状态。状态说 Active 只证明"现在能传",不证明"过去没出错";计数器为零只证明"统计窗口内没出错",不证明"现在能传"。第二,计数器是累积值,脱离时间窗口单独看一个累积值几乎没有意义——同一个 2849,可能是十年来每小时 0.3 个的稳定误码,也可能是刚刚开始恶化的一根坏线。第九节给出 --pm_pause_time 取差值、以及 -pc 清零后重新观察这两条标准做法,就是为了让计数器回到"速率"这个有意义的量纲上。
还要补一个容易被忽略的推论:正因为状态机与计数器是两条独立的信息源,任何声称"用一条命令就能判定链路健康"的说法都不成立。本篇第十二节提到的 UFM Cyber-AI / 之类托管诊断产品之所以有价值,正是因为它们把这两条信息源、以及更多厂商私有计数器统一到了一处——但它给出的仍然是结论,而 ibdiagnet 给出的是原始材料。
本节关键记忆:5 类问题 + 2 层工具 + 1 个方法论
- 5 类问题:线缆 / 端口 / 配置(含路由)/ 软件版本失配 / 链路超额订阅;只有"端口故障"能被状态机直接发现
- 2 层工具:DOCA-OFED 第一线工具(各管一个方面)→ ibdiagnet(一个工具做很多事,把 fabric 全状态采成文件)
- 1 个方法论:"状态正常"只证明现在能传,计数器才记录过去发生了什么;两个信息源必须都看
- 1 个量纲提醒:累积计数器脱离时间窗口没有意义,必须取差值或清零后重测(第九节)
三、ibdiagnet 的定位与工作原理:为什么定向路由是它的基础
What — 官方对工具的一句话定位
ibdiagnet User Manual 与 ibdiagnet(1) man page 对这个工具的定位是一句话:它是 InfiniBand Fabric 发现、错误检测与诊断的基本工具之一(one of the basic tools for InfiniBand fabric discovery, error detection and diagnostics)。
软件归属上,ibdiagnet 作为 ibutils2 包的一部分分发,而 ibutils2 又包含在 DOCA-OFED 与 UFM 软件包中。课程还补了一句它不在这两个包里的情况:它也以 InfiniBand 管理包的形式在 NVIDIA 官网单独提供下载。
3.1 工作原理:扫描是靠"自己发包"完成的
Why — 定向路由让"扫描"这个动作不需要被扫描方的任何配合
ibdiagnet(1) man page 对工作原理的描述是一句关键的话:当它运行时,它使用定向路由包(directed route packets)扫描 fabric,并提取关于连通性与设备的全部可用信息(When ibdiagnet runs, it scans the fabric using directed route packets and extracts all the available information regarding its connectivity and devices)。
这句话里"定向路由"四个字是整台工具的技术地基,有必要把它与本系列第八篇的 SMP 发现机制对照着看,因为这两者是完全不同的两套寻址方式:
| 维度 | SM 的 SMP 发现(ib-08) | ibdiagnet 的定向路由扫描 |
|---|---|---|
| 寻址依据 | LID 路由为主(已知目的 LID 才能发) | 不需要预先知道目的 LID——包头里直接写"要去的交换机端口编号"与"要走多少跳" |
| 扩散方式 | 逐跳发现:交换机作为跳板继续向下探 | 逐端口探:对每个已知端口生成一条定向路由包,看有没有回包 |
| 能否发现未配置的设备 | 不能——没有 LID 就没有可用的路由,SM 发现不了 | 可以——这正是诊断工具与配置工具的根本分野 |
| 对 SMA 的依赖 | 强依赖:设备必须应答 SMP | 不依赖——这是本篇第十二节"为什么它能发现无响应设备"的答案 |
把上表最后一行与本系列第十四篇的结论连起来:ib-14 说"固件版本不对 → 设备连 SMP 都应答不了 → SM 永远发现不到它",而 ibdiagnet 不受这条链的约束。原因是定向路由包的目标是交换机端口而不是某个需要 SMP 应答的节点——它问的是"这条路径通不通",而不是"这个节点是谁"。
这也解释了 -c 选项的语义。ibdiagnet(1) man page 写明:发现阶段结束后,定向路由包会被发送多次(次数由 -c 决定,默认 10)以检测可能丢包的问题路径;这些路径会被逐一探查,并在标准输出上给出可疑坏链路的报告。也就是说,同一批包发多次这件事本身就是一种检测手段——发一次通、发十次也通,与发一次通、发十次有丢,是两个不同的结论。
3.2 官方功能清单:20 项功能,本篇的骨架
What — ibdiagnet User Manual 第 2 章的 Functionality 表
官方手册用一张表列出 ibdiagnet 的全部功能。这张表是本篇后续所有章节的索引,本节逐条抄录并标注本篇哪一节展开:
| # | 官方功能名 | 官方描述要点 | 本篇 |
|---|---|---|---|
| 1 | Fabric Discovery | 扫描 fabric,从交换机、HCA、路由器、聚合节点、网关收集信息 | 第六节 |
| 2 | Duplicated GUIDs Detection | 检查并报告 fabric 中重复的 Node GUID 与 Port GUID | 第六节 |
| 3 | Duplicate Node Description Detection | 检查并告警交换机或 HCA 的重复节点描述 | 第六节 |
| 4 | Alias GUIDs Check | 执行别名 GUID 检查(仅与 ConnectX-3 设备相关) | FAQ Q14 |
| 5 | LIDs Check | 对 InfiniBand 设备执行正确的 LID 分配与重复 LID 检查 | 第七节 |
| 6 | Links in INIT State and Unresponsive Nodes Detection | 报告处于 INIT 逻辑状态的链路;并报告无响应设备及到这些设备的定向路由 | 第七节 |
| 7 | Split Cables Support | 在 dump 与日志中报告分裂线缆(split cable) | 第十一节 |
| 8 | Counters Fetch | 从设备取各类计数器:标准与扩展端口计数器、诊断计数器、phy 计数器等 | 第八节 |
| 9 | Error Counters Check | 检查在两次计数器快照之间跨越阈值的错误计数器 | 第八节 |
| 10 | Routing Fetch and Checks | 执行交换机转发表正确性检查,以及无信用环路由的检查 | 第十二节 |
| 11 | Link Width and Speed Checks | 检查 fabric 链路是否运行在最大支持的速率与宽度 | 第九节 |
| 12 | Dumping Virtualization Information | 从通道适配器导出虚拟化信息 | FAQ Q18 |
| 13 | Dumping SHARP Trees Structures and SHARP Counters | 导出 SHARP 树结构与计数器 | 本篇不展开 |
| 14 | Dumping SHIELD Configuration and Counters | 导出 SHIELD 配置与计数器 | 本篇不展开 |
| 15 | Topology Matching | 把 fabric 拓扑与先前存储的拓扑做匹配 | 第十二节 |
| 16 | Fast Discovery | 通过使用先前缓存的 fabric 数据避免重新发现 fabric | 第十三节 |
| 17 | Support IB Security | 使用 MKEY、VSKEY、AMKEY、CC KEY 导出 fabric 配置 | FAQ Q19 |
| 18 | Partition Checks | 导出并校验 HCA 与交换机的分区表 | 第十一节 |
| 19 | BER Test | 报告高误码率的链路 | 第十二节 |
| 20 | Dump PCI Data / Cable Info / PHY Info | 导出服务器 PCI 数据、线缆信息、PHY 信息 | 第十二节 |
请对照转写稿那段列举:课程口述的十余项与官方表的 20 项基本对应,但漏掉了 Alias GUIDs、Split Cables、虚拟化、SHARP、SHIELD、IB Security 六项。这个差异本身值得注意——官方功能表里有若干项是"平台相关"的(AGUID 只对 ConnectX-3 相关、BER 的 --ber_test 只对 SwitchX/ConnectX-4/ConnectX-3 有效),课程只讲了与当时演示环境匹配的那部分。第十节与 FAQ 会逐条说明哪些是"本篇环境可用"、哪些是"换平台才出现"。
本节关键记忆:1 句定位 + 1 条原理 + 1 张 20 行功能表
- 1 句定位:ibdiagnet 是 InfiniBand fabric 发现、错误检测与诊断的基本工具之一,由 ibutils2 包分发,含在 DOCA-OFED 与 UFM 中
- 1 条原理:用定向路由包扫描 fabric;-c 控制每条链路的发包次数(默认 10),多次发送本身就是检测手段
- 1 个关键分野:ibdiagnet 不依赖被扫描设备的 SMA——它问"路径通不通"而不是"节点是谁",所以能发现未配置、无响应乃至不在线的设备,这是 SMP 发现做不到的
- 1 个功能覆盖面:官方 20 项功能,本篇覆盖其中 14 项,其余 6 项给出定位与出处
四、运行前的四个准备:版本、自检、多 HCA 选卡、配置预置
What — 课程点出的三个前置动作与官方补充的第四个
课程在介绍工具时给出了三个明确动作,顺序是有意义的,不能调换:
- 先确认你装的是哪个版本——课程说这一步是"你首先应该做的事",用 --version(或 -v)确认 ibdiagnet 是否已安装、能否用于扫描 fabric
- 用 -h / --help 发现更多能力——课程说 ibdiagnet 有多个高级特性,应通过 help 选项去发现
- 不带任何参数运行——这是最简单的用法,会执行本节列出的那一整套诊断
官方手册补充了课程没讲、但对可复现性至关重要的第四个准备:配置文件。这一项课程完全没有提到,但它会静默改变 ibdiagnet 的默认行为,必须单独讲。
4.1 三个自检命令:确认装了、确认能跑、确认环境
How — 三个命令各自的定位
| 命令 | 回答什么问题 | 注意 |
|---|---|---|
| ibdiagnet --version (短选项 -V) |
装没装、什么版本 | -v 在新版里是 verbose,不是 version;版本请用 -V 或 --version |
| ibdiagnet -h (或 --help) |
这版工具到底支持哪些选项 | 官方说明中特别注明:帮助信息里也包含插件(plugin)的帮助——若装了线缆诊断 / PHY 诊断插件,它们的选项也会出现在这里 |
| ibdiagnet --vars | 打印工具的环境变量及其取值 | ibdiagnet(1) man page 明确列出这一条;排查"为什么行为和文档不一致"时,先跑它 |
把课程那句"这个输出说明 ibdiagnet 已安装、并且可以用于扫描 fabric"落到实践上:它给出的不只是版本号,还有插件加载路径。公开文档中记录的一次实际运行输出,第一行就是加载插件的位置:
# ibdiagnet --version
Load from /usr/share/ibdiagnet/2.1.1
ibdiagnet 2.1.1
这里有个实用技巧:插件目录名里嵌了版本号。如果 --version 报的版本是 2.1.1 而 ls /usr/share/ 下出现多个 ibdiagnet* 目录,说明系统里存在多版本共存,此时"我到底在跑哪一版"这个问题必须靠实际执行路径确认,不能靠包管理器推断。
4.2 多 HCA 主机上的选卡规则:默认用第一个活动接口
What — 官方手册"Selecting InfiniBand Interface"一节的原文口径
课程在这里讲得很直接:在一台安装了多个 HCA 的系统上,ibdiagnet 与其他 OFED 工具一样,在没有指定接口时会使用第一个活动接口。官方手册的表述与它完全一致:若下列选项未指定,ibdiagnet 将使用第一个活动的 IB 接口(first active IB interface will be used by ibdiagnet)。
要显式指定目标端口,三个官方选项:
- -i / --device:指定用于连接 IB fabric 的设备名(本机有多设备时)
- -p / --port:指定本设备用于连接 IB fabric 的端口号
- -g / --guid:指定本机端口 GUID 值;若 GUID 传 0,ibdiagnet 会列出所有可选端口 GUID 并等待用户输入
官方给出的组合示例是:
# multi-HCA host: bind the scan to one specific port
ibdiagnet -i mlx5_0 -p 1
# list every selectable port GUID, then pick one by GUID
ibdiagnet -g 0
这条规则的实践含义:多卡机器上"我以为我扫的是这台"经常是错的
结合本系列第十四篇已经确立的一条结论来看这件事:mlx5_0 是驱动族名加枚举序号,不携带型号信息,换卡后名字不变。因此"用 -i mlx5_0 指定要扫的卡"这个动作本身就选错了依据——它选的是枚举顺序,不是你想诊断的那张卡。
在多 HCA 主机上做 Fabric 诊断,推荐的做法是先用 -g 0 让工具把候选端口 GUID 列出来,再按 GUID 选。GUID 是唯一可靠的设备身份标识——这一点本系列第一篇《InfiniBand 架构简介:从五层模型到子网管理》已经确立。
4.3 配置文件:一个会静默改变行为的入口
Why — 为什么"我没给这个选项,它怎么就变了"必须有一个答案
官方手册第 4.3 节 "Using Configuration File" 写明:所有 ibdiagnet 选项都可以在配置文件中事先指定;默认配置文件位于 /etc/ibutils2/ibdiag.conf(默认配置文件名与 ibutils2 包名同源,见第一节误听表第 2 条)。
生效规则这一句必须记住:如果 --config_file 选项未指定、但默认位置存在该文件,那么文件里定义的配置项将被应用——除非被命令行上的具体选项覆盖(applied if not overridden by specific options in the ibdiagnet command line)。
官方给的示例很具体:
# /etc/ibutils2/ibdiag.conf
# applied when --config_file is absent and this file exists,
# and overridden by any option given on the command line
ibdiagnet -i mlx5_0
ibdiagnet -p 1
两个相关选项一并记下:
- --config_file:从指定文件加载配置
- -c / --create_config_file:创建一份模板配置文件——这是第一次部署该工具时最该先跑的一条命令,它把"当前生效的全部配置"固化下来,成为可版本化的运维基线
由此得出一条本篇反复用到的纪律:任何一次 ibdiagnet 的执行结果,只有在"版本 + 命令行 + 配置文件"三者都被记录下来时才是可复现的。这一点在第十三节讲取证流程时会再展开。
本节关键记忆:4 个准备 + 3 个选卡选项 + 1 个静默入口
- 4 个准备:--version 确认版本(注意 -v 是 verbose 不是 version)/ -h 发现能力(含插件)/ --vars 看环境变量 / -c 导出配置模板
- 3 个选卡选项:-i 设备名、-p 端口号、-g 端口 GUID(传 0 会列出候选让你选);未指定时用第一个活动接口
- 1 个静默入口:/etc/ibutils2/ibdiag.conf 会被自动应用,命令行可覆盖它;取证时必须一并记录
- 1 个推论:多卡机器上"用 -i mlx5_0 选卡"依据是枚举序号而非设备身份,正确做法是 -g 0 列出候选后按 GUID 选
五、屏幕输出的骨架:12 个默认阶段与官方 20 项功能
What — "不带参数运行"到底会做什么:官方手册的 12 项清单
课程说"最简单的用法是不指定任何命令行参数直接运行 ibdiagnet,它会执行前面列出的那些诊断",并且预告"后面会看到我们可以用不同的命令行参数来限制或扩展 ibdiagnet 执行的诊断"。这里必须把"前面列出的那些"落实成一份确切清单——官方手册第 4.2 节 "Running ibdiagnet without Parameters" 给出的就是这份清单,一共 12 项:
| # | 默认执行的诊断 | 它在查什么 | 本篇 |
|---|---|---|---|
| 1 | Fabric Discovery | 扫全网,采集所有设备与连接关系 | 第六节 |
| 2 | Duplicated GUIDs check | 重复的 Node GUID / Port GUID | 第六节 |
| 3 | Duplicated Node Description Check | 重复的节点描述 | 第六节 |
| 4 | LID Check | LID 分配是否正确、有无重复 LID | 第七节 |
| 5 | Links Check | INIT 逻辑状态的链路、无响应节点 | 第七节 |
| 6 | Subnet Managers Check | SM 状态与优先级 | 第七节 |
| 7 | Port Counters Snapshot/Checks in One Sec Period | 一秒间隔两次采样取差值 | 第八节 |
| 8 | Nodes Information Check | 全网固件版本是否统一等 | 第九节 |
| 9 | Speed/Width Check | 链路是否跑在最大支持的速率与宽度 | 第九节 |
| 10 | Dump Virtualization Information | 虚拟化信息 | FAQ Q18 |
| 11 | Partition Keys Checks | 导出并校验 HCA 与交换机分区表 | 第十一节 |
| 12 | Dump Temperature Sensing | 温度传感数据 | FAQ Q18 |
这份清单还多出第 13 项,课程也提到了:Create Network Dump File Similar to the ibnetdiscover Format——生成 ibnetdiscover 格式的网络 dump 文件。这就是第十二节讲的拓扑基线文件,默认运行就会产生,不需要额外加参数。
课程口述与官方清单的三处差异,需要按官方为准
- 差异一:课程提到"转发表正确性检查与信用环路由检查",但它不在默认 12 项里——那属于 -r / --routing 选项,必须显式加。官方功能表里 Routing Fetch and Checks 与 Link Width and Speed Checks 是并列的两项,但后者默认执行、前者默认不执行
- 差异二:课程提到 BER 检查,默认 12 项里也没有——--ber_test 需要显式加,且官方标注它只对 SwitchX / ConnectX-4 / ConnectX-3 设备有效,更新的设备要用 --get_phy_info 做 BER 校验
- 差异三:课程说"检查错误计数器跨越阈值",但没提这个检查依赖 -P——不指定阈值时没有"跨越"可言,详见第八节
这三条的共同教训:课程按"演示环境里用到的功能"组织讲解,官方按"工具的全部能力"组织文档。做生产环境规划时,以官方清单为准,把不在默认集里的功能显式加进命令行。
5.1 输出的物理结构:分隔线、阶段名、三种前缀
How — 屏幕上那些横线与字母前缀不是排版,是有语义的
课程说"输出被分成若干阶段、用虚线分隔",这一句在实践中的含义比听起来重要:横线划出的每一个区块是一个独立的诊断阶段,阶段名紧跟在横线之后。公开文档中记录的一次完整运行输出,结构是这样的:
###################################
-I- Log file /var/tmp/ibdiagnet2/ibdiagnet2.log created
###################################
###################################
# Discovery
###################################
-I- 6 Switches, 19 CAs, 55 Ports
###################################
###################################
# LIDs Check
###################################
-I- Noduplicated LID Switches
###################################
###################################
# Links Check
###################################
-I- All links are in INIT state
###################################
###################################
# Subnet Manager Check
###################################
-I- 1 Master SM, other SM 0
###################################
###################################
# Port Counters
###################################
-I- PortCountersDelta, PauseTime 1
###################################
###################################
# Nodes Information
###################################
###################################
# Summary
###################################
Warnings Errors
Discovery 0 0
LIDs Check 0 0
Links Check 0 0
SM Check 0 0
Port Counters 0 0
Nodes Information 0 0
Speed / Width checks 0 0
Pkey Check 0 0
三种前缀的含义必须记牢,因为它们决定了你该不该往下查:
| 前缀 | 含义 | 看到它该做什么 |
|---|---|---|
| -I- | Informational,信息 | 正常输出,描述"看到了什么",本身不代表有问题 |
| -W- | Warning,告警 | 需要判断:可能是真问题,也可能是可接受的现状(例:固件版本本来就允许不统一) |
| -E- | Error,错误 | 需要立即处理,错误通常意味着某个检查阶段未能完成 |
还有一个容易漏掉的行为:屏幕上的错误与告警条数是有限的。官方 --screen_num_errs 选项的含义是"指定打印到屏幕的错误消息阈值上限(默认 5)",超出部分只记录到 ibdiagnet2.log 文件里。官方给出的对照示例非常直白:
# default: only the first 5 errors reach the screen
-E- 1: node xxx, port 3, error ...
-E- 2: node xxx, port 5, error ...
-E- 3: node xxx, port 7, error ...
-E- 4: node xxx, port 9, error ...
-E- 5: node xxx, port 11, error ...
-I- 11 more messages in the log file
# raise the screen threshold
ibdiagnet --screen_num_errs 20
这里藏着一个非常容易造成误判的陷阱:加了 --screen_num_errs 之后,屏幕看起来"干净了",但问题一条都没少。判断一次巡检是否干净,必须以 Summary 汇总表与日志文件为准,不能以屏幕输出为准——这正是第十节要展开的内容。
5.2 三种结果输出物:屏幕、日志、dump 文件
What — 课程强调"屏幕之外还有 dump 文件",官方把三者的分工讲得更清楚
课程说"除了显示在屏幕上的命令输出之外,ibdiagnet 还会生成包含 fabric 额外信息的 dump 文件;生成哪些文件取决于运行时使用的命令行参数"。这句话在官方文档里被拆成三个明确的输出物:
- 标准输出(屏幕):按阶段组织的进度与告警,受 --screen_num_errs 截断
- 日志文件 ibdiagnet2.log:完整的应用报告,不受屏幕截断影响
- 各 dump 文件:.lst / .fdbs / .sm / .pm / .pkey / .db_csv 等,由命令行参数决定产出哪几个
三者的关系用一句话概括:屏幕是给你看进度的,日志是给你看结论的,dump 文件是给分析工具看的。绝大多数"看起来没报错"却仍有问题的现场,原因都是只看了屏幕、没看日志。
官方还补充了两个现代版本才有的便利特性,它们对取证流程影响很大:dump 文件中会包含 ibdiagnet 的版本号与命令行参数(Dump files include ibdiagnet version and command line parameters)。这一条把第四节说的"三者都要记录"从运维纪律变成了工具自带能力——dump 文件自带版本与命令行,因此它本身就是自证的。
本节关键记忆:12 项默认诊断 + 3 种前缀 + 3 类输出物 + 1 个陷阱
- 12 项默认诊断(+1 项默认生成 ibnetdiscover 格式文件);路由校验与 BER 检查默认都不执行,必须显式加 -r / --ber_test
- 3 种前缀:-I- 信息 / -W- 告警需判断 / -E- 错误需处理
- 3 类输出物:屏幕(进度,受截断)/ ibdiagnet2.log(完整结论,不受截断)/ dump 文件(给分析工具)
- 1 个陷阱:--screen_num_errs 让屏幕变干净但问题一条不少,全在日志里;判干净要看 Summary 与日志
- 1 个取证便利:新版 dump 文件自带版本号与命令行参数,dump 文件本身自证来源
六、Discovery 阶段:一切结论的证据从这一行开始
What — 这一阶段报告的是"网络上有什么",不是"网络对不对"
官方对 Fabric Discovery 的定义是:扫描 InfiniBand fabric,并从下列 InfiniBand 设备收集信息:交换机、HCA、路由器、聚合节点、网关(Sweeps the InfiniBand fabric and collects information from the following InfiniBand devices: Switches, HCAs, Routers, Aggregation Nodes, Gateways)。
请注意这个清单里路由器、聚合节点、网关三类是"设备"而不是"交换机"——它们在 ibdiagnet 的输出里与交换机并列统计。这一条在第八篇讲 Min Hop 路径计算时出现过(多级交换机的不同 IC 有各自的 LID),在第十篇讲 Dragonfly+ 时也出现过(Dragonfly+ 的收敛节点被单独计为一个角色)。
课程给出这一阶段的读法:Discovery 阶段输出的是从 InfiniBand 设备(交换机、HCA、路由器、网关)收集到的信息;可以看到发现了多少个节点、都是什么类型。公开文档记录的一次输出显示了实际格式:
###################################
# Discovery
###################################
-I- 6 Switches, 19 CAs, 55 Ports
-I- Duplicated node descriptions
-I- No Duplicated GUIDs
课程举的例子是 6 台交换机、19 个 CA、55 个端口,并给出两句关键结论:没有检测到重复的 GUID,也没有检测到重复的节点描述。这两句"没有检测到"是阴性结果,它们的价值在于排除,排除之后剩余的可能原因就少了。
6.1 三个子检查各自的实际含义
How — GUID 重复、节点描述重复、LID 重复是三件不同的事
这三个概念在转写稿里被混成了一团(见第一节误听表第 7 条),必须彻底分开。它们检查的对象、后果、严重程度全都不同:
| 检查项 | 检查对象 | 出问题意味着什么 | 能否自己修 |
|---|---|---|---|
| Duplicated GUIDs Detection 默认执行 |
Node GUID 与 Port GUID 同一份 fabric 里出现两个相同的 GUID |
身份冲突:SM 无法区分这两个设备,转发表与路由计算的结果全部失去意义 | 不能。必须找到冲突源(常见于克隆 MAC 烧 GUID、虚拟机模板复制、换板后 GUID 未清零) |
| Duplicate Node Description Detection 默认执行 |
Node Description 字段 两个不同设备的描述字符串相同 |
可读性问题为主:GUID 仍唯一,路由不受影响,但报告里两个设备长得一样,人工判读容易搞混 | 能。改设备描述即可 |
| LIDs Check 默认执行 |
LID 分配与唯一性 同一子网内两个端口拿到同一个 LID |
转发错误:包会被送到错误的端口 | 不能自行修,必须由 SM 重新分配(见 ib-08 的 LID 分配机制) |
三者的严重程度排序是 GUID 重复 > LID 重复 > 节点描述重复,但可修复性恰好相反。这个"严重度与可修复性不同向"的特征,是排障时最值得记住的一条。
课程提到这个子检查的判读要点:检查并告警交换机或 HCA 的重复节点描述(Checks and warns regarding duplicated node description of switches or HCAs)。"告警"而非"错误"这个用词是准确的——它对应第二节表里"只有端口故障能被状态机直接发现"这个结论的补充:节点描述重复不会让网络变慢,但会让你的排障过程变慢。
6.2 GUID 重复检测的一个官方开关
Tip — ibdiagnet 默认不做交换机 GUID 重复检查,要显式打开
官方手册第 4.6 节写明:默认情况下,ibdiagnet 在网络发现时不检查重复的交换机 GUID;要允许这项检查,必须指定 --enable_switch_dup_guid。
# duplicate switch GUID check is OFF by default
ibdiagnet --enable_switch_dup_guid
实践建议:把 --enable_switch_dup_guid 加进周期性巡检的命令行。理由是交换机 GUID 冲突虽然罕见,但一旦发生是灾难性的——它会让两台交换机在 SM 眼里变成同一台,而这种故障在业务侧的表征是"部分流量黑洞",极难定位。
把 Discovery 阶段单独拎出来看,会发现它在整台工具里承担的是一个很特殊的角色:它是唯一一个不做合格判定的阶段。其余每个阶段都会给出"通过 / 有告警 / 有错误"的结论,只有 Discovery 阶段只负责陈述"我看到了什么"。这个设计决定了它在运维流程中的位置。
从"发现什么"这个动作本身看,它是自顶向下的。工具从本机的一个活动端口出发,靠定向路由包逐跳、逐端口地把整张 fabric 走一遍,走到哪里就采哪里的信息。这意味着它的可见性边界等于定向路由的可达范围——而定向路由不需要目的 LID 配合,因此这个范围在正常状态下覆盖全网,在异常状态下则恰好暴露出"走不到的地方"。这就是为什么"Discovery 没发现某个设备"本身就是一条有价值的诊断信息,而不只是"少了一个节点"。
从"报告什么"这个动作看,它是自底向上的证据汇总。它把走过的每一跳采集到的三类信息(身份、描述、连接)汇成一行统计。这一行的价值完全取决于它是否可与其他时间点的同类输出做比较——孤立的"4 个节点"没有意义,"昨天 4 个、今天 3 个"才是结论。
由此推出本篇反复要用的一条纪律:Discovery 阶段的输出必须被存成时间序列,而不是被看过就算。这也解释了为什么第十二节把 -w 拓扑基线列为进阶用法的核心——它的价值不在"导出当前拓扑",而在"让下一次运行有可比对的参照物"。
还要补一个容易被忽略的边界:Discovery 报告的节点数,与 ibswitches 报告的交换机数,不是同一个集合。ibdiagnet 的 1 Switches & 3 CA-s 统计的是它在本次扫描中能到达的节点,而 ibswitches 走的是 SMP 逐跳查询,对无响应设备无能为力。因此"ibswitches 说有 N 台交换机,ibdiagnet 只发现 N-1 台"是一个非常有价值的交叉验证信号——差的那一台,一定是有问题的。见 FAQ Q8。
本节关键记忆:5 类被采集设备 + 3 个子检查 + 1 个默认关闭的开关 + 1 个用法纪律
- 5 类被采集设备:交换机、HCA、路由器、聚合节点、网关(后 3 类不是交换机,单独计数)
- 3 个子检查分家:GUID 重复(身份冲突,最严重,不可自修) / 节点描述重复(可读性问题,可自修) / LID 重复(转发错误,必须 SM 重分配);严重度与可修复性不同向
- 1 个默认关闭的开关:--enable_switch_dup_guid,建议加进周期巡检
- 1 个用法纪律:Discovery 输出必须存成时间序列;"比上次少了谁"才是结论,孤立数字无意义
- 1 个交叉验证点:ibdiagnet 发现数少于 ibswitches 报告数 = 差的那台有问题(因两者可达性不同)
七、LIDs / Links / SM 三个检查阶段:分别对应前序三篇的三套机制
What — 三个阶段的官方定义,逐条抄录
- LIDs Check:对 InfiniBand 设备执行正确的 LID 分配与重复 LID 检查(Performs correct LID assignment and duplicated LID check for InfiniBand devices)
- Links in INIT State and Unresponsive Nodes Detection:报告处于 INIT 逻辑状态的链路;此外还报告无响应设备以及到这些设备的定向路由(Reports links in INIT logical state. Additionally, it reports unresponsive devices and Direct Route to such devices)
- Subnet Managers Check:报告 fabric 中 SM 的状态与优先级(本篇依据 ibdiagnet.sm dump 文件的官方描述)
课程对这三条的读法非常准确,并且给出了三者"全部成功"这个结论该如何理解:LIDs Check 报告 LID 分配是否正确、并对 InfiniBand 设备执行重复 LID 检查;Links Check 报告处于 INIT 逻辑状态的链路与无响应节点;SM 阶段报告 fabric 中识别出了一个 Master SM;可以看到这三项检查全部成功完成。
把这三条与本系列的前序文章对上号,会发现一个很清晰的结构——它们检查的正是前序三篇各自描述的那套机制的产出物:
| 本篇阶段 | 检查的对象 | 对应本系列哪一篇的机制 |
|---|---|---|
| LIDs Check | LID 是否被正确分配、有无重复 | 第八篇《子网初始化》的 LID 分配三条规则 + Min Hop 路径计算的产物 |
| Links Check | 链路逻辑状态是否为 Init、节点是否应答 | 第八篇的端口状态机(Down/Init/Armed/Active)+ 第九篇《SM 监控与拓扑变化》的 Trap 与重收敛 |
| Subnet Manager Check | SM 的状态与优先级 | 第九篇的 Master SM 选举与 failover / handover |
这就把"为什么要用 ibdiagnet 而不是分别跑 ibstat 和 smpquery"回答清楚了:因为它检查的正是那几篇讲的机制的结果,一次跑完就能确认"子网管理器该做的事都做了"。
7.1 Links Check 的"定向路由"是本篇最该记住的一个细节
Why — 无响应设备为什么还能被检查出来
官方对 Links Check 阶段的定义里,"报告无响应设备以及到这些设备的定向路由"这半句最容易一带而过,但它正是第二节那条方法论的直接体现。
回想 ib-14 建立的因果链:设备固件异常 → 不能应答 SMP → SM 发现不到 → 不分配 LID → 业务不通。如果诊断工具也依赖 SMP,那么这条链的最上游那个故障点恰恰是它唯一看不见的——你会看到一个"少了这个节点"的 fabric,但看不到"为什么少"。
定向路由扫描绕开了这个盲区。逻辑是:
SM (managed port)
|
v
+------------+------------+
| |
+----+----+ +----+----+
| SW 1 | | SW 2 | it is physically reachable,
it is the SM that cannot talk to it.
这个结构还有一个实际好处:到无响应设备的定向路由本身就是一条可操作的排查线索——它告诉你"这个设备在 fabric 的哪个位置、经过哪几跳"。有了这个位置信息,才谈得上"去那个位置的交换机上看端口状态"。
同时要清楚 Links Check 的边界:它报告的是"逻辑状态为 Init 的链路"与"无响应的设备",但它不判断"为什么 Init"。停在 Init 的原因可能是对端没上电、可能是对端不在 Armed、也可能是 VCRC 校验没通过——而这三种原因要靠第八篇的物理状态判读法与 ibstat 输出才能区分。
7.2 Subnet Manager 阶段:确认"恰好有一个"比确认"有"更重要
How — 从 dump 文件反推这个阶段在做什么
课程说"SM 阶段报告在 fabric 中识别出了一个 Master SM"。"一个"这个量词是重点——它对应的判断是"恰好有一个 Master",而不是"至少有一个"。
为什么"恰好"比"有"更重要,这在本系列第九篇《SM 监控与拓扑变化:选举、故障切换、扫描与重收敛》里有完整机制:
- 有多个 Master → 两个 SM 各自编程转发表,结果是转发表被反复互相覆盖,表现为"部分流量黑洞 + 部分流量正常"的间歇性故障
- 没有 Master → 没有任何 SM 在配置子网,表现为新接入的设备永远停在 Init
- 有一个 Master → 正常
这三态在 ibstat 输出里对应本系列第十四篇已经引用过的字段组合 Base lid / SM lid,所以诊断时两条命令要对照着看:ibdiagnet 说"识别出一个 Master",ibstat 说"本机看到的 SM lid 是谁",两者不一致就说明视图本身有问题。
官方 ibdiagnet.sm dump 文件的描述是 "List of all the SM (state and priority) in the fabric"——状态与优先级两项都在里面。这就解释了为什么这个阶段能发现"多个 Master":它不只看谁是 Master,而是把全网 SM 的状态和优先级都列出来,多个 SM 同时标为 Master 就会被看见。详见第十一节。
本节关键记忆:3 个阶段 + 1 个技术细节 + 1 个三态判断
- 3 个阶段各自的对象:LIDs Check 查 LID 分配与重复(ib-08 的产物)/ Links Check 查 Init 链路与无响应节点(ib-08 + ib-09)/ SM Check 查 SM 状态与优先级(ib-09 的产物)
- 1 个技术细节:Links Check 报告"到无响应设备的定向路由"——这就是它能发现不响应 SMP 设备的原因,也是排障时最有用的定位信息
- 1 个边界:Links Check 报告"是 Init"但不判断"为什么 Init",三种可能原因要靠 ib-08 的状态判读法区分
- 1 个三态判断:恰好一个 Master(正常)/ 多个 Master(转发表互相覆盖)/ 没有 Master(新设备永远 Init);与 ibstat 的 SM lid 对照看
八、Port Counters 阶段:两次采样取差值,以及三类计数器的判读方向
What — 官方口径:收集什么、怎么收
官方手册第 4.8 节开篇一句话:ibdiagnet 收集并处理标准 InfiniBand 端口计数器与厂商特定端口计数器。它列出被采集的计数器分七个类别,其中四类默认采集:
| 计数器类别 | 采集时机 | 说明 |
|---|---|---|
| PortCounters | 默认采集 | 规范定义的基础端口计数器 |
| PortCountersExtended | 默认采集 | 规范定义的扩展端口计数器 |
| PortRcvErrorDetails | 默认采集 | 接收错误明细 |
| PortXmitDiscardDetails | 默认采集 | 发送丢弃明细 |
| LLRCounters | 支持该能力的设备默认采集 | 仅 ConnectX-3 / SwitchX |
| PerSL/VL counters | 需指定对应选项 | --per_slvl_cntrs |
| PortExtendedSpeedCounters | 需指定对应选项 | --extended_speeds |
| Mellanox Diagnostic Counters | 需指定对应选项 | --sc,输出到 ibdiagnet2.mlnx_cntrs |
这个"默认采集 / 需指定选项"的划分有很实际的含义:默认那一组是规范级的,任何平台都有;后三组是能力级的,不同厂商不同代次支持情况不同,必须显式要求才会去取。要一次取全,官方给了两个聚合开关:
- --pm_get_all:取全部 PM 计数器,它会自动激活 --per_slvl_cntrs / --sc / --extended_speeds all / --pm_per_lane 四个选项
- --pm_clear_all:清空全部 PM 计数器,它会自动激活 --scr / --pc / --qos 三个选项
8.1 为什么要采样两次:把累积值换算成速率
Why — 课程讲的"差值",以及它解决的是第二节提出的量纲问题
课程对这一阶段的描述是:ibdiagnet 收集并处理标准 InfiniBand 端口计数器与厂商特定端口计数器;它报告两次采样之间端口计数器数值的差值,两次采样间隔一秒。课程还补了一句"我们很快会看到这个计时器怎么按需要设置"。
这个"差值"设计对应的是第二节末尾提出的那个问题:累积计数器脱离时间窗口没有意义。取差值把它变成了"每秒变化多少",量纲回到了可判断的速率上。
但要提醒一个容易被忽略的点:默认的一秒间隔,在多数故障场景下是远远不够的。原因很直接——一个真正在恶化的误码源,可能几分钟才产生一个错误计数;一秒的差值很可能就是 0,此时看到的是"这一秒没问题",不是"这条链路没问题"。官方给的调整选项是:
# default: 1 second between the two samples
ibdiagnet
# widen the window
ibdiagnet --pm_pause_time 60
# single sample, no delta (still the accumulated value)
ibdiagnet --pm_pause_time 0
还有一个必须知道的官方细节:即使把 --pm_pause_time 设为 0(只采样一次、不做差值),它采集到的仍是累积值。所以"我只想快速看一眼当前状态"这个诉求,用 --pm_pause_time 0 是可以满足的;但"我想判断这条链路是否在出错"这个诉求,必须给一个有意义的时间窗口。
那么"有意义的时间窗口"取多长?这取决于你要抓的错误速率,本篇不给具体秒数——因为它取决于链路上实际发生了什么,必须现场测。可行的做法是:用 --pm_pause_time 0 读一次累积值,跑一段业务,再读一次,用两次累积值之差除以经过的时间,得到你这条链路的真实错误速率。这个数才是你后续设定 -P 阈值的依据。
8.2 三类计数器的判读方向:一半要查高值,一半要查低值
What — 课程这段是本篇最容易出错的地方,本节按官方计数器名逐个校准
课程给了一个很正确的判断框架,但其中的术语全部需要校准。先把课程的判断抄录清楚:
- 在 fabric 正常运行时,有些端口计数器应当显示高值——例如发送与接收包数
- 另一些计数器,例如 link down 与 symbol error,应当显示低值
- 对于后者,高值意味着存在问题,应当处理
把这些描述对应到官方的 PM Counter 名称全表(这是判断"哪些是增量型、哪些是存量型"的唯一可靠依据):
| 判读方向 | 官方计数器名(节选) | 语义 | 高值意味着 |
|---|---|---|---|
| 应当高 增量型 |
port_xmit_data / port_rcv_data | 发送 / 接收的字节数 | 正常——只要链路在跑业务,它们就该一直涨 |
| port_xmit_pkts / port_rcv_pkts | 发送 / 接收的包数 | ||
| port_unicast_xmit_pkts / port_unicast_rcv_pkts | 单播包数 | ||
| port_multicast_xmit_pkts / port_multicast_rcv_pkts | 组播包数 | ||
| port_xmit_cells / port_rcv_cells | 发送 / 接收的 cell 数 | ||
| 应当低 存量型 |
symbol_error_counter port_symbol_error |
物理层符号错误 | 物理层或链路层异常——正常链路上这些应当长期保持极小或不增长 |
| link_down_counter | 链路 down 次数 | ||
| link_error_recovery_counter | 链路错误恢复次数 | ||
| port_xmit_discard | 因本地原因丢弃的发送包 | ||
| port_rcv_errors | 接收错误(含物理层与链路层) | ||
| port_rcv_remote_physical_errors | 来自远端的物理错误 | ||
| port_xmit_constraint_errors / port_rcv_constraint_errors | 本地缓冲区不足导致的约束错误 | ||
| excessive_buffer_errors / local_link_integrity_errors | 缓冲区超额 / 本地链路完整性错误 | ||
| 需单独判断 拥塞指标 |
port_xmit_wait | 包在发送缓冲中等待的时间(ASIC 时钟周期数) | 可能存在拥塞——需结合业务量判断,见 8.4 |
| port_xmit_wait 的延伸指标 | — | ||
| 管理面 与业务无关 |
vl15_dropped | VL 15 丢弃计数 | 见 8.5 — 这是本篇最容易被误判的一个计数器 |
本篇第二处关键纠正:port_xmit_wait 是一个计数器名
转写稿把它听成了"port ex im ate weight counter",第一节误听表第 9 条已记录。这里补充它的官方语义——课程对它的解释是完全正确的:该计数器指示数据包在发送缓冲区中等待、直到被发上线缆之前所经过的 ASIC 时钟周期数;可能的原因是接收缓冲区空间不足;该计数器的高值可能指示拥塞,应当进一步调查。
把这段话拆成三个可操作的判断:
- 单位是 ASIC 时钟周期数,不是微秒、不是毫秒——要换算成时间必须知道该 ASIC 的时钟频率,本篇不给这个换算,因为不同型号不同
- 成因是"接收缓冲区空间不足"——注意方向:包是在发送侧等,因为对端的接收缓冲不够,所以排查方向是链路的远端,不是本端
- 它是拥塞指标,不是错误指标——高值不表示链路坏了,表示链路忙。这条与第二节表里"链路超额订阅"那一行对应
本篇把它单列一行并标成 红色,是因为它在实践中最容易被误用:看到高值就报"链路故障"是最常见的错误结论。正确结论是"这条链路当前负载重,需要看容量规划",而不是"这条链路坏了"。还有一条与之配套的判据必须一起记:低负载下 port_xmit_wait 增长本身就是异常—它只在链路被打满时才有值,空闲链路上它增长,意味着链路上出现了本不该有的排队。本系列第十五篇《打流与性能基线》把这个计数器放进了"打流后必读"的清单里,并给出了它在高负载与低负载两种情形下的期望值,本篇讲"它高意味着什么",那一篇讲"它什么时候应该高",两篇必须对照读。
8.3 十六进制显示:一个必须会做的换算
How — 为什么 port_xmit_pkts 会显示成一个看不懂的数
课程指出了一个实际会绊住所有人的细节:端口计数器的值以十六进制表示。公开文档中的一次 ibdiagnet2.pm 输出里,port_xmit_pkts 显示为 0xB19,转成十进制是 2849。
这个换算必须会做,原因是十六进制与十进制的"大小感"完全不同:
| 屏幕上的十六进制 | 十进制 | 人的直觉 |
|---|---|---|
| 0xB19 | 2849 | 看起来像 3 位数,实际接近 3000 |
| 0x1000 | 4096 | 看起来像 1000,实际超过 4000 |
| 0x10000 | 65536 | 看起来像 5 位数,实际是 6 万 5 |
| 0xFFFFFFFF | 4294967295 | 32 位计数器的最大值,约 42.9 亿 |
最后一行有一个必须知道的工程含义:端口计数器是 32 位计数器,上限约 42.9 亿。在跑满 200G 双向、满包大小的极端场景下,计数器回绕(wrap around)是会发生的——此时"读到的值突然变小"不是故障,是计数器归零了。回绕会让"两次采样取差值"这个算法算出负数或巨大的错误值,所以长周期的趋势监控必须能识别回绕。
Tip — 三个实用换算习惯
- 看到 0x 开头的值先换算再判断,尤其是与"应该有多大"的直觉比对时
- 判断"这个值是不是很大"时用数量级:0xB19 是千级,0x10000 是万级,0x1000000 是千万级
- 看到数值突然从很大掉到很小,先怀疑计数器回绕与 -pc 清零,不要先怀疑设备
8.4 官方给出的正确做法:清零后重测,而不是纠结累积值
How — 课程这段是本篇最实用的一段操作指导
课程给出的完整逻辑链是:显示的端口计数器值是自上次计数器被重置以来累积的值;为了判断所显示的值是否与你正在调查的问题相关,建议重置端口计数器;让流量运行一段时间,然后观察端口计数器的新值。
官方对应的选项与它的准确边界:
# clear all fabric standard + extended port counters
ibdiagnet -pc
必须先确认的一条:-pc 影响的是整个 fabric,不只是本机
这一点课程没有强调,但它是本篇唯一一处会真正影响他人的操作。官方措辞是 "Resets all fabric IB spec compliant port counters"——all fabric。
实践含义有三条:
- 它需要设备侧配合执行重置,是有写入副作用的操作——这与本系列其它工具的只读性质不同,在生产环境执行前应先确认执行窗口
- 它会破坏他人的历史数据——如果别人的监控正在采集这些计数器做趋势,你的清零会让对方看到一次假的"归零事件"
- 它与 --pm_pause_time 是配合关系,不是替代关系——清零解决"历史值干扰",时间窗口解决"新值太小看不见",正确做法是两者都用
因此本篇给出一个明确推荐流程(第十四节会再展开):先 -pc 清零 → 让业务跑够时间 → 再 --pm_pause_time N 采样。
8.5 一个必须单独讲的计数器:vl15_dropped
Why — 为什么这个计数器在"业务零丢包"的 fabric 上也可能是非零
在官方 PM Counter 名称表里,vl15_dropped 与业务量计数器并列,但它统计的不是数据流量。它的位置是 VL 15——而本系列第八篇已经确立:SMP 报文固定走 VL 15。
这意味着:vl15_dropped 统计的是管理流量被丢弃的数量,不是业务包被丢弃的数量。出现非零值时,正确的第一反应是"子网管理面有压力或有问题",而不是"业务在丢包"。
它为什么值得单独讲,还有一个原因:它是 SMP 拥塞的直接指标,而 SMP 拥塞会直接影响本系列第八、九篇讲的那整套机制——管理流量排不出去,LID 分配就慢,Trap 就送不到,最终表现为"子网变化后收敛很慢"。看到 vl15_dropped 持续增长,应当去查子网规模与管理面配置,而不是去查业务链路。
把官方那份 PM Counter 名称表按量纲重新分类,会发现它不是一张扁平的列表,而是四种性质完全不同的东西混在一起。这是初学者读 ibdiagnet2.pm 最容易出错的地方,也是本篇最想传达的判读方法。
第一类是流量型:port_xmit_data、port_rcv_pkts、port_xmit_cells。它们的判据是"涨不涨"——链路在跑业务就必然增长。它们本身不指示任何问题,唯一的用途是确认这条端口确实有流量。反过来,如果一个业务端口上这类计数器长期不涨,那才是问题:可能是转发表算错导致流量绕路,也可能链路是 Active 但业务没真正走它。
第二类是错误型:symbol_error_counter、link_down_counter、link_error_recovery_counter、port_rcv_errors。它们的判据是"增不增"——正常链路上应长期不增长。它们的绝对值不重要,增长速率才重要,这正是 8.1 节取差值的原因。
第三类是拥塞型:port_xmit_wait。它的判据与前两类都不同——它高不代表链路坏,也不代表链路空。它是一个负载指标,必须结合同一端口的流量型计数器一起看:流量大 + port_xmit_wait 高 = 这条链路接近满载,需要扩容;流量小 + port_xmit_wait 高 = 另有原因,要去查对端的接收缓冲与信用。这个组合判断是本节最实用的一条。
第四类是管理型:vl15_dropped。它与业务无关,判据是"VL 15 有没有丢",指向的是子网管理面。把它和前三类混在一起看,是本篇明确要避免的错误做法。
把四类的判据并排放,判读顺序就有了唯一解:先用流量型确认"这条端口该有流量吗";再用错误型确认"它有没有在错";如果两者都正常但体感有慢,用拥塞型解释;如果流量型显示流量在涨而 vl15_dropped 也在涨,那是管理面问题,不是业务链路问题。这个顺序不是本篇发明的,它是第二节那句"状态正常不等于链路健康"的展开——只不过这里把"链路健康"拆成了四个可分别测量的维度。
本节关键记忆:8 类计数器 + 1 个时间窗口 + 1 个四量纲判读法
- 4 类默认采集:PortCounters / PortCountersExtended / PortRcvErrorDetails / PortXmitDiscardDetails;--pm_get_all 一次取全
- 1 个时间窗口:--pm_pause_time 默认 1 秒,多数故障场景下不够;设 0 则只采一次、仍是累积值;窗口长度要按你实测的错误速率来定,本篇不给具体秒数
- 1 个推荐流程:-pc 清零 → 跑业务 → --pm_pause_time N 采样;-pc 影响全 fabric,需执行窗口
- 1 个换算提醒:十六进制显示(0xB19 = 2849);32 位计数器上限约 42.9 亿,会回绕,长周期趋势必须识别回绕
- 1 个四量纲判读法:流量型看"涨不涨" / 错误型看"增不增" / 拥塞型看"结合流量" / 管理型 vl15_dropped 看管理面、与业务无关
九、Speed/Width Check 与 Nodes Information:降级链路与固件不齐
What — 这两个阶段检查的是完全不同的两类问题
把它们放在一起讲,因为它们在本系列的语境下是同一个因果链的两端:
- Speed/Width Check 检查的是物理层协商出来的结果是否符合预期——这一端的成因是硬件与配置
- Nodes Information Check 检查的是全网固件版本是否统一——这一端的成因是运维
但两者的严重程度差了一个量级:降级链路只是慢,固件不统一可能引入难以预测的行为差异。课程对此的判读是准确的:Speed/Width 阶段报告发现有多少链路速率与宽度不符;Nodes Information 阶段用于验证所有被发现的设备是否运行最新固件版本,示例输出显示固件检查以告警结束,因为部分设备装的不是最新版本。
9.1 Speed/Width Check:两个选项与两类错误样例
How — 怎么用、报什么错
官方手册第 4.7 节把这项检查拆成速率与宽度两个独立校验,关键结论是:不符合预期的端口会被记录在 ibdiagnet.log 文件里(Ports with degraded speed or width are reported in ibdiagnet.log file)。这一句再次印证了第五节的结论:屏幕不是完整的。
两个选项的取值范围(新版已扩展,这是课程时代与现在的一个实际差异):
| 选项 | 可选值 | 0 的含义 |
|---|---|---|
| --ls <0|2.5|5|10|14|25|50|100|200|FDR10> | SDR / DDR / QDR / FDR / EDR / HDR / NDR / FDR10 各代速率 | 0 = 禁用期望速率检查 |
| --lw <0|1x|2x|4x|8x|12x> | 各代宽度 | 0 = 禁用期望宽度检查 |
官方给出的两组错误样例非常具体,这两条是本篇引用官方输出最完整的地方:
-E- Speed Error: 1: node r-ufm112, port 1, Speed mask (Expected 0x2E,
Actual 0x1) - 1
-W- Width Error: 1: node switch-004, port 12, Width mask (Expected 0x0,
Actual 0x1) - 1
这两组样例的价值在于它们展示了官方错误消息的三个固定要素:链接描述符、期望值、实际值。你在自己的环境里看到任何一条同类告警,都可以按这三要素照抄格式去写工单。
降级链路的排查方向:先看两端,再看中间
从上面的样例能推出一个实用的判断顺序。链路速率与宽度是两个端口协商出来的结果,任一端能力不足都会导致降级,而本系列第八篇讲过:端口的 Speed 与 Width 是 SM 配置给它的四个参数之一,且受链路上最慢设备约束。
因此排查顺序是:先确认两端端口各自支持什么(交换机端口配置 + HCA 端口配置),再确认中间是不是线缆或模块的问题(第八篇提到的 Split Cables 就是这一类,官方功能表里"Split Cables Support"就是为报告分裂线缆存在的)。如果两端都支持目标速率而实际协商结果仍偏低,那嫌疑就集中在线缆与光模块上——此时可以用 --get_cable_info 取线缆信息(但要注意该插件官方已标注为废弃,见 FAQ Q20)。
9.2 Nodes Information:它比较的是"同型号在本网内的最高版本",不是"NVIDIA 官网最新版"
What — 课程那段读法中的一处需要收紧
课程说"Nodes Information 阶段用于验证是否所有被发现的设备都运行着最新固件版本"。这句话的方向对,但"最新"的定义必须精确化,否则会得出"这台交换机固件旧了"的错误结论。
看官方输出样例,判据写在告警文本里,说得非常明确:
-W- Firmware version check: 1: node switch-004, devid 4115(0x1013),
PSID MT_2190110032, current ver 12.26.4012, latest ver 12.26.4000
-W- Firmware version check: 2: node H-10, devid 4103(0x1007),
PSID MT_0000000008, current ver 16.18.160, latest ver 9.3.1700
把这三要素与本系列第十四篇对照,会发现它们是同一组标识符的不同用法:
- Devid 与括号里的十六进制,就是 ib-14 中 vendor_part_id 的十进制与十六进制两种写法
- PSID 是 ib-14 讲的那个 16 个 ASCII 字符的参数集标识
- 判据的参照系是"同一 Devid + 同一 PSID 在本 fabric 内的最高版本"
这个判据的实践后果:-W- 不等于"该升级了",-E- 才是
看上例的告警:r-ufm118/U1 跑的是 12.27.6008,而参照版本是 12.100.5600。按十进制分段比是 27 > 100?不对——按段比是 12.27 与 12.100,第 2 段 100 > 27,所以这台的版本确实低于参照版本。但如果某台的版本是 12.200.x,它会被判为"最新",反过来成为参照系。
由此得出本篇明确推荐的做法:
- -W-(版本低于本网内同型号最高版本) → 这是一个一致性提示,不是缺陷判定。是否要统一,取决于你的运维策略:统一版本有利于排障与行为一致性,分版本有时是必要的灰度策略。课程对此的措辞是准确的——"管理员现在可以考虑是否为稳定性与一致性升级这些设备的固件",用了 may consider,而不是 must
- -E-(The firmware of this device returned invalid general info data) → 这才是真问题:设备固件返回的通用信息数据无效,意味着它连自己的身份信息都报不出来。此时该设备的所有身份类信息都不可信,应当按 ib-14 的固件排查流程处理
顺带把课程提到的一行补全:以 -W- 开头的行是告警,其它以 -I- 开头的行是信息——见 5.1 节。但要注意上例中阶段末尾的 -E- FW Check finished with errors 是错误,它与具体的 -W- 告警行是两回事:告警是内容,阶段结论是判定。
本节关键记忆:2 个阶段 + 2 个选项 + 1 个判据参照系
- Speed/Width Check:--ls / --lw,0 = 禁用该检查;降级端口记录在 ibdiagnet.log;错误消息三要素 = 链接描述符 + 期望值 + 实际值
- 降级排查顺序:两端端口能力 → 中间线缆 / 光模块(Split Cable 是其中一类)
- Nodes Information 的判据参照系是"本 fabric 内同 Devid + 同 PSID 的最高版本",不是 NVIDIA 官网最新版
- -W- 版本低 = 一致性提示(是否统一取决于运维策略);-E- 通用信息数据无效 = 真问题,身份信息不可信
- 1 个跨篇印证:Devid:4115(0x1013) 中的十六进制,就是 ib-14 的 vendor_part_id 十六进制写法;PSID 概念相同
十、Summary 汇总表:读出"哪个阶段出了问题"而不是"有问题"
What — 汇总表是唯一应该作为"是否通过"判据的那一行
课程对这一阶段的描述是:最后一个阶段是汇总,显示前序每个阶段识别出的告警数与错误数。
公开文档中记录的汇总表实际形态如下(注意它的列顺序是 Warnings 在前、Errors 在后):
Warnings Errors
Discovery 0 0
LIDs Check 0 0
Links Check 0 0
SM Check 0 0
Port Counters 0 0
Nodes Information 3 2
Speed / Width checks 0 6
... Keys 0 0
How — 怎么读这张表:三个必须注意的点
第一,列顺序容易看反。表头是 Warnings Errors,所以上例中 Speed / Width checks 0 6 意味着 0 个告警、6 个错误——不是 0 个错误。这个表在旧版本文档里出现过列名与数据错位的历史记录,所以引用时务必连表头一起贴出来,不要只贴数据行。
第二,最后两行的 ... 表示版本差异。公开文档记录的那次输出里,... Keys 这一行前面是省略号而不是具体阶段名。这说明不同版本默认执行的阶段集合不同——回到 5.1 节的 12 项清单,你要核对自己这一版的阶段集,而不是照抄别人的输出。
第三,汇总表回答的是"哪个阶段",不是"怎么修"。它给你的是一个定位索引:Speed / Width checks 有 6 个错误,说明问题集中在降级链路上;Nodes Information 有 3 个错误,说明是固件信息问题;Port Counters 有 2 个告警,则需要看日志里那两条具体是什么。把汇总表当成诊断结论是误用;它是诊断的索引。
10.1 从汇总表到结论:三条可执行的分支
汇总表真正的价值不在于"它列出了每个阶段的数字",而在于它把一次巡检的结果按成因分成了三类,而这三类需要的后续动作完全不同。把这条分流路径走通,一次全网巡检的产出就能直接变成工单。
分支一:硬件类 — 体现在 Speed / Width checks 与 Port Counters 的错误型计数器上。这一类的共同特征是成因在物理层,且定位信息极其充分——因为错误消息本身就带完整的链接描述符(两端 GUID + 端口号)。处理动作是直接派单去查那一对端口,中间不需要任何判断。第七节的 Links Check 发现 Init 状态链路也属于这一类,但它的定位信息弱一些(只知道"这条链路",不知道"为什么"),需要补一次 ibstat 看物理状态。
分支二:配置与软件类 — 体现在 Lids Check、Subnet Manager、Speed/Width 之外的各种检查上。这一类的特征是定位信息不足,必须补一次人工判断。典型如 Subnet Manager 报出多个 Master:汇总表只告诉你"这个阶段有 1 个错误",但"哪两个 SM 冲突"要打开 ibdiagnet2.sm 这个 dump 文件才看得到(第十一节)。处理动作是先看 dump 文件定位到具体设备,再决定是手工干预还是让 SM 自行收敛。
分支三:一致性类 — 体现在 Nodes Information 的 -W- 告警与 Duplicate Node Description Detection。这一类的特征是它几乎不会导致业务故障,它的危害是让未来的排障变慢、让未来的行为不可预测。处理动作不是"修复",而是"决定"——是统一版本,还是接受现状并记录在案。这类问题的正确处理方式往往是写一份文档,而不是派一张工单。
三条分支的分野,本质上是第二节那张问题表在实际数据上的展开:线缆 / 端口(硬件类)、配置 / 路由(配置类)、软件版本与描述(一致性类)。而第五类"链路超额订阅"没有出现在汇总表的典型阶段里——因为它不是错误,是负载状态,需要通过 -P 阈值主动设定才会在屏幕上显现(第八节)。这是"默认诊断看不见的那一类问题",也是本篇推荐把 -P 加进周期巡检的根本原因。
最后补一条纪律:这三条分支的判定依据必须来自日志文件,不是屏幕。第五节已经说明 --screen_num_errs 会截断屏幕输出。正确顺序是:先看 Summary 定位阶段 → 再去 ibdiagnet2.log 里读该阶段的具体条目 → 最后按需要打开对应的 dump 文件。这个三步顺序在第十四节会固化为运维流程。
本节关键记忆:1 张表 + 3 个读表要点 + 3 条处理分支
- 1 张表:列顺序 = Warnings 在前、Errors 在后;引用时必须连表头一起贴
- 3 个读表要点:列顺序易看反 / 末行 ... 表示版本差异,阶段集要按自己这版核对 / 汇总表给的是索引不是方案
- 3 条处理分支:硬件类(定位充分,直接派单)/ 配置类(定位不足,先看 dump 文件)/ 一致性类(不修,做决定并记录)
- 1 个盲区:"链路超额订阅"不在默认诊断里,必须用 -P 设阈值才会显现
- 1 个正确顺序:Summary 定位阶段 → ibdiagnet2.log 读具体条目 → dump 文件深挖
十一、Dump 文件全景:旧版 13 个与新版 30 个文件分别能回答什么
What — 先把"文件名带不带 2"这件事彻底说清
第一节误听表已经指出:dump 文件名与默认输出目录都随版本变化。现在把两个版本的清单并排放,差异一目了然:
| 对照项 | 旧版(ibdiagnet(1) man page) | 新版(NVIDIA 文档站 v2.24.0) |
|---|---|---|
| 默认输出目录 | /tmp | /var/tmp/ibdiagnet2/ |
| 文件名前缀 | ibdiagnet.(无数字) | ibdiagnet2.(带 2) |
| 文件数量 | 13 个 | 30 项 |
| 差异原因 | 工具名从 ibdiag 演进为 ibdiagnet、dump 前缀随之从 ibdiagnet 改为 ibdiagnet2;官方 Changes and New Features History 中记录了多个版本新增文件 | |
因此本篇全篇采用新版写法 ibdiagnet2.*,你在旧环境上要把前缀的 2 去掉
这不是风格问题,是可复现性问题。写进工单、脚本、文档里的文件名必须与你环境里实际生成的一致。确认方法有两个:ibdiagnet --version 之后看实际版本号;或者直接 ls 一下输出目录。不要靠记忆。
11.1 五个"必看"文件:课程点名的那些,以及它们能回答的问题
How — 按"回答什么问题"组织,而不是按字母顺序
课程点名了五个 notable 文件。它们的官方描述与实际用途如下:
| 文件(新版名) | 官方描述 | 能回答什么问题 |
|---|---|---|
| ibdiagnet2.lst | Fabric links in LST format (旧版:所有节点、端口与链路的列表) |
"这个 fabric 现在到底长什么样?" ——节点、端口、链路的完整清单,是所有其它分析的基础 |
| ibdiagnet2.fdbs | Unicast FDBs 默认禁用,需 --enable_output fdbs |
"某个目的 LID 的包会被转发到哪些出口?" ——交换机单播转发表的完整内容,排查绕路与黑洞的第一手材料 |
| ibdiagnet2.sm | Subnet Managers | "全网有几个 SM、各自什么状态与优先级?" ——对应第七节的"恰好一个 Master"判断 |
| ibdiagnet2.pm | IB spec compliant Ports Counters | "这条链路上次重置以来累计发生过什么?" ——规范级端口计数器值(十六进制显示,见 8.3) |
| ibdiagnet2.pkey | Pkey tables | "分区是怎么划的、哪些主机口属于哪个分区?" ——对应本系列第七篇的 P_Key 分区机制 |
这五个文件的选择逻辑很清晰:.lst 是"有什么"、.fdbs 是"怎么转"、.sm 是"谁在管"、.pm 是"发生过什么"、.pkey 是"怎么隔离"。五个维度覆盖了一次 Fabric 诊断的全部核心问题域。
Tip — ibdiagnet2.fdbs 默认是禁用的,必须显式打开
官方 Dump Files 页面对 fdbs 与 ar 两个文件都标注了 "Dump disabled by default",并在页脚统一注明:默认禁用的 dump,需要用 --enable_output 打开。
这是个很容易踩的坑:你跑了 ibdiagnet -r,以为会拿到转发表,结果发现目录里没有 .fdbs 文件。原因是路由校验执行了,但转发表 dump 默认不产出。正确的命令是显式指定输出类型:
# -r alone does NOT produce the .fdbs file
ibdiagnet -r
# ask for the forwarding-table dump explicitly
ibdiagnet -r --enable_output fdbs
所以要拿到转发表,正确写法是 ibdiagnet -r --enable_output fdbs。而 --disable_output all 是一个很有用的加速手段——全部输出关闭,只保留屏幕与日志,跑得快得多。
11.2 新版 30 项清单:按"回答什么问题"重新分组
What — 官方 Dump Files 页面 30 项的完整清单与本篇判读
官方文档站给出的 30 项文件清单,如果按字母顺序读是看不出用途的。按问题域重新分组之后会发现,它们对应的是本系列前面各篇讲过的机制:
| 问题域 | 文件 | 对应本系列哪一篇 |
|---|---|---|
| 拓扑与连接 | .lst | 第八、九、十篇 (拓扑发现 / 重收敛 / Fabric 拓扑) |
| .ibnetdiscover —— 以 ibnetdiscover 格式呈现的已发现网络 | ||
| .iblinkinfo —— 以 iblinkinfo 格式呈现 | ||
| .net_dump / .net_dump_agg —— 含分裂线缆映射与 FEC 信息 | ||
| 转发与路由 | .fdbs / .mcfdbs | 第八篇 LFT / MFT |
| .vl2vl / .slvl | 第八、九篇 SL-to-VL 映射 | |
| .plft | 第十一篇路由引擎(可编程 LFT) | |
| 自适应路由与 SHIELD | .ar (默认禁用) / .far / .far_flid | 第十一篇:ar_updn 引擎与 SHIELD |
| .rn —— SHIELD 配置表 | ||
| .rnc (旧文件,默认禁用) / .rnc2 —— SHIELD / SHIELDv2 / HBF 计数器 | ||
| .aports —— APorts dump | ||
| 计数器 | .pm / .pm_agg | 第八节 |
| .mlnx_cntrs —— NVIDIA 诊断计数器 | 需 --sc | |
| .net_dump_ext —— 含 FEC、BER 与额外 phy 数据 | 第十二节 | |
| 管理面 | .sm —— 子网管理器 | 第九篇 |
| .pkey —— 分区表 | 第七篇 | |
| .aguid —— 别名 GUID(仅 ConnectX-3) | FAQ Q14 | |
| 虚拟化 | .vports | 本篇不展开 |
| .vport_pkeys —— 虚拟化分区表 | ||
| SHARP | .sharp | 本篇不展开 |
| .sharp_pm | ||
| 物理层 | .cables —— 线缆信息 | 第十二节 |
| .flid —— FLIDs 配置详情 | 第十一篇 SHIELD 前提 | |
| 设备信息与主档 | .db_csv —— ibdiagnet 内部数据库 | 第十三节的加速基础 |
| .nodes_info —— 节点信息(固件版本等) | 第九节 | |
| .log —— 日志文件 | 第五、十节 | |
| 拓扑验证 | .rails —— "rails optimized" 验证详情 | 第十二节 |
| .guid —— Scope Builder 创建的 scope 文件 | 第十三节 | |
| .ppcc —— 端口可编程拥塞控制文件 | 本篇不展开 |
把 30 项按这个方式分组之后,一个此前不明显的事实浮现出来:ibdiagnet 的 dump 文件集合,本质上是本系列前 14 篇所讲机制的一份"可导出快照"。.fdbs 是第八篇 LFT 的快照,.ar / .far 是第十一篇路由引擎的快照,.sm 是第九篇选举机制的快照,.pkey 是第七篇分区机制的快照。
11.3 db_csv:唯一值得单独强调的文件
Why — 为什么它被称为"主档"
官方对 ibdiagnet2.db_csv 的描述只有一句:"ibdiagnet internal database"。但从功能表第 16 项 Fast Discovery(避免通过使用先前缓存的 fabric 数据来重新发现 fabric)与旧版 man page 对应文件 ibdiagnet.db 的描述——"内部子网数据库的转储;此文件可在后续运行中用 -load_db 选项加载"——可以看出它的特殊地位:
它是唯一一个"能被 ibdiagnet 自己读回去"的文件。其它所有 dump 都是给人看的输出,只有它同时是输入。这意味着它把"发现"这一步的结果固化成了可复用的资产,而发现恰恰是全流程中最慢的一步。
它的内容组织方式也值得注意:它不只是计数器值,还按"段"组织。官方提到 --per_slvl_cntrs 采集的 per-SL/VL 计数器报告在 ibdiagnet2.db_csv 文件里;--pm_pause_time 的两次采样差值写入 db_csv 的 PM_DELTA 段;--extended_speeds 的计数器报在 db_csv 的 PM_INFO 段;--aguid 的数据也 dump 到 db_csv。
官方 --enable_output 的说明里还有一句关键提示:csv 段的示例可以在 .db_csv 文件里看到(Examples of csv sections see in '.db_csv' file)。换句话说,要搞清 --enable_output csv:xxx 里能填哪些段名,方法就是打开 db_csv 看它有哪些段。这是一个自描述的设计。
因此本篇给出的运维建议是:db_csv 应当作为"巡检归档"的第一件物品保留下来,因为它既是这一次的完整取证材料,又是下一次加速诊断的输入。第十三节会讲具体怎么用。
把前面十一节的内容合起来看,会发现 ibdiagnet 的输出设计有一条明确的思路:它把"发现"与"判定"这两件事的产出物分开保存,并通过 db_csv 让前者可以复用。理解这条设计意图,第十四节的运维流程就不需要额外论证了。
第一层是发现层的产物,它描述"客观现状"。.lst 记录有哪些节点与链路,.db_csv 记录全部采集到的原始属性。这一层的信息有一个共同特点:它不依赖任何阈值、不依赖任何期望值。链路跑 25G 还是 50G、固件是 12.26 还是 12.100,.lst 与 .db_csv 都照实记录,不做任何评判。
第二层是配置层的产物,它描述"协议层配置了什么"。.fdbs、.mcfdbs、.slvl、.pkey、.ar / .far 属于这一类。这一层的信息特点是把现状翻译成了协议语义——不只是"这条链路通着",而是"这个 LID 的包会被送到这三个出口"。排查绕路、信用环、分区隔离失效,都必须落到这一层。
第三层是判定层的产物,它描述"工具认为有没有问题"。屏幕输出、.log、Summary 表属于这一类。这一层的信息依赖参数——--ls 50 才会产生"速率不符"的错误,不给这个参数就没有这条判定。所以判定层的结论必须与"当时用的什么参数"绑定保存,否则无法复现。
这三层的设计有一个很实用的推论:第一层和第二层的文件,是可以长期沉淀为基线的;第三层的结论必须每次重新生成。原因很直接——客观现状会变,但"什么是合格的"这个判断标准可能不变。把这两类东西分开管理,是把 ibdiagnet 用好之后最明显的效率提升点。
还有一点值得单独说:这正是本系列第十三篇讲的三种 SM 运行形态在运维层面的一个投影。交换机内嵌 SM 时,dump 文件得逐台交换机去取;OpenSM 部署在服务器上时,在那台服务器上跑一次就能覆盖全网;UFM 平台上则由平台统一调度。工具的输出设计与 SM 的部署形态无关,但"到哪里去跑"这个问题由部署形态决定——这一点在第十四节会具体展开。
本节关键记忆:2 套命名 + 5 个必看文件 + 30 项分组 + 1 个主档文件
- 2 套命名:旧版 /tmp + ibdiagnet.*(13 个)/ 新版 /var/tmp/ibdiagnet2/ + ibdiagnet2.*(30 项);写文档要用你环境里实际的名字
- 5 个必看文件:.lst 有什么 / .fdbs 怎么转 / .sm 谁在管 / .pm 发生过什么 / .pkey 怎么隔离
- 1 个默认禁用的坑:.fdbs 与 .ar 默认不产出,必须 --enable_output fdbs
- 1 个主档文件:.db_csv —— 唯一能被工具自己读回的文件,既是取证材料又是下次加速的输入;它还自描述了所有 csv 段名
- 1 个三层划分:发现层(可沉淀基线)/ 配置层(可沉淀基线)/ 判定层(每次重生成,必须与参数绑定保存)
十二、进阶用法一:阈值告警、路由校验、BER 与拓扑基线比对
What — 课程点名的两个进阶特性,以及官方补齐的三个
课程在最后点出 ibdiagnet 的一个"非常有用的特性":它能生成一个描述 fabric 的拓扑文件,格式称为 IBNL(InfiniBand Network List),用 -w 选项加上文件位置与名称;运行时就会生成该名称的拓扑文件;打开文件可以看到内容,拓扑通过列出每个被发现的设备及其连接来描述。
课程给这段特性配了一句本篇认为极重要的评语:拥有这些文件非常重要,因为你可以在稳定状态下记录拓扑,并在排障失败时把它当作基线使用;如果你怀疑拓扑故障,可以生成当前的拓扑文件,然后与你的基线拓扑做比较。第十二节与本节分别讲这两件事。
官方功能表里与"主动发现"相关的另外三项,本节一并覆盖:Error Counters Check(-P)、Routing Fetch and Checks(-r)、BER Test(--ber_test)。
12.1 -P:把"超额订阅"这一类问题变成可见的告警
How — 阈值告警的语法与它填上的那个盲区
第十节已经指出:"链路超额订阅"不在默认诊断里。-P 就是把它变成可见的那一条路。官方定义:
# print every non-zero counter (-P all, 0 is the default)
ibdiagnet -P all
# print only counters above a threshold you measured yourself
ibdiagnet -P 100
用好 -P 的关键在于阈值怎么定。本篇不给具体数字,因为阈值必须来自你自己链路的实测错误速率(8.4 节的方法)。但可以给出定阈值的三条原则:
- 错误型计数器(symbol_error_counter、link_down_counter 等):阈值应设成"任何非零都值得知道"——这些计数器正常链路上应当长期不增长,=1 就是合适的起点
- 拥塞型计数器(port_xmit_wait):阈值必须结合流量型计数器定,不能单独设——见 8.4 节的组合判断
- 管理型计数器(vl15_dropped):阈值应结合子网规模定——因为它反映的是管理面压力,而管理面压力随节点数与拓扑变化速率变化
官方还提供了一个相关选项,第九节提过但没展开:--pm_per_lane —— 在设备支持时按 lane 列出所有计数器,应与 --extended_speeds 组合使用。它的诊断价值在于:一条 4 宽链路上只有 1 个 lane 出错,与 4 个 lane 都在出错,是两个完全不同的问题——前者更像单模块或单通道的偶发问题,后者指向链路整体劣化。
12.2 -r:转发表正确性与信用环,这是本系列第十篇结论的验证工具
What — 官方定义的六项检查内容
官方对 -r / --routing 的定义是:ibdiagnet 执行单播(静态与自适应)与组播路由校验,并计算、报告以下内容:
- 处于各跳数距离上的 CA 对数量
- 考虑所有 CA-to-CA 路径时,经过每个交换机出端口的实际路径数
- 考虑所有 CA-to-CA 路径时,经过每个交换机出端口的实际目的 LID 数
- 扫描组播路由表以检查环与连通性
- 应用信用环检测算法
- 应用自适应路由配置校验——若使用 -smdb,则把 AR 的 LFT 与 up-down min-hop 表做对照检查
官方给出的实际输出样例非常完整,其中两处注释是本篇最想强调的内容:
###################################
-I- Routing Check
###################################
-I- Fetching Routing Tables
###################################
###################################
-I- Credit Loops Report:
###################################
-I- Analyzing Fabric for Credit Loops 1 SLs, 1 VLs used.
-I- no credit loops found
-I- Routing Check, 186 unicast paths
###################################
-I- Multicast Groups Check
###################################
-I- Scanning all multicast groups for loops and connectivity...
-I- Multicast Group:0xC000 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC001 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC002 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC003 has:7 switches and:8 FullMember ports
-I- Multicast Group:0xC004 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC005 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC006 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC007 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC008 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC009 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00A has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00B has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00C has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00D has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00E has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC00F has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC010 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC011 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC012 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC013 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC014 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC015 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC016 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC017 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC018 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC019 has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC01A has:7 switches and:9 FullMember ports
-I- Multicast Group:0xC01B has:7 switches and:9 FullMember ports
###################################
# Fabric Qualities Report
###################################
-I- 7 Devices, 1 Active Port per device
-I- 210 CA to CA paths, 186 unicast paths
-I- Histogram of the number of paths per port
0 21
1 7
2 9
-I- If the routing is correct, the histograms of all the ports
in the same tree level should be narrow (concentrated)
Why — 那句注释是整段输出里最有价值的一句话
请注意第二段直方图后面的这句注释:"如果 fabric 路由正确,同一树层级的所有端口的直方图应该是集中的(narrow)"。
这句话把一个抽象的正确性标准变成了可测量的形态:看直方图的"宽度",不看具体数值。具体含义是:
- 同层级端口的"承载路径数"应当接近——如果某层里一个端口过 100 条路径、另一个只过 5 条,说明流量分布严重偏斜,即使所有路径都是通的、也没有信用环,这条 fabric 的路由质量仍然是差的(拥塞会集中在少数链路上)
- 直方图里出现大量 0(样例中 0 21 表示 21 个端口不走任何 CA-to-CA 路径)——这不一定是问题。官方注释说明了原因:驱动 CA 的端口被刻意排除了(Ports driving CAs are ignored),因为它们的取值必然等于 Nca - 1。所以那些 0 主要是"这些端口不属于这里该统计的范围"
这个判据与本系列第十篇《拓扑与路由引擎:Fabric 拓扑、路由引擎、自适应路由与信用环》的结论是严丝合缝的:那一篇讲"信用环为什么会导致死锁",本节的 Credit Loops Report 就是检测它是否已经存在的工具。样例输出中 -I- no credit loops found 这一行,含义是沿 186 条单播路径追踪,没有发现信用环。
第三段组播检查同样值得注意:它逐个组播组报告"有几个交换机、有几个 FullMember 端口"。FullMember 这个词是协议术语,指完整成员端口——与 FullMember 相对的另一种成员类型在协议里另有定义,不要把两者混为一谈。样例中 0xC003 has:7 switches and:8 FullMember ports 与其它组相比少一个成员,这类差异就是组播路径不完整的线索。
关于 -r 的一个必须知道的成本
官方在 --vlr 选项的说明里给出了一句关键的成本提示:"由于路径数量是 N 的平方,提取 PSL 文件可能需要一些时间"(Since number of paths is N^2 extracting the PSL file may take some time)。
这个 N2 就是 CA-to-CA 路径数的来源——CA 数为 N 时,CA 到 CA 的路径组合是 N × (N-1) 个。样例中"Scanned:210 CA to CA paths"对应的 CA 数约在 15 上下(15 × 14 = 210,与样例的 55 nodes 中"54 Switches & 1 CA-s"不是同一次运行,可以对照看不同规模下的行为)。
推论:在节点数上千的大 fabric 上,-r 会很慢,而且它产生的数据量与 N2 成正比。所以本篇的建议是:全网规模的周期巡检不必每次都带 -r;把它留给"怀疑路由有问题时"以及"fabric 有重大变更之后"。日常巡检用 -P + 计数器 + Summary 就够。
12.3 BER 与 FEC:从"链路是 Active"走向"链路是健康的"
What — BER 的官方定义与两代工具的分工
官方手册对 BER 的定义是:比特误码率是单位时间内的比特错误数除以研究时间间隔内传输的总比特数;BER 是一个无量纲的性能度量(the number of bit errors per unit time divided by the total number of transferred bits during a studied time interval. BER is a unitless performance measure)。
关于用什么工具,官方有一条随代次变化的分工,务必按自己的设备代次选:
| 选项 | 适用设备 | 关键语义 |
|---|---|---|
| --ber_test | 仅 SwitchX / ConnectX-4 / ConnectX-3 官方已标注 Deprecated |
为每个端口提供 BER 测试,计算每个端口的 BER 并检查是否有 BER 值超过阈值。默认阈值 = 10^-12 |
| --ber_thresh | 同上 | 阈值要填 BER 的倒数。官方示例:10^-12 需填 1000000000000 或 0xe8d4a51000(1012)。若填 0,则报告所有端口的所有 BER 值 |
| --llr_active_cell <0|64|128> | 同上 | fabric 中启用 LLR 时指定 LLR 活跃 cell 尺寸(0 = 不指定) |
| --get_phy_info | 更新的设备(官方指定的替代方案) | 官方原文:"对于后续设备,使用 --get_phy_info 进行 BER 校验" |
--ber_thresh 那个"填倒数"的要求是本篇明确要提醒的操作细节:你要表达 BER ≤ 10-12,填进去的数是 1000000000000,而不是 0.000000000001。这个设计的用意是让阈值参数本身是整数——避免浮点数的表示误差导致边界判定不确定。
官方给出的错误样例揭示了 FEC 模式(FEC mode)会进入判定,这一点很重要:
-E- BER Test, 1: node r-ufm112 port 1, ber_thresh 1.000000e-12,
FEC mode (16, 133), actual ber 1.234568e-11
把这一节与第二节表里"线缆故障"那一行连起来:这是本篇唯一一类"链路完全 Active、所有状态判读都正常、但链路已经不健康"的故障。原因是前向纠错(FEC)机制在起作用——当误码率较低时,FEC 能在链路层把错误纠正掉,上层完全感知不到,状态机自然不会报任何东西。只有直接测 BER 或 PHY 数据才能发现它。官方功能表里 .net_dump_ext 的描述"含 FEC、BER 与额外 phy 数据"正是为此准备的。
这也解释了为什么新版本把 PHY 诊断做成了独立插件(--get_phy_info / --get_ppamp / --show_cap_reg):因为在 FEC 成为主流配置的代次之后,"链路健康"这个问题的答案已经不在状态机里,也不在基础计数器里,而在 PHY 层的数据里。
12.4 拓扑基线:-w 导出、-t 比对
How — 两个选项的官方定义与文件格式
官方对 -w 的定义(手册中它在"Topology Comparison"一节):为发现的拓扑写出一个拓扑文件。而 man page 版本的定义更完整,并且说明了一个容易忽略的副作用:
这个标志在你之后想检查与 fabric 当前状态的变化时会很有用;同时该选项还会创建一个名为 ibdiag_ibnl 的目录,其中保存加载此拓扑所需的 IBNL 文件;要使用这些文件,你需要把名为 IBDM_IBNL_PATH 的环境变量指向那个目录;该目录位于 /tmp 或 -o 提供的输出目录里。
-t / --topo_file 的语义是:指定拓扑文件名;提供的拓扑文件将与发现的拓扑做比对,两者之间的任何不匹配都会在日志文件中被报告。
官方给出的拓扑文件格式示例如下,这个格式值得记住,因为它是人可读且结构对称的:
# 6 Switches, 19 CAs, 55 Ports
# ibdiagnet2.lst - InfiniBand Network List
switch-004 0x0002c903003d5c41 SW 6 ports
r-ufm101 0x0002c903001a1b01 SW 1 ports
H-10 0x0002c903001b2c02 CA 1 ports
H-14 0x0002c903001b2c03 CA 1 ports
把课程那句评语落到可执行层面:"在稳定状态下记录拓扑并作为基线"这个操作,对应的就是定期跑 ibdiagnet -w baseline.lst;"怀疑拓扑故障时生成当前文件并比较",对应的就是 ibdiagnet -t baseline.lst,不匹配项在日志里。
还要注意新旧两版拓扑命令的差异:旧版 man page 用的是 -wt <file-name>(-t 是拓扑文件、-w 是写文件),而新版把它们拆成了独立的 -t / --topo_file 与 -w / --write_topo_file。ib-14 已经确立了一条纪律:选项以 -h 的输出为准,不以记忆为准。本篇全篇采用新版的拆分写法。
Tip — 基线比对的三条实践纪律
- 基线要带时间戳与 fabric 身份信息归档——文件名建议 topo_YYYYMMDD_HHMM.lst,否则几个月后无法判断哪份是"变更前"
- diff 要看连接行,不看设备行——新增一台服务器会让设备行变化但连接行只增不改,而"某条连接消失了"才是真正要关注的
- 基线必须在"业务已稳定、变更已结束"的时刻采集——在变更窗口内采到的基线会把中间态固化成"标准",后续所有比对都会误报
把 -t 拓扑比对放到整篇的框架里看,会发现它代表的是一种诊断哲学的转变,而不只是多了一个选项。
与"标准"比对的问题在于:标准是通用的,通用意味着它无法反映你这张 fabric 的特殊性。第二节那张五类问题表里,每一类故障的严重程度都取决于具体环境——port_xmit_wait 高到什么程度算问题,取决于这条链路平时跑多少流量;固件版本不统一到什么程度算问题,取决于你的运维策略。任何写死的标准都必然在这两端出错:要么太松漏掉真问题,要么太严天天误报。
与"历史"比对的优越性在于:历史里存的是"你这张 fabric 在健康状态下的样子",它天然包含了你所有的特殊性。这不是抽象的优越性,它体现在本篇已经讲过的三处:Discovery 阶段的节点数只有在与上次比才有意义(6.2 节);固件版本检查的参照系是"本网内同型号最高版本"而不是"官网最新版"(9.2 节,官方自己就是这么设计的);拓扑比对检查的是"与你的基线不一致"(12.4 节)。三处的逻辑完全一致。
不过必须把它的代价说清楚,因为这是本篇不想含糊的一点:基线法要求"基线本身是正确的",而这个前提无法自动验证。如果第一次采基线时 fabric 已经有了一个不明显的缺陷——某条链路悄悄降级了、某个节点的描述重复了——那么这个缺陷会被固化成"标准",此后每次比对都报"正常"。
由此得出基线法的正确使用方式,它是三条约束的组合:其一,基线必须在"确认健康"之后采集,不能反过来用"没报错"来证明基线正确;其二,基线要定期重采——fabric 的合理演进本身就会改变基线,一个三年没重采的基线,其比对结果没有参考价值;其三,基线比对结果为"一致"时不能直接下"没问题"的结论——"与上次一致"与"现在健康"是两个不同的命题,前者只排除了"发生了变化"这一类原因。第八节的计数器与第十二节的 BER 检查,测的正是"基线测不到的那部分"。
把这一节与第十节的三条处理分支、第十一节的三层输出划分合起来,本篇的完整方法论就闭合了:客观现状与配置进基线并持续比对,判定结论每次重算且必须记录参数,而两类信息合起来才构成一次完整的诊断。这正是第十四节要固化成运维流程的内容。
本节关键记忆:4 个进阶特性 + 1 个成本提示 + 3 条基线纪律
- -P 阈值告警:填的是"超过就打印"的阈值,all 默认 0 意味着打印所有非零计数器;阈值必须来自实测速率,本篇不给数字
- -r 路由校验:六项检查;判据是直方图"宽度"而非数值(同层级端口路径数应接近);成本是 CA 数的平方,大 fabric 上不宜每次都跑
- BER 校验:--ber_test 仅老设备且已废弃,默认阈值 10^-12;--ber_thresh 填的是倒数;新设备用 --get_phy_info;FEC 会掩盖误码,这是唯一"状态正常但不健康"的故障类型
- 拓扑基线:-w 导出 / -t 比对(不匹配在日志里);新版已拆分为两个独立选项,老版的 -wt 不再是新版的写法;-w 还会生成 ibdiag_ibnl 目录并需设 IBDM_IBNL_PATH
- 3 条基线纪律:带时间戳归档 / 只看连接行的 diff / 只在稳定时刻采集
十三、进阶用法二:加速重复诊断(-f)与按 scope 缩小范围
What — 官方 Fast Discovery 功能的完整形态
官方功能表第 16 项 Fast Discovery 的定义是:通过使用先前缓存的 fabric 数据避免重新发现 fabric。它由两个选项配合实现,而且有明确的前置条件。
先产出一份可用的 db_csv:
# 1) produce a reusable discovery database
ibdiagnet --discovery_only -o /tmp/ibdiag
# 2) later, re-run the judgement stage from that database
ibdiagnet -f /tmp/ibdiag/ibdiagnet2.db_csv
官方对加载侧的要求写得很明确:
ibdiagnet -f /var/tmp/ibdiagnet2/ibdiagnet2.db_csv
这个限制的含义要说透:-f 加速的代价正好落在"最该查的那几项"上
被跳过的三项是:重复 / 零值 GUID 检查、链路状态检查、SM 状态检查。
对照第七节就会发现,这三项恰好是本篇最核心的三个阶段——Links Check 与 Subnet Manager Check 直接在列,GUID 重复检查是 Discovery 阶段的子检查。也就是说,用 -f 跑出来的报告,天然不含"链路状态"与"SM 状态"这两个结论。
因此本篇给出的使用边界非常明确:
- 适合 -f 的场景:大批量重复采集计数器数据——比如每小时采一次 --pm_pause_time 的差值做趋势。这类任务里链路状态与 SM 状态是常量,每次重查没有意义
- 不适合 -f 的场景:排障——排障时恰恰需要那三项检查
- 一条硬纪律:db_csv 必须新鲜——它是"生成那一刻的 fabric 快照"。用它加速时若 fabric 已经变过,得到的是"用旧拓扑查新计数器",结论无效。本篇建议:-f 使用的 db_csv 必须是当天生成的
13.1 scope 与 exclude_scope:只查一部分
How — 语法、文件格式与一个必须知道的副作用
官方对这两个选项的定义:--scope 是文件路径,文件内是一份应留在范围内的 Node-GUID 与端口列表;--exclude_scope 是文件路径,文件内是一份不应应用计数器采集与诊断的 Node-GUID 与端口列表。
文件格式的官方规范是:第一行必须是版本行,格式为 version: - Scope file format version, must be first line of the file. Supported version 1.0;以 # 开头的行是注释。可用的节点行格式有四种:
version: 1.0
# a scope file: node-guid[/port] entries, one per line
0x0002c903003d5c41
0x0002c903001a1b01/1
0x0002c903001b2c02/2
这个副作用的影响比看起来大:用了 scope 就拿不到拓扑快照了
因为 .ibnetdiscover 是"以 ibnetdiscover 格式呈现的已发现网络",它正是 12.4 节拓扑基线的原料。所以一条严格的纪律是:-w 拓扑基线的采集,不加 --scope 与 --exclude_scope。
正确的组合方式是分两次跑:一次全范围跑 -w 采基线;另一次带 scope 跑计数器采集。这样既有完整拓扑基线,又有针对性的计数器数据。
13.2 加速相关的其它官方选项
Tip — 影响运行时长的四个官方参数与两个范围参数
MAD 相关(决定"等多久、回几次"),官方默认值一并列出:
- --mads_timeout:发送与接收 MAD 的超时(毫秒),默认 500
- --mads_retries:MAD 超时的重试次数,默认 2
- --smp_window:最大在途 QP0 MAD 数,默认 8
- --gmp_window:最大在途 QP1 MAD 数,默认 128
- --max_hops:发现过程的最大跳数,默认 64
- --sl:用于 QP1 MAD 的 SL,默认 0
这里有一个必须点明的关键事实:发现是在 QP0 上进行的,--smp_window 默认只有 8——这解释了为什么在大 fabric 上发现阶段慢:它一次只能在途 8 个 QP0 MAD。而 --gmp_window 默认 128 是给 QP1 用的(一般 MAD),两者不是一回事,不要混着调。
另外官方还有两个性能相关选项:--enable_spst(官方已标注 Deprecated,作用是利用交换机的 Switch Port State Table 跳过 down 端口以加快发现,需要交换机支持该表,否则无效果);--aguid(只跑 Alias GUID 阶段)。
把运行时长的调参逻辑说清楚:发现慢就调 --smp_window;有设备不响应导致每次都要等超时就调 --mads_timeout 与 --mads_retries;但这三个参数的调整都要以"不加重管理面负担"为前提——它们直接决定有多少管理流量在 fabric 上,调大它们之前应先确认 VL 15 不拥塞(见 8.5 节的 vl15_dropped)。
本节关键记忆:2 个加速选项 + 1 个功能损失 + 1 个副作用 + 6 个时序参数
- Fast Discovery 两步:--discovery_only -o /tmp 产出 db_csv → -f /tmp/ibdiagnet2.db_csv 加载
- 1 个功能损失(官方明列):-f 会跳过重复/零值 GUID 检查、链路状态检查、SM 状态检查——正好是本篇最核心的三项,所以不适合排障,只适合大批量计数器趋势采集
- 1 条新鲜度纪律:db_csv 是"生成那一刻的快照",应当当天生成
- 1 个必须知道的副作用:用了 --scope / --exclude_scope 就不会生成 .ibnetdiscover——所以采拓扑基线与采计数器要分两次跑
- 6 个时序参数:--mads_timeout 500ms / --mads_retries 2 / --smp_window 8 / --gmp_window 128 / --max_hops 64 / --sl 0;发现慢调 --smp_window,调大前先确认 VL 15 不拥塞
十四、把它接进运维流程:什么该周期做、什么该按需做
Why — 前十三节讲的都是"这个工具能做什么",这一节回答"我什么时候该用它"
把前面十三节的内容按"触发时机"重新组织一次,会得到一份可直接落地的运维规程。本节的划分依据是各功能项的三个属性:运行成本、对管理面的影响、以及结论是否会随时间自然变化。
14.1 三档执行频次
How — 按成本与收益分三档
第一档:周期执行(建议纳入例行巡检)——成本低、无写入副作用、结论只反映"此刻":
# periodic inspection: read-only, no side effects
ibdiagnet
ibdiagnet --enable_switch_dup_guid
ibdiagnet --extended_speeds
ibdiagnet -o /var/tmp/ibdiagnet2/
第二档:按需执行(故障处理中、重大变更后)——成本较高或需要额外条件:
| 场景 | 追加的命令 | 为什么这类场景才需要 |
|---|---|---|
| 怀疑路由 / 绕路 / 信用环 | -r + --smdb(有 SMDB 时) |
成本是 CA 数的平方;且 --smdb 的 AR 校验需要 SM 侧的路由引擎与 rank 数据,这来自本系列第十一篇讲的 OpenSM 路由引擎 |
| 怀疑光模块 / 线缆劣化 | --get_phy_info 老设备用 --ber_test --ber_thresh 1000000000000 |
需要设备支持与插件;是唯一能发现"状态正常但不健康"的手段 |
| 拓扑发生变化后 | -w topo_<时间戳>.lst 然后 -t topo_<基准>.lst |
基线比对的结论只在拓扑确实变过时才有意义 |
| 大批量计数器趋势采集 | -f <当日 db_csv> + --pm_pause_time <大值> |
见 13.1 节:这类任务里拓扑是常量,跳过发现是正确的优化 |
| 怀疑某台设备身份不可信 | --aguid(ConnectX-3) --extended_speeds all --pm_per_lane |
分别是别名 GUID 与按 lane 的细粒度计数器 |
第三档:受控执行(需要执行窗口与授权)——本篇唯一一类会真正影响他人的操作:
-pc 与 --pm_clear_all 属于这一档,理由三条
- 它是全 fabric 范围的写入操作——官方措辞是 all fabric,会清掉全网所有设备的规范计数器,以及 RN / AR / HBF 计数器
- 它会破坏他人的趋势数据——任何正在采集这些计数器的监控系统都会看到一次假的归零事件
- 官方建议与 --reset_phy_info 一起用——因为两者有交叉计数器,只用一个会让下一轮采集结果令人困惑
推荐流程(把 8.4 与本节合并):协调执行窗口 → -pc 清零 → 让业务跑够一个完整业务周期 → --pm_pause_time N 采样 → 记录本次清零时刻,与 dump 文件一并归档。
最后一条"记录清零时刻"容易被忽略但很重要:没有清零时刻这个时间戳,dump 里的累积值在事后无法解释——看的人不知道这个数字从什么时候开始累计的。
14.2 到哪里去跑:与 SM 部署形态的耦合
本系列第十三篇把 SM 的运行形态分成三种:交换机内嵌 SM、服务器上的独立 OpenSM、UFM 平台。这个划分对 ibdiagnet 的执行位置有直接影响,而这个影响在多数部署文档里不会被提到。
形态一:交换机内嵌 SM。此时子网的"中心"是交换机自己,而 ibdiagnet 必须从一台接入了这个子网的服务器上执行——因为它需要一个本机的 IB 端口作为扫描起点(4.2 节的 -i / -p / -g 就是选这个端口)。这意味着诊断主机本身会成为故障域的一部分:这台服务器 down 了或它的 HCA 出问题了,整个子网就失去了诊断能力——哪怕其它所有设备都正常。因此这种形态下必须准备至少一台备用的诊断主机,且它的 -g 要指向一个已知正常的端口 GUID。这个要求常被忽略。
形态二:服务器上的独立 OpenSM。此时跑 ibdiagnet 的最佳位置就是跑 OpenSM 的那台服务器,理由有三:其一,这台机器的管理面本来就在承载全部子网管理流量,它对整网状态的可见性最好;其二,第十二节的 AR 校验如果要用 --smdb,需要加载 SM 的路由引擎与 rank 数据,而这些数据就在这台机器上(第十一篇讲过 OpenSM 的 SMDB 文件);其三,这台机器本身就是 SM,它的 ibstat 输出里的 SM lid 字段可以直接与 ibdiagnet2.sm 对照(7.2 节)。
形态三:UFM 平台。此时有两层可选:在平台上调度执行,好处是覆盖面与统一调度;或从任意一台服务器手工执行,好处是能按需、不受平台任务队列限制。但要注意 UFM 自身也做大量诊断,两边的结论可能不一致——不一致本身是一条信息:它说明平台的视图与从设备侧直接观测的结果有偏差,这种偏差通常指向权限、密钥或 scope 范围问题(对应官方功能表第 17 项 Support IB Security 与 13.1 节的 scope 机制)。
把三种形态合起来看,可以提炼出一条通用原则:ibdiagnet 的执行位置应当选在"管理面权重最高的那台机器"上,而不是"随便一台能连上的机器"。原因是它采集的不只是数据,还包括管理面的视角——同一张 fabric,从不同位置跑可能看到不同的可达范围(见 6.2 节末尾关于 ibswitches 对照的那条结论)。
最后补一个与本篇主题直接相关的观察:这条原则也解释了为什么 UFM Cyber-AI 这类托管诊断产品会有价值——它把"从哪个位置看"这个选择固化成了平台策略,用户不需要自己判断。但本篇的立场在第二节就说清楚了:这类产品给出的是结论,ibdiagnet 给出的是原始材料。两者不是替代关系,最佳实践是用托管产品做日常巡检的告警,用 ibdiagnet 做告警之后的取证。
14.3 一次完整巡检的检查清单
How — 把前十三节压缩成一份可逐条勾选的清单
本篇的全部内容最终落到这七条上。顺序是有依赖的,不能打乱:
- 确认版本与配置来源:ibdiagnet --version + 确认 /etc/ibutils2/ibdiag.conf 是否存在(4.3 节)
- 确认执行位置与端口:多卡时用 -g 0 列出候选后按 GUID 选,不要用 -i mlx5_0(4.2 节)
- 读 Summary 表定位阶段:注意列顺序是 Warnings 在前(第十节)
- 去 ibdiagnet2.log 读该阶段的具体条目——不要以屏幕输出为准,屏幕受 --screen_num_errs 截断(5.1 节)
- 按需打开对应 dump 文件:身份问题看 .lst,路由问题看 .fdbs(记得 --enable_output fdbs),SM 问题看 .sm,计数问题看 .pm(11.1 节)
- 计数器归零时按受控流程走:清零前先协调执行窗口,并记录清零时刻(8.4 与 14.1 节)
- 归档三样东西:整个 dump 目录 + 命令行原文 + --version 输出——新版 dump 文件已自带后两项(5.2 节),但命令行仍应单独记录,因为 dump 只记录了本次命令行,跨次比对时需要它
最后一条要再强调一次本篇开头的那句话:ibdiagnet 的产出不是"通过 / 不通过",而是"出问题时的完整取证材料"。上面第 7 条之所以要归档三样东西,正是为了让这份材料在半年后仍然可用——一份没有版本与命令行的 dump 文件,半年后你无法判断它是哪一版工具、用什么参数、在什么配置下跑出来的。
本节关键记忆:3 档频次 + 1 个部署耦合 + 7 步清单
- 第一档(周期):-g 0 --enable_switch_dup_guid --enable_output fdbs --pm_pause_time N -P all=0;不含 -pc、-r、BER
- 第二档(按需):-r / --get_phy_info / -w+-t / -f / --aguid
- 第三档(受控):-pc 与 --pm_clear_all——全 fabric 写入、破坏他人趋势、需执行窗口
- 1 个部署耦合:执行位置应选"管理面权重最高"的机器;内嵌 SM 形态必须备一台诊断主机;OpenSM 形态用 --smdb 才有 AR 校验
- 7 步清单:版本与配置 → 端口选择 → Summary 定位 → 日志读细节 → dump 深挖 → 归零走受控流程 → 归档目录+命令行+版本
十五、FAQ 高频问答(20 组)
本节围绕 ibdiagnet 的 20 个高频易错点展开,覆盖术语辨析、工具原理、阶段语义、计数器判读、选项边界、dump 文件与运维流程七类。答案中的阶段名、选项语义、默认值、dump 文件清单、计数器名称、错误码与输出样例,均引自文末「参考资料」列出的 NVIDIA ibdiagnet User Manual、ibdiagnet(1) man page 与 NVIDIA 文档站 Dump Files 页面。
-
Q1. ibdiagnet 到底属于哪个软件包?我该装什么?
装 ibutils2 就有了;它包含在 DOCA-OFED 与 UFM 软件包中。官方手册明确写的是 ibdiagnet 作为 ibutils2 包的一部分分发,而 ibutils2 又包含在 DOCA-OFED 与 UFM 软件包中。课程补充了它不在这两个包里的情况:它也以 InfiniBand 管理包的形式在 NVIDIA 官网单独提供下载。验证是否已安装的唯一可靠方式是执行 ibdiagnet --version,而不是看包管理器列表。注意包名是 ibutils2 带 2,配置文件目录 /etc/ibutils2/ 同源。
-
Q2. -v 和 --version 是一回事吗?
不是,这是新版最容易踩的一个选项错误。-V(大写)或 --version 才是打印版本;而 -v 在 ibdiagnet(1) man page 里是 verbose(详细输出)模式。课程口述里说"输入 --version 或 -v",这个说法需要按官方文档收紧为 -V / --version。另外 -c 也不是"check",它的含义是 --create_config_file(创建模板配置文件)——这是本篇反复强调的"选项以 -h 输出为准"的典型例子。
-
Q3. 课程说它检查"重复的 LID",那 GUID 重复检查和 LID 重复检查有什么区别?
这是两项完全独立的功能,课程转写在这里把它们混成了一项。官方功能表把它们分开列:Duplicated GUIDs Detection(检查并报告 fabric 中重复的 Node GUID 与 Port GUID)与 LIDs Check(对 InfiniBand 设备执行正确的 LID 分配与重复 LID 检查)。检查对象、后果、可修复性全都不同:GUID 重复是身份冲突,SM 无法区分两个设备,转发全部失去意义,不可自修;LID 重复是转发错误,必须由 SM 重新分配。详见 6.1 节的三分表。
-
Q4. dump 文件名到底带不带 2?默认目录是哪个?
取决于版本,必须现场确认,不要照抄任何一篇文档。旧版 ibdiagnet(1) man page 写的是默认输出目录 /tmp、文件名前缀 ibdiagnet.(无数字)、共 13 个文件;新版文档站(v2.24.0)列的是 /var/tmp/ibdiagnet2/、前缀 ibdiagnet2.、共 30 项。课程口述的 /var/tmp/ibdiagnet2/ 只对较新版本成立。确认方法:执行 ibdiagnet --version 后直接 ls 输出目录,不要靠记忆。写进工单或脚本的文件名必须与实际生成的一致。
-
Q5. -o 是干什么的?默认不写会落到哪里?
-o / --output_path 指定 dump 文件的输出目录。旧版 man page 明确写默认值是 /tmp;新版实际落在 /var/tmp/ibdiagnet2/(见 Q4)。课程说"可以用 -o 把它设为别的位置"是准确的。本篇推荐在脚本里一律显式写 -o,避免因版本差异导致 dump 散落在意外目录。官方 2.24.0 文档站另有 --path 选项用于为特定类型的文件设置自定义路径,粒度比 -o 更细。
-
Q6. 我跑了 ibdiagnet -r,为什么没找到转发表 dump 文件?
fdbs 与 ar 默认是禁用的,必须用 --enable_output 显式打开。官方 Dump Files 页面对这两个文件标注了 "Dump disabled by default",页脚统一注明默认禁用的 dump 需用 --enable_output 打开。路由校验执行了,但转发表 dump 不会默认产出——这是路由与 dump 两件独立的事。正确写法是 ibdiagnet -r --enable_output fdbs。--enable_output 的类型值官方按扩展名列举(lst|sm|pm|nodes_info|fdbs|...|db_csv),并有两个保留值 <default|csv:default>(为未指定项禁用)与 <all|csv:all>(全部禁用)。
-
Q7. --screen_num_errs 是干什么的?为什么加了它屏幕反而"干净"了?
它限制打印到屏幕的错误与告警条数上限(默认 5),超出的部分只写进 ibdiagnet2.log,问题一条都没少。官方示例非常清楚:同样一次运行,加了 --screen_num_errs 3 之后屏幕上的 -W- 行消失,多出一行 -I- Errors/Warnings list will be reported in log file。因此判断一次巡检是否干净,必须以 Summary 汇总表与日志文件为准,绝不能以屏幕输出为准。这是本篇第五节与第十节反复强调的那条结论。
-
Q8. ibswitches 说有 N 台交换机,ibdiagnet 只发现 N-1 台,是不是 ibdiagnet 出问题了?
正好相反,差的那一台几乎肯定就是问题所在。两个工具的可达性不同:ibswitches 走 SMP 逐跳查询,遇到不响应 SMP 的设备就无能为力;ibdiagnet 走定向路由,对不响应 SMP 的设备仍然能探测到路径。所以"ibswitches 能看到、ibdiagnet 看不到"这个组合,唯一可能的解释就是那台设备对定向路由也不通——而这正是 Links Check 阶段要报告的"无响应设备"。这是一个非常有价值的交叉验证信号,详见 6.2 节。
-
Q9. 为什么 -P all 会把整个 fabric 的计数器全打出来?all 的默认值是多少?
all 的默认阈值是 0,因此它的语义就是"所有非零计数器都打印"。官方定义:如果提供的任一计数器大于其对应阈值,则打印出来;若使用 all,所有计数器使用同一阈值(默认为 0)。所以 -P all 不是"打印全部计数器"而是"打印全部非零计数器"。实用价值是它可以作为发现"哪些计数器在你环境里非零"的快速手段;-P all=0 是与之等价的显式写法。另外官方也支持组合形式如 -P vl15_dropped=1,port_xmit_discard=1,以及分多次 -P 追加。
-
Q10. port_xmit_wait 高,说明链路坏了吗?
不说明链路坏了,说明链路忙。这是本篇最容易被误用的一条。官方语义:它指示数据包在发送缓冲中等待、直到被发上线缆之前所经过的 ASIC 时钟周期数;可能的原因是接收缓冲区空间不足;高值可能指示拥塞,应当进一步调查。两点必须注意:一是单位是 ASIC 时钟周期数,不是微秒/毫秒,要换算必须知道该 ASIC 的时钟频率;二是成因指向"对端"的接收缓冲不足,所以排查方向是链路的远端而不是本端。正确判读要与流量型计数器组合:流量大 + 高 port_xmit_wait = 接近满载需扩容;流量小 + 高 = 另有原因。
-
Q11. 端口计数器显示成十六进制,怎么读?有没有上限?
按十六进制转十进制即可,关键是别被"位数感"误导:0xB19 = 2849(看起来像 3 位数、实际近 3000),0x1000 = 4096(看起来像 1000、实际超过 4000)。官方示例中 port_xmit_pkts 显示 0xB19、转成十进制是 2849。端口计数器是 32 位计数器,上限 0xFFFFFFFF = 4294967295(约 42.9 亿),跑满大带宽时会回绕。回绕会让"两次采样取差值"算出负数或巨大错误值,所以长周期趋势监控必须能识别回绕;看到数值突然从很大掉到很小,应先怀疑回绕与 -pc 清零,不要先怀疑设备。
-
Q12. --pm_pause_time 设多大合适?默认的 1 秒够吗?
默认 1 秒在多数故障场景下不够;但本篇不给具体秒数,因为合适的窗口取决于你自己链路的实测错误速率,必须现场测。官方定义:指定第一次与第二次计数器采样之间等待的秒数;若为 0 则不做第二次采样;默认 1 秒;差值写入 db_csv 的 PM_DELTA 段。设为 0 时采到的仍是累积值,只适合"快速看一眼"。可行做法:先用 --pm_pause_time 0 读一次累积值,跑一段业务再读一次,用两次累积值之差除以经过时间得到真实错误速率,再用这个数去定 -P 阈值。
-
Q13. -pc 会不会把我这台机器的数据清掉而已?
不是,它是全 fabric 范围的操作——官方措辞是 "Resets all fabric IB spec compliant port counters"。它重置的是所有 fabric 的 PortCounters 与 PortCountersExtended,以及 RN、AR、HBF 计数器。两条实践含义:其一,它是有写入副作用的操作,应先协调执行窗口;其二,它会破坏别人的历史——任何正在采集这些计数器做趋势的监控系统都会看到一次假的归零事件。官方建议与 --reset_phy_info 一起使用,因为两者有交叉计数器,只用一个会让下一轮采集结果令人困惑。要清全部可加 --pm_clear_all(它会自动激活 --scr / --pc / --qos)。
-
Q14. --aguid 是什么?为什么说它"只与 ConnectX-3 相关"?
它是 Alias GUID 检查,官方功能表明确标注 "Relevant for ConnectX-3 devices only"。命令是 ibdiagnet --aguid,作用是从通道适配器、路由器与交换机管理口(若支持)取回已分配的 alias GUID,dump 到 ibdiagnet2.db_csv 与 ibdiagnet2.aguid。官方给出的 .aguid 文件描述也写着 "alias GUIDs (ConnectX-3 only)"。本篇的判断是:在 ConnectX-3 之后的代次上这个功能基本用不到,不要把它当作通用检查项排进周期巡检——但如果你的环境里确实有 ConnectX-3,它在排查"同一物理卡出现多个身份"这类问题时有用。
-
Q15. --ber_thresh 填多少?为什么官方示例填了一个那么大的数?
因为要填的是 BER 的倒数,而不是 BER 本身。官方定义:指定 BER 测试的阈值值;应当提供 BER 的倒数;例如对于 10^-12,该值需为 1000000000000 或 0xe8d4a51000(1012);若给定阈值为 0,则报告所有端口的所有 BER 值。这个设计的用意是让阈值参数是整数,避免浮点表示误差导致边界判定不确定。另两点:默认阈值是 10^-12;--ber_test 官方已标注 Deprecated 且只对 SwitchX / ConnectX-4 / ConnectX-3 有效,新设备要用 --get_phy_info 做 BER 校验。
-
Q16. -r 在大 fabric 上会不会很慢?成本是怎么增长的?
会,而且成本按 CA 数的平方增长。官方在 --vlr 说明里明确提示:由于路径数量是 N 的平方,提取 PSL 文件可能需要一些时间。这解释了 CA-to-CA 路径数的来源——CA 数为 N 时,CA 到 CA 的路径组合是 N × (N-1),官方样例中 "Scanned:210 CA to CA paths" 对应约 15 个 CA(15 × 14 = 210)。本篇建议:全网规模的周期巡检不必每次都带 -r,把它留给"怀疑路由有问题时"以及"fabric 有重大变更之后"。日常巡检用 -P + 计数器 + Summary 就够。
-
Q17. -r 的输出里,端口路径数直方图怎么看?
看"宽度",不看具体数值。官方注释给出了明确判据:"如果 fabric 路由正确,同一树层级的所有端口的直方图应该是集中的(narrow)"。含义是同层级端口的"承载路径数"应当接近;若某层里一个端口过 100 条路径、另一个只过 5 条,即使所有路径都通、也没有信用环,这条 fabric 的路由质量仍然是差的,因为拥塞会集中在少数链路上。另外直方图里出现大量 0(样例中 0 21)不一定是问题——官方注释说明"驱动 CA 的端口被刻意排除,因为它们必须等于 Nca - 1"。这与本系列第十篇讲的路由引擎直接对应。
-
Q18. 默认诊断里包含虚拟化和温度,我能用吗?它们输出到哪?
默认 12 项里包含 "Dump Virtualization Information" 与 "Dump Temperature Sensing",它们分别输出到 ibdiagnet2.vports(含 .vport_pkeys)与相关 db_csv 段。官方 Dump Files 清单里这两项都有对应文件:.vports(Virtualization)与 .vport_pkeys(virtualization pkey tables)。但本篇明确不展开这两块——虚拟化环境的诊断涉及 --scope / --exclude_scope、安全密钥与 scope 文件的配合,是另一个需要单独设计的话题,见 FAQ Q19。本篇只确认它们默认执行、文件位置明确。
-
Q19. fabric 开了 IB 安全,ibdiagnet 能正常工作吗?
官方提供了专门支持,但需要你把密钥告诉它。官方功能表第 17 项 Support IB Security 的定义是:使用 MKEY、VSKEY、AMKEY、CC KEY 导出 fabric 配置。对应的四个选项是 --m_key / --vs_key / --am_key / --cc_key,另有 --pm_key 与 --m2n_key;也可以用 --security_keys 指定密钥文件目录(官方列出该目录内应含 guid2lid、guid2mkey、neighbors、guid2vskey、guid2cckey、guid2_m2n_key、guid2_pm_key)。此外 --read_capability / --write_capability 用于能力掩码配置,因为不同设备的厂商特定 MAD 能力不同。注意这涉及密钥管理,命令行会被记录进 dump 文件(5.2 节),在共享场景下要留意这一点。
-
Q20. 工具的退出码怎么解读?跑完没有报错就算成功吗?
不能只看"跑完没报错"——必须读 Summary 汇总表。官方 ibdiagnet(1) man page 给出六个错误码:1 = 未能完整发现 fabric;2 = 命令行选项解析失败;3 = 与 IB fabric 交互失败;4 = 无法使用本机设备或本机端口;5 = 无法使用拓扑文件;6 = 未能加载所需包。注意这六个错误码描述的是"工具自身能否正常工作",而不是"fabric 是否健康"——退出码为 0 只说明工具跑完了,不代表 fabric 没毛病。健康判定要看 Summary 表中各阶段的 Warnings / Errors 两列(注意列顺序是 Warnings 在前),再去 ibdiagnet2.log 读具体条目。完整的三步顺序见 14.3 节检查清单。
FAQ 总纲(口诀式速记)
- 1 个包名:ibutils2(带 2),含在 DOCA-OFED 与 UFM 中;验证方式是执行 --version
- 2 个易混选项:-V/--version 是版本,-v 是 verbose;-c 是创建配置模板,不是 check
- 3 项独立检查:GUID 重复 / 节点描述重复 / LID 重复——对象、后果、可修复性全不同
- 1 个必须现场确认:dump 文件名带不带 2、默认目录是 /tmp 还是 /var/tmp/ibdiagnet2/,ls 一下再说
- 2 个默认禁用的输出:fdbs 与 ar,必须 --enable_output fdbs
- 1 个交叉验证信号:ibswitches 看到但 ibdiagnet 看不到的那台,就是问题设备
- 1 个判读纪律:-P all 默认阈值 0 = 打印所有非零计数器,不是"打印全部"
- 1 个最易误用:port_xmit_wait 高 = 链路忙,不是链路坏;单位是 ASIC 时钟周期,排查方向在远端
- 1 个读数提醒:十六进制显示(0xB19 = 2849);32 位计数器约 42.9 亿上限,会回绕
- 1 个时间窗口纪律:--pm_pause_time 默认 1 秒不够;设 0 得累积值;窗口长度按实测错误速率定
- 1 个写入型选项:-pc 是全 fabric 范围,需执行窗口、破坏他人趋势、官方建议配 --reset_phy_info
- 1 个平台限定:--aguid 仅 ConnectX-3;--ber_test 仅老设备且已废弃,新设备用 --get_phy_info
- 1 个阈值反直觉:--ber_thresh 填倒数(10^-12 → 填 1000000000000)
- 1 个成本公式:-r 成本按 CA 数的平方增长,大 fabric 不必周期跑
- 1 个直方图判据:看宽度不看数值,同层级端口路径数应接近;大量 0 可能是"驱动 CA 的端口被刻意排除"
- 1 个功能损失:-f 跳过 GUID 重复 / 链路状态 / SM 状态三项检查,所以只适合计数器趋势采集
- 1 个副作用:用了 --scope / --exclude_scope 就不会生成 .ibnetdiscover——采基线与采计数器要分两次跑
- 1 个静默入口:/etc/ibutils2/ibdiag.conf 会被自动应用,命令行可覆盖;取证必须一并记录
- 6 个退出码:1 发现不完整 / 2 选项解析 / 3 交互失败 / 4 本机设备端口 / 5 拓扑文件 / 6 缺包;退出码 0 只代表工具跑完了,不代表 fabric 健康
- 1 个致命警告:-P 与 --pm_pause_time 配 --security_keys 时,命令行会含密钥并被写进 dump 文件
十六、Roadmap 后续预告
本篇是 InfiniBand 专题的第十七篇。它的位置是:本系列第八篇《子网初始化:拓扑发现、LID 分配、路径计算与子网激活》讲清了 fabric 怎么从线缆变成能传数据的子网,第九篇《SM 监控与拓扑变化:选举、故障切换、扫描与重收敛》讲清了子网建立之后如何持续运行,第十篇《拓扑与路由引擎:Fabric 拓扑、路由引擎、自适应路由与信用环》与第十一篇《路由引擎:算法原理、选型对照与 OpenSM 配置验证》讲清了路径计算这一步内部用什么算法实现,第十四篇《HCA 固件升级:工具链、版本识别、固件烧录与验证》补上了设备侧固件本身是否可用这一环,第十五篇《打流与性能基线:perftest 工具族、参数语义与故障判读》与第十六篇《流量抓取与分析:ibdump 与 Wireshark 实战》分别从主动加压与被动抓包两个方向补上了"子网跑起来之后性能是否达标"的验证手段。本篇补上的是这三者之外的最后一条——子网跑起来之后,凭什么断定它是健康的。这六篇合起来覆盖了"设备就绪 → 拓扑发现 → 路径计算 → 子网激活 → 持续监控与重收敛 → 主动诊断与取证 → 性能基线与抓包验证"的完整链路。
接下来的方向,按由"能读懂输出"向"能自动判定与自动取证"深入的顺序包括:
- 用 Wireshark 分析 InfiniBand 流量:本篇的诊断全部基于设备侧上报的计数与状态,看不到链路上真实发生了什么。抓包能看到实际的包序列、重传、拥塞窗口行为——这是计数器给不了的信息。课程在本单元结尾也指向了这个方向
- 把 ibdiagnet 的输出接进时序数据库做趋势分析:本篇第十二节讲了基线比对,但基线比对只能回答"变没变",回答不了"这个变化速率正常吗"。把 db_csv 的 PM_DELTA 段周期采集入库,才能做基线漂移告警
- 阈值该怎么定:一份可操作的方法:本篇明确说了"阈值必须来自实测速率,本篇不给数字",但没有展开"怎么把这个实测过程标准化"——什么样的观察窗口、什么样的业务负载、多少次采样才够
- 拥塞控制的观测与调参:本篇提到官方有 --congestion_control / --congestion_counters / --clear_congestion_counters / --ppcc 这组选项,但没有展开拥塞控制计数器怎么读、PPCC 算法文件怎么写。这与第十篇讲的"链路超额订阅"是同一个问题的两面
- SHIELD 的计数器判读:本篇只把 .rn / .rnc2 列进了清单,没有展开 SHIELD 与 SHIELDv2、HBF 三类计数器各自的含义——这需要第十一篇的自适应路由内容作为前置
- SHARP 树结构与计数器:官方有 --sharp 与 --sharp_opt(含 trees 验证选项),本篇完全没有展开——SHARP 是在 fat tree 里做带内聚合的机制,它改变了"拥塞发生在哪一层"的答案
- 线缆与 PHY 诊断插件的输出解析:本篇讲了 --get_cable_info 与 --get_phy_info 的定位,但没讲输出字段怎么读。要注意官方已把 --get_cable_info 所属插件标注为废弃、将完全移除
- Dragonfly+ 与 Fat-Tree 的拓扑验证:官方有 --dfp(Dragonfly+ 分析报告)与 --ft(Fat-Tree 分析报告)两个选项,本篇没有展开它们的判据——这与第十、十一篇的拓扑与路由引擎内容直接相关
- Rail 优化拓扑验证:--rail_validation 检查拓扑是否为 rail optimized(默认禁用),这是超大规模 AI 集群的标准拓扑形态,值得单独展开
- 多 HCA 主机上诊断端口的选择方法论:本篇 4.2 节给了一条原则(用 -g 0 按 GUID 选),但没有展开"如何把 GUID 与业务流量实际走的路径对应起来"——这需要结合 RDMA 侧的网卡绑定与 --map 节点命名映射
如果你在实践中遇到具体问题——例如 ibdiagnet 跑到一半大量超时、Summary 报 Ports Check 有错误但不知道从哪个 dump 文件看起、-P 阈值设多少合适、-r 在大 fabric 上跑不动、-f 加载 db_csv 报文件无效、固件版本告警该统一到什么版本——欢迎在评论区留言,我会挑出共性问题单独扩展一篇专题。

浙公网安备 33010602011771号