凌晨两点值班手机被一条“Mellanox 网卡光模块高温”告警震醒。这不是我第一次跟 NVIDIA Mellanox 网卡打交道但那天之后我下决心把自己负责的这套网络优化项目彻底工具化。我们内部给这个项目起名叫NEO全称是Network Edge Optimization其实做的事情很朴素把节点上每一张 Mellanox ConnectX 网卡、每一根光模块/线缆的物理状态全部盘清楚在 GPU 集群的“最后一公里”上减少莫名其妙的卡顿和断链。文章里要聊的mlxlink -d mlx5_9 -m/-c参数就是我在这个项目里使用频率最高的两把螺丝刀。如果你也负责跑 AI 训练集群、存储网络或者 HPC 高速互联大概率会遇到类似的场景nvidia-smi正常、RoCE ping 也通但分布式训练一跑就时不时超时最后抓破头皮才发现是某个光模块接收功率掉到了悬崖边上。下面这些内容就是我基于实际排障经验整理出来的 NEO 项目实战笔记。1. 项目代号 NEO 的由来我们为什么盯上 Mellanox 网卡1.1 从 GPU 集群的“最后一公里”说起单张 GPU 卡的计算能力越来越猛但跨节点的数据交换还是要靠网络。在我们机房里一台 8 卡 GPU 服务器通常会配一张或两张 NVIDIA Mellanox ConnectX 系列网卡通过 100G/200G 以太网或 InfiniBand 把数据送出节点。这套链路里面最容易被忽略的就是节点出口那一段物理层——包括光模块、线缆、接口连接器和 PCIe 链路。NEO 这个项目一开始并不叫 NEO。最早我们只是在监控脚本里加了一条ethtool -S收包错误统计后来发现很多问题其实不在驱动、不在路由而在光模块的发射光功率、接收光功率和温度。于是我们就把“节点出口物理层检查”单独列为一个项目起名 NEO也就是 Network Edge Optimization。项目刚启动的第一个月就靠这几条命令在十几个节点里找出了三根有隐患的线缆和两个劣化光模块。你可能会问为什么不用交换机端去定位交换机当然能看链路状态但端到端的问题必须从两端各自的视角去看。同一个光纤回路上A 端看到的是发送功率B 端看到的是接收功率如果 B 端接收功率不对可能是光纤衰减、接头脏污也可能是对端发射模块有问题。这时候单看交换机端口是不够的必须站在每块网卡的视角去读模块诊断信息这也是mlxlink这类工具无法被替代的原因。1.2 选型ConnectX-6/7 还是 BlueFieldNEO 的第一批节点选的是ConnectX-6 Dx双口 100G后来扩容时也上过 ConnectX-7。为什么不直接全上 BlueField因为我们的场景主要是 GPU 节点的 RoCE 通信不需要把 Open vSwitch 卸载到 DPU 上用 ConnectX 系列更简单、成本也更可控。如果你要做虚拟机网络卸载、裸金属云化或者更复杂的可编程数据处理再考虑 BlueField 也不迟。选型时还有一个容易忽略的因素不同型号网卡对mlxlink的支持字段不完全一样。ConnectX-5 以前的部分网卡可能读不到完整的线缆信息ConnectX-6/7 基本能覆盖常见的光模块和 DAC/AOC 线缆。我在 NEO 项目里踩到过一个坑拿最新版 MFT 在旧型号 ConnectX-4 上执行mlxlink -c工具直接报 “Command not supported”最后还得回到ethtool -m去读模块信息。所以如果你照着本文的步骤操作最好先确认一下手头设备的固件版本和 MFT 版本别等到命令跑不通才回头查兼容性。2. 环境准备让 mlx5_9 出现在 mlxlink 的视野里2.1 安装 MFT / mlx-tools 的注意事项mlxlink不是 Linux 内核自带的工具它通常随MFTMellanox Firmware Tools一起发布。NVIDIA 官网的 Networking Software/Firmware 页面里可以下载对应操作系统版本的 MFT 包安装后一般会提供mst、mlxlink、mlxup等一堆工具。安装时最常见的坑是版本匹配。生产服务器如果跑的是 Ubuntu 20.04/22.04且内核是定制过的直接用官网的 MFT RPM/DEB 包通常没问题但如果你自己编译过内核最好先确认 MFT 包依赖的 kernel modules 能正常编译。另外一个更隐蔽的问题是MFT 版本太旧会导致mlxlink无法解析新固件的部分字段。比如某些 ConnectX-6 固件升级后老版本 MFT 读出来的温度、电压全是 “Unknown”而不是实际数值。所以我会在每次升级网卡固件时顺手把 MFT 也升到对应版本避免工具和固件鸡同鸭讲。装完之后先跑一条命令确认设备树状态sudo mst start sudo mst status正常输出里能看到类似这样的设备列表DEVICE_TYPE MST PCI BUS IRQ ConnectX-6 Dx /dev/mst/mt4125_pciconf0 ...mst status里显示的设备路径是后续很多工具的输入但mlxlink用的设备名不太一样它直接接收mlx5_9这种内核设备名。2.2 识别设备号mlx5_9 到底是谁第一次看到mlx5_9的人多半会懵这是网卡型号吗不是。mlx5_9是 Mellanox 驱动mlx5_core创建的设备实例名数位序号一般来自系统对多张网卡/PF 的枚举顺序。同一台服务器里插了两张 ConnectX-6 和一张 ConnectX-4很可能就会看到mlx5_0、mlx5_1、mlx5_2之类序号完全由驱动加载时决定。要弄清楚mlx5_9对应哪张物理卡、哪个网口我的习惯是先看 lspcilspci -nn | grep -i mellanox然后把 RDMA 设备名和端口映射关系打出来ibstat ibdev2netdev比如输出可能是mlx5_9 port 1 enp216s0np0 (ConnectX-6 Dx)这样我们就知道mlx5_9对应的物理网卡是哪一个了。多卡服务器上最怕的就是拿mlx5_9的诊断结果去拔另一张卡的线所以在执行mlxlink之前务必先把映射关系确认清楚。我们 NEO 项目里的巡检脚本第一步就是自动跑ibdev2netdev生成一张网卡端口到mlx5_*的对照表再逐个做诊断不然拔错线真的会让整个训练队列中断。3. -m 参数实战光模块 EEPROM 与光功率读数全解3.1 理解模块信息输出字段当你确定要对某个设备做光模块诊断时最常用的命令是mlxlink -d mlx5_9 -m-m在这里表示读取Module模块信息也就是网卡上插着的那个 QSFP28/QSFP-DD/OSFP 光模块的 EEPROM 内容。Mellanox 网卡遵循 SFF-8636 类的管理接口规范模块里会存厂商、型号、序列号、速率能力、波长以及实时诊断数据。我简化后的输出大致长这样Device : mlx5_9 Module ID : QSFP28 Type : 100G SR4 Vendor Name : Mellanox Part Number : MFA1A00-C003 Serial Number : MT1234X56789 Temperature : 51.0 C Vcc : 3.29 V Tx Power : 1.32 mW Rx Power : 0.85 mW Rx Power High Warn: 2.50 mW Rx Power Low Warn : 0.10 mW这些字段看起来多实际排障时需要优先看三样Temperature模块内部温度长时间超过 70℃ 要警惕有些型号的告警阈值设在 75℃ 以上但高温会加速模块劣化。Vcc模块供电电压正常在 3.13V-3.47V 之间。偏离太多可能不是模块坏了而是主板供电或背板接触问题。Tx Power / Rx Power发射功率和接收功率这是判断链路质量最直接的证据。拿到这些数据先别急着高兴还需要理解功率的单位和含义。mlxlink默认显示的mW只是毫瓦很多资深网络工程师习惯用 dBm。换算很简单dBm 10 * log10(P / 1mW)。比如0.25 mW对应-6 dBm1 mW对应0 dBm。3.2 用光功率判断链路质量光模块的发射功率一般集中在 1mW 上下也就是 0 dBm 附近100G SR4 光模块接收端能工作的最低功率一般在-8 dBm 到 -10 dBm左右但这只是“能工作”的边界不代表“稳定”。我通常会把 -6 dBm 作为观察阈值低于这个值就进入重点跟踪名单如果收到大量 CRC 错误再加接收功率掉到 -10 dBm 以下基本上可以直接判断物理层在恶化。举一个实际案例有段时间某训练节点的 NCCL all_reduce 性能时好时坏ibstat显示 LinkUp但跑大规模集合通信时延迟偶尔飙高。我对着mlxlink -m的输出一看Rx Power从正常时的0.6 mW掉到了0.04 mW换算过来约 -14 dBm这已经远超模块能稳定工作的范围。为什么链路还能 up因为极低速率下信号还能恢复但 100G PAM4 信号对噪声和幅度太敏感瞬间就出 FEC 纠错风暴。更换模块后Rx Power回到0.7 mW问题立刻消失。这里要说一个容易误判的点mlxlink -m读到的Rx Power是模块内部接收光功率它低不一定是模块坏也有可能是光纤连接头脏了、光纤弯曲过大、对端发射模块功率下降。所以看到 RX 低我下一件事就是去对端机器上也跑一次mlxlink -m看一下对端的 Tx Power。如果对端 Tx 正常而本端 Rx 低大概率是光纤链路损耗大优先做清洁和重新插拔如果对端 Tx 本身就低那就要换对端模块。3.3 第三方模块与“Unsupported”的真相NVIDIA Mellanox 网卡有一个让很多运维头疼的机制固件里会校验光模块/线缆的厂商信息。如果你插了非 NVIDIA 认证的第三方模块mlxlink -m里可能显示Vendor Name: Other或者直接标记为Unsupported。这不代表模块物理上立刻不能工作网卡可能仍然能 Link Up但固件会关闭一些高级诊断能力或者干脆拒绝开启端口。我们曾经贪便宜买过一批第三方 100G AOC 线缆插上去能亮但mlxlink -m的 EEPROM 里很多字段都是乱码而且使用过程中出现过高频 CRC 错。后来和厂商确认是因为他们的线缆 EEPROM 里写的告警阈值和 Mellanox 网卡预期不一致导致网卡错误触发了一些保护逻辑。换回 NVIDIA 认证线缆后一切正常。这条经验建议你记下来在需要长期稳定运行的生产环境里不要省那个模块/线缆的钱认证兼容性本身是 SLA 的一部分。4. -c 参数实战线缆诊断与故障定位4.1 DAC/AOC 线缆的信息读取说完了光模块再来说另一个高频场景直连铜缆DAC和有源光缆AOC。这两种线缆的接口和光模块一样但它们的“模块”是直接封装在线缆两端的。Mellanox 支持用mlxlink的-c参数读取线缆信息命令长这样mlxlink -d mlx5_9 -c-c在我理解里对应的就是Cable线缆诊断/信息读取。它会读线缆内部的 EEPROM给出线缆类型、长度、厂商、支持的速率还有一些和信号质量相关的参数。输出示例Cable Type : Passive Copper Cable Length : 2m Vendor Name : Mellanox Part Number : MCS2A00-A002 Serial Number : ... Supported Speed : 100Gb/s Link State : ActiveDAC 线缆本身没有光功率所以-m那些模块诊断字段在 DAC 上永远读不到真正要关注的是线缆两端的连接状态、信号调整参数、以及有无异常告警位。AOC 线缆则把电光转换藏在两端线缆 EEPROM 里会多出一些和激光器相关的状态比如发射光功率、接收光功率这些信息同样通过-c读取。一开始我们 NEO 项目里只对光模块跑-m后来发现有一批问题其实发生在 DAC 线缆上才把-c也加进了巡检脚本。两者配合起来基本上能覆盖服务器出端口的所有物理形态。4.2 用 cable 信息定位瞬时断链说一个用-c抓到“真凶”的案例。某个存储节点上的 100G 链路每隔六小时左右就会 flap 一次时间点完全没有规律系统日志里只能看到网卡端口 Link Down/Link Up。我第一次排查时怀疑是交换机配置问题后来看了交换机日志发现链路 down 的原因是远端信号丢失并且发生时间点和节点本地网卡日志完全吻合。于是走到服务器侧先mlxlink -d mlx5_9 -c看了下这根线缆的状态发现Link State: Active但有一项Cable Warning: Out of Range亮着。继续往下翻看到一个Cable Temperature字段明显偏离同批次其他线缆好几度而且还有一组Signal Margin参数在多次采样里数值忽高忽低。后来把这根线缆搬到实验室压力测试发现轻微弯折时信号余量会断崖式下跌。换线之后问题彻底消失六小时定时 flap 没有再出现过。那次之后我学到一个经验瞬时断链不一定都是模块坏可能是线缆内部的物理损伤。DAC/AOC 一旦内部光纤或铜芯受力弯折平时可能还能协商上但温度变化或者震动就会让信号余量跌破阈值。mlxlink -c的价值在于把线缆的状态字段暴露出来哪怕这些字段平时不会显示红色告警也要纳入趋势记录。4.3 链路协商参数的额外检查除了线缆本身的信息-c输出里通常还包括两端协商出来的工作速率、FEC 模式、自动协商状态。这些参数和物理层问题交织在一起如果只盯着光模块功率往往会漏掉真正的原因。比如 100G 以太网通常建议开启 RS-FECReed-Solomon FEC因为 PAM4 信号对噪声敏感不开启 FEC 的话短距离光模块都可能出现几百个 CRC 错误。但如果两端协商时不匹配——一端开 RS-FEC另一端只开 FC-FEC 或者关掉 FEC表现就是链路能起来但 FEC 错误计数器一路猛涨业务性能却拉胯。用mlxlink -d mlx5_9 -c看当前协商结果确认两端 FEC 模式一致是排查这类问题的第一步。如果发现不一致别急着敲命令强制配置先查交换机端口的配置很多交换机默认对 100G 端口启用 RS-FEC而服务器网卡默认配置可能没有你需要在两端找到共同可接受的配置再统一调整。5. 现场排错一次 mlxlink 定位光模块劣化的完整链路5.1 现象业务报错与链路反复 flapNEO 项目上线后遇到最典型的一次问题是某个训练集群频繁出现 NCCL 超时。表面现象非常具有迷惑性所有网卡nvidia-smi正常GPU 利用率高的节点跑单机测试没问题RoCE ping 能通ibstat显示端口状态为 Active但一旦跑大规模 all_reduce偶尔会有人报 “Timeout”边缘交换机上看端口没有长时间完全 down但 FEC 错误计数器在跳跃。这种问题最怕“看起来都正常”。如果没有物理层工具我们大概率会陷入反复调整 NCCL 超时参数、修改路由、重装驱动的泥潭。实际上分布式训练对网络质量的敏感度远高于普通 TCP 业务微小的物理层抖动都会被集合通信放大。5.2 排查把可疑网卡按序号捋一遍我先把集群里所有 GPU 节点的 Mellanox 网卡设备名梳理出来用ibdev2netdev拿到mlx5_*到网口的映射然后写了一个小循环挨个执行for dev in $(ibstat -l); do echo $dev mlxlink -d $dev -m | grep -E Temperature|Tx Power|Rx Power done这个脚本在几十个节点上跑完后只有mlx5_9的Rx Power明显异常而且温度也偏高。再回头看这台节点的机柜位置发现它正好在空调出风口对面但挡板前堆了一堆标签线缆散热条件很差。到这里已经基本锁定是两个因素叠加模块本身可能有老化环境温度又加快了劣化速度。接着我用mlxlink -d mlx5_9 -m连续采了 10 次数值发现Rx Power在-13 dBm到-15 dBm之间波动。按我们 NEO 项目的判定标准这类模块必须直接更换不能再等了。5.3 结论与替换方案最后我们联系硬件厂商更换了那个光模块顺便整理了挡板前的理线让模块进风更顺畅。替换后mlxlink输出的关键数值恢复正常指标异常时更换后Temperature71.5 ℃48.0 ℃Tx Power0.9 mW1.3 mWRx Power0.04 mW0.72 mW新的模块连续跑了一周FEC 错误计数清零NCCL 也不再出现超时。这次排障让我更加坚定NEO 这种项目不能只看端口 up/down必须把物理层诊断数据纳入日常巡检。哪怕一个月只捡出一根有隐患的线缆也值回工具学习和脚本开发的成本。6. 那些文档里不会写的坑散热、兼容性与固件版本6.1 模块温度与散热口的关系很多运维第一次看到光模块温度上 70℃ 都以为模块坏了其实未必。光模块的散热路径非常短它插在网卡面板里热量主要靠机箱风流带走。如果机柜前后挡板被杂乱的线缆堵住或者服务器前脸正好被隔壁设备的电源吹出热风干扰模块温度能轻松比正常高 10℃。我在 NEO 巡检脚本里给温度加了两个阈值65℃ 时报警60℃ 以下才认为正常。高温环境下光模块的激光器发射效率会漂移长期下来接收灵敏度下降最终出现那种“时好时坏”的链路。如果你用mlxlink -m看到温度高先别急着换模块看看物理环境把散热改好之后温度恢复正常往往模块还能继续用很久。6.2 固件版本和 MFT 版本要一起升Mellanox 网卡的固件升级工具是mlxup但很多人不知道mlxlink的字段解析能力和固件版本、MFT 版本都有关系。我遇到过同类网卡一台机器上mlxlink -m能正常读功率另一台上干脆报 “Failed to get module info”最后发现是那台机器的 MFT 没升级和已经升级的固件不兼容。所以在 NEO 项目里我要求所有节点必须保证 MFT 版本和网卡固件版本同批次升级不要拆分操作。顺带提一句如果你在 Ubuntu 上折腾过 NVIDIA 驱动应该体会过“驱动模块和内核版本不匹配”的酸爽。Mellanox 的 OFED 驱动和 GPU 的 NVIDIA 驱动是一对容易互相踩踏的邻居尤其是系统自动更新内核后mlx5_core和nvidia模块经常一起罢工还会连带出现类似nvidia-smi has failed because it couldnt communicate with the nvidia driver的报错。这时候先别怪驱动去看一下自己是不是升级内核后忘了重新安装 OFED 和 NVIDIA 驱动。把系统更新纳入变更管理比事后排队重装要省心得多。6.3 其他实用命令组合除了-m/-c两个参数NEO 项目里的日常巡检还会用到几个互补命令mlxlink -d mlx5_9 -e查看以太网端口统计包括 CRC、FEC 错误ethtool -m enp216s0np0有时 MFT 装不了或者版本太老ethtool -m也能读出一部分模块 EEPROMmst status快速确认设备是否被驱动识别ibstat确认 InfiniBand/RoCE 端口状态。组合起来我通常会在巡检脚本里先跑mst status再对每个mlx5_*执行mlxlink -m和mlxlink -c把结果以 CSV 存起来按天拉趋势。判断标准很简单接收功率不能连续两天下降超过 1 dB温度不能持续高于 65℃。一旦达到报警条件值班人员会主动找硬件厂商处理而不是等到分布式训练报错再生产变更。这整套流程就是 NEO 项目给我的最大回报把不可见的物理层风险变成每天可见的量化趋势。最后再分享一个小技巧mlxlink -c在不同固件版本上输出的字段名略有差别有些老版本叫Signal Integrity新版本可能改成SNR Margin别看到 Unknown 就紧张先 grep 一把同批所有设备的数据如果所有设备都是 Unknown大概率是工具版本问题而不是硬件真的坏了。