RoCEv2 与无损以太网:PFC、ECN 与 DCQCN
把 RDMA 跑在以太网上,全部难点集中在一件事:不能丢包。
学完这节你能做到
- 解释 PFC 与 ECN 的分工,说出只配一个会怎样
- 看懂 PFC 风暴与死锁的形成条件
- 列出交换机与主机两侧必须对齐的配置项
建议先学跳过这几节会看不懂本节的部分推导
RoCEv2 就是把 RDMA 塞进 UDP
报文结构很朴素:
[ 以太网头 ][ IP 头 ][ UDP 头(目的端口 4791)][ IB 传输头 ][ 数据 ][ ICRC ]
外层是标准 IP/UDP,所以:
- 能被普通三层交换机转发,能跨网段路由,不需要专用的 IB 交换机
- 能被
tcpdump抓到包头(但抓不到内容,数据从没进过内核)
# 确认 RoCE 流量真的在跑
tcpdump -i bond0 -nn udp port 4791 -c 20
看着很美好。但代价藏在一个假设里:RDMA 假设网络不丢包。
为什么 RDMA 受不了丢包
TCP 丢一个包,靠 SACK 精确重传那一个包,代价很小。RDMA 的可靠传输不一样, 传统实现丢一个包要 go-back-N:从丢的那个位置开始,后面全部重发。
在 400 Gbps 上这意味着什么?0.1% 的丢包率就能让有效带宽掉到个位数百分比。 这不是"性能下降",是雪崩。
所以 RoCE 部署的全部难点,就浓缩成一件事:让这条路上永不丢包。而以太网天生是允许丢包的, 拥塞了就丢——这是它设计上的自由。要把它改造成无损,得用两套机制。
PFC:按优先级踩刹车
Priority Flow Control(802.1Qbb)。交换机某个优先级队列涨到水位线时, 向上游发一个 PAUSE 帧:这个优先级你先停一下。
下游交换机队列涨到阈值
│
▼ 发 PFC 帧(只针对某个优先级)
上游端口暂停发送该优先级
│
▼ 队列泄下去后恢复
关键在"按优先级"——只让 RDMA 那条队列停,普通 TCP 流量不受影响。
PFC 的两个严重副作用
1. 反压会层层传导(congestion spreading)
A 堵了让 B 停,B 的队列于是涨起来,B 又让 C 停……一个端口的拥塞可以扩散到整个 fabric, 表现是全网莫名卡顿,但找不到哪里在丢包。
2. 可能死锁
如果反压形成环路(A 等 B、B 等 C、C 等 A),所有端口互相等待,整片网络永久停摆, 只能重启交换机。这在有环路的拓扑或者路由配置不当时会真实发生。
把 PFC 当作主要拥塞控制手段是最常见的架构错误。它的正确定位是"兜底": 在 ECN 来不及反应的瞬间保住不丢包。长期依赖 PFC 说明网络设计有问题。
判断依据很直接:看 PFC 帧计数。
ethtool -S bond0 | grep -iE 'pause|prio.*pfc'正常情况下这个数应该很少且不持续增长。如果每秒都在涨几千,说明拥塞控制没起作用, 网络在靠踩刹车硬撑。
ECN 与 DCQCN:真正的主力
ECN(Explicit Congestion Notification)的思路完全不同:不停流量,而是让发送端自己降速。
交换机队列超过阈值
│
▼ 在 IP 头里打个标记(不丢包、不暂停)
接收方网卡看到标记
│
▼ 回一个 CNP(拥塞通知包)给发送方
发送方网卡降低发送速率
│
▼ 一段时间没再收到 CNP 就慢慢加回来
这套端到端的闭环叫 DCQCN(Data Center QCN),是当前 RoCE 拥塞控制的事实标准。
它和 PFC 的分工:
| 机制 | 作用范围 | 反应速度 | 定位 |
|---|---|---|---|
| PFC | 逐跳(hop-by-hop) | 快(微秒级) | 兜底,防止瞬时丢包 |
| ECN/DCQCN | 端到端 | 慢(一个 RTT) | 主力,从源头压住流量 |
水位线要错开配置:ECN 的标记阈值必须低于 PFC 的触发阈值。 这样正常拥塞时先由 ECN 温和降速,只有突发来不及时才轮到 PFC 踩刹车。配反了, PFC 会天天触发,ECN 形同虚设。
优先级映射必须端到端一致
这是实际部署中失败率最高的环节。RDMA 流量要被识别成"那条特殊队列", 靠的是报文里的优先级标记,而这个标记在不同层有不同名字:
| 层 | 字段 | 取值范围 |
|---|---|---|
| IP 层 | DSCP | 0–63 |
| 以太网层 | PCP(802.1p) | 0–7 |
| 交换机内部 | TC / 队列号 | 取决于机型 |
一条链路上的每一跳——主机网卡、leaf、spine、对端网卡——都必须把同一个值映射到同一条无损队列。 任何一跳映射错,RDMA 流量就会掉进普通队列,拥塞时照常被丢,于是带宽断崖式下跌。
主机侧的相关配置:
# 查看/设置 QoS:哪些优先级启用 PFC、带宽如何分配
mlnx_qos -i ens1f0
# 例:只给优先级 3 开 PFC
mlnx_qos -i ens1f0 --pfc 0,0,0,1,0,0,0,0
# trust 模式:按 DSCP 还是按 PCP 判优先级(要和交换机侧约定一致)
mlnx_qos -i ens1f0 --trust dscp
NCCL 侧对应的参数是 NCCL_IB_TC。生产配置里常见 NCCL_IB_TC=106——
不设的话 RoCE 流量没有优先级标记,一拥塞就会被当普通流量丢掉。
一张网卡有多个 GID 条目,分别对应 RoCEv1、RoCEv2、IPv4、IPv6。选错版本会出现 "能建链但性能异常"或"直接连不上"。所以每次测试前先确认:
# 只看 v2 条目,记下 index
show_gids | grep v2DEV PORT INDEX GID IPv4 VER
mlx5_0 1 3 0000:0000:0000:0000:0000:ffff:0a68:1467 10.104.20.103 v2
然后把这个 index 传给测试工具:
ib_send_bw -x 3 -d mlx5_0 # server 端
ib_send_bw -x 3 -d mlx5_0 <server> # client 端NCCL 对应的是 NCCL_IB_GID_INDEX。默认能自动选对的情况居多,
但一旦出现诡异现象,先用 show_gids 核对。
验收清单:怎么证明它真的无损
配完不能只看"能跑通"。下面五项过了才算交付:
# 1. 链路速率与状态:每张卡都要是预期速率
ibstat | grep -E 'Rate|State|Physical'
# 2. 点对点带宽:应达到线速的 90% 以上
ib_send_bw -x 3 -d mlx5_0 <server_ip>
# 3. 点对点延迟:同机房应在个位数微秒
ib_write_lat -x 3 -d mlx5_0 <server_ip>
# 4. 压力下 PFC 帧不应持续暴涨
watch -n2 "ethtool -S bond0 | grep -i pause"
# 5. ECN 标记应该有、但不应该失控
nstat -az | grep -i ecn
再加一项集群级验收:多机 NCCL AllReduce 的 busbw 达到理论峰值 90% 以上。 这一项过了,说明整条链路(网卡、交换机、拥塞控制、拓扑布线)都是对的。
IB 的无损来自链路层 credit 机制,网络自带,不需要你配。RoCE 的无损要靠人配, 配对了性能相当,配错了比普通 TCP 还糟。
所以决策点不在性能,在团队:有没有人能长期维护 PFC/ECN 配置。 没有的话,IB 那笔额外的硬件钱买的其实是确定性。
检查点
RoCE 集群里 PFC 帧计数每秒增长几千,业务带宽还行但延迟抖动很大。该怎么判断?
RoCE 环境下 ib_send_bw 点对点能跑到线速的 95%,但多机 NCCL 一上量带宽就掉到三分之一。最值得先查的是?
关于 PFC 和 ECN 的分工,下面哪些说法正确?(多选)
这节课的落点
- RoCEv2 = RDMA over UDP 4791,能被普通三层网络路由,抓包只能看到包头
- RDMA 的可靠传输是 go-back-N,0.1% 丢包就能让带宽雪崩
- PFC 逐跳踩刹车,反应快但会反压扩散、可能死锁 —— 只能当兜底
- ECN/DCQCN 端到端降速,是主力;ECN 水位必须低于 PFC 阈值
- DSCP / PCP / TC 映射必须端到端一致,任何一跳错都会让 RDMA 流量掉进普通队列
show_gids | grep v2先确认 GID index,再跑ib_send_bw -x <idx> -d <dev>- 验收要看五项:链路速率、点对点带宽、点对点延迟、PFC 帧、集群 busbw ≥ 90%
延伸资料
- ·k8s-in-action
network/network-operator/README.md - ·k8s-in-action
ai/nccl-tests/config-reference.md - ·DGX SuperPOD H200 参考架构 ↗