RDMA把数据搬运交给了网卡硬件,但硬件也会出错------而且它出起错来比软件更难查:丢一个包不会打印"Segmentation fault"。
好在硬件给自己装了一套"仪表盘"和"黑匣子":CQE状态码告诉你某个具体操作哪儿失败了,端口计数器告诉你整张网卡出了什么状况,ibv_devinfo和ethtool则让你看清链路的物理状态。
这篇文章从硬件视角,把这些排障工具一个个拆开。
一、CQE状态码:每个错误包都有自己的"死亡报告"
当你轮询CQ拿到一个状态码非IBV_WC_SUCCESS的CQE时,网卡硬件已经在里面写好了失败原因。
1.1 IBV_WC_LOC_QP_OP_ERR
QP收到了一个它不认识的OpCode------比如一个UD QP收到了RC的SEND Request。硬件在包处理流水线上解析BTH时发现OpCode超出合法范围,直接拒绝处理,返回此错误。检查点:本端SQ里填的WQE操作类型是否对应该QP的传输类型。
1.2 IBV_WC_LOC_PROT_ERR
L_Key或R_Key权限校验失败。硬件在地址翻译阶段查MPT时发现钥匙不对------要么钥匙本身不匹配,要么QP与MR不属于同一个保护域(PD)。网卡执行此校验无需软件参与,校验失败直接返回。检查点:MR注册时给的权限够不够;QP和MR是不是在同一个PD里。
1.3 IBV_WC_REM_ACCESS_ERR
远端拒绝了你的访问。请求包发过去后,对端网卡校验R_Key发现权限不足------比如你拿一把只有读权限的钥匙试图写。检查点:注册MR时是否声明了IBV_ACCESS_REMOTE_WRITE。
1.4 IBV_WC_RNR_RETRY
接收端还没准备好接收缓冲区。你发了一个SEND消息,但对端QP的RQ里没有空闲的Receive WQE。硬件无法把数据写入内存,于是返回RNR NAK,你在本端CQE里看到这个状态码。检查点:接收端是否提前调用了ibv_post_recv;rnr_retry_cnt是否设得太小。
1.5 IBV_WC_REM_OP_ERR
远端QP在处理你的请求时出了内部错误。比如远端尝试访问内存时发现地址越界或权限不足。这通常是远端应用有问题,不是网络的事儿。
1.6 IBV_WC_RETRY_EXC_ERR
重传次数超过了配置上限。发送端一直没收到ACK,重传了retry_cnt次都没成功------可能是链路断了,也可能是对端QP已经进入了Error状态。检查点:确认对端QP的状态;检查网络丢包情况。
二、端口计数器:硬件的"里程表"和"故障灯"
网卡硬件内部维护了一组计数器,记录收发的每一个包和每一次错误。NVIDIA的ibdiagnet工具可以读取这些计数器。
关键计数器速查:
port_xmit_discard
计数场景: 发送端因拥塞或缓冲区不足主动丢掉了包
排障思路: 计数持续增长说明发送队列拥塞。检查PFC配置和ECN阈值。
port_rcv_errors
计数场景: 接收端检测到CRC错误或链路级损坏
排障思路: 非零表示链路信号质量有问题。检查光模块、光纤、对端PHY。
port_rcv_remote_physical_errors
计数场景: 对端发来的数据包在物理层就坏了
排障思路: 上电自检计数持续增加说明SerDes参数异常;硬件自协商后仍频繁报错则考虑更换硬件。
symbol_error_counter
计数场景: 8b/10b或64b/66b编码层符号错误
排障思路: 时钟漂移或信号完整性有问题。
local_link_integrity_errors
计数场景: 链路训练失败或物理连接问题
排障思路: 链路一直起不来。检查线缆是否插好、对端端口是否up。
link_down_counter
计数场景: 链路状态从up变成down的次数
排障思路: 频繁波动说明物理连接不稳定。
pcie_malformed_tlp(PCIe寄存器)
计数场景: 总线上的事务层包格式错误
排障思路: TLP头格式错误或内存地址对齐问题。检查PCIe配置空间中的MPS/MRRS设置。
port_xmit_wait
计数场景: 发送端因流控停顿的总时长
排障思路: 值越大说明PFC触发越频繁。
如何使用这些计数器:最直接的方法是用ibqueryerrors --counter主动巡检,检查的阈值可以配置。也可以使用ibdiagnet -P port_xmit_discard=1定期采集计数器数据并生成日志报表,当port_xmit_discard超过设定的阈值(比如1)时,配置的巡检命令会在日志中醒目地打印出报错信息,便于集成到自动化运维脚本中。
三、常用诊断命令速查
ibv_devinfo -v:显示RDMA设备的详细信息------端口状态、LID、MTU、FW版本等。这是排查RDMA软件栈问题时的第一命令。如果看到的端口状态是"DOWN",先查物理连接;如果是"ACTIVE"但通信不通,查路由和子网管理器。
ethtool -S <interface>:读取网卡的以太网统计------收发包计数、CRC错误、PFC帧统计等。RoCEv2场景必备。看到rx_crc_errors跳变,查光纤和光模块;看到rx_pfc_*计数异常,查PFC配置。
lspci -vv -s <address>:查看PCIe设备的状态。LnkCap显示设备支持的最高规格,LnkSta显示当前实际运行的规格。两者不一致说明链路降级了------接触不良或带宽不足。PCIe降级会直接限制网卡的最大吞吐,但不会在ibv_devinfo或ethtool里留下明显痕迹,因此排查吞吐问题时建议把lspci作为常规检查项之一。
rdma link:显示RDMA设备的链路状态。快速确认设备是否被系统识别、端口是否up。
ibstatus:显示InfiniBand设备状态和端口信息,输出比ibv_devinfo更精炼,适合快速检查端口是否ACTIVE以及LID是否已被子网管理器分配。
show_drop(Mellanox专用):查看端口丢包详情。比通用计数器更精细,能区分丢包发生在哪个环节。
sminfo:查询子网管理器状态。确认SM是否运行、主备是否正常。
四、PFC Watchdog:交换机的"自动断路开关"
PFC配置不当可能导致队列永久阻塞------即之前文章讲过的PFC死锁。死锁的表现是某个优先级队列长时间不转发数据,同时port_xmit_wait持续飙升。PFC Watchdog专门对付这个问题:如果某队列持续被Pause超过设定时间,Watchdog触发,交换机不再响应PFC Pause帧并自动清空队列,打断死锁环路。
交换机配置PFC Watchdog后可实时查看统计:PFC storm detected(死锁被检测到的次数)和PFC storm restored(死锁被自动恢复的次数)。若detected远多于restored,说明配置可能需要调优------要么阈值设得太敏感,要么网络拥塞模式根本不是死锁。
在RoCEv2部署中,PFC和ECN需要配合使用。ECN监控队列深度、主动标记CE码点,CNP返回后触发DCQCN主动降速;PFC作为最后一道防线,在ECN失效导致队列真正撞线时才触发逐跳反压。当ECN+DCQCN工作正常时,PFC Watchdog应很少触发------如果频繁触发,说明ECN配置需要重新审视。
五、总结
RDMA硬件调试的本质是读懂硬件留给你的三类信号:CQE状态码告诉你哪个操作出了什么问题,端口计数器告诉你整体健康状态,PFC Watchdog等机制自动介入恢复并留下统计痕迹。理解这些信号,你就能在没有"Segmentation fault"的世界里抓住每一个故障。