3. PFC(优先级流控)原理:逐跳反压机制,如何防止丢包?
大家好,我是老张。今天聊PFC,Priority Flow Control。
说白了,这就是数据中心无损网络的核心命脉。没有PFC,RoCEv2就是空中楼阁。我当年第一次接触无损网络时,觉得PFC不就是个流控嘛,有啥难的?结果被现实狠狠教育了一顿。
3.1 为什么需要PFC?
传统以太网丢包了怎么办?重传呗。但RDMA不行。RDMA要求网络零丢包,一旦丢包,性能直接断崖式下跌。你想想看,一个GPU集群正在跑大模型训练,突然丢了一个包,整个AllReduce都得等重传,那画面太美我不敢看。
那传统的802.3x流控呢?它是基于端口的。一个端口忙,就把整个端口都停了。这太粗暴了。比如端口上有两个流,一个高优先级,一个低优先级。低优先级的把端口堵了,高优先级的也得跟着等。这不合理。
所以PFC来了。它把流控粒度从端口细化到了优先级。每个优先级可以独立做流控。嗯,这里要注意,PFC定义了8个优先级(0-7),每个优先级对应一个虚拟通道。
核心思想:PFC不是停整个端口,而是只停某个优先级。其他优先级照常转发。
3.2 逐跳反压机制
PFC是逐跳的,不是端到端的。什么意思?
每一跳交换机都只跟它的上游邻居说:兄弟,你慢点,我这边某个优先级快满了。上游收到后,就暂停发送该优先级的报文。这就是反压。
我画个图你就明白了:
你看这个图。接收端处理不过来时,交换机2的某个优先级队列开始堆积。快到阈值了,交换机2就给交换机1发PFC暂停帧。交换机1收到后,暂停该优先级的发送。如果交换机1的队列也满了,它继续往上游发暂停帧。一直反压到发送端。
这就是逐跳反压。每一跳都只跟邻居说话,不跨级。好处是响应快,坏处是...嗯,后面会讲它的坑。
3.3 PFC暂停帧长什么样?
PFC暂停帧是一个MAC控制帧。我直接给你看格式:
PFC MAC控制帧格式:
+----------------+----------------+----------------+----------------+
| 目的MAC地址 | 源MAC地址 | 以太类型(0x8808)| MAC控制opcode |
| (6字节) | (6字节) | (2字节) | (2字节) 0x0101 |
+----------------+----------------+----------------+----------------+
| 优先级使能向量 | 优先级0暂停时间 | 优先级1暂停时间 | ... |
| (2字节) | (2字节) | (2字节) | |
+----------------+----------------+----------------+----------------+
| 优先级7暂停时间 | 保留 | FCS |
| (2字节) | (26字节) | (4字节) |
+----------------+----------------+----------------+----------------+
关键字段就两个:
- 优先级使能向量:告诉对端,我这次要暂停哪些优先级。每个bit对应一个优先级。
- 暂停时间:每个优先级独立设置暂停时长。单位是512比特时间。比如10Gbps下,一个单位约51.2纳秒。
暂停时间设为0,就是恢复发送。所以PFC可以精确控制每个优先级的暂停时长。
我的经验:暂停时间不要设太长。我见过有人设了65535,结果一个优先级被停了快1秒。对于RDMA来说,1秒的延迟简直是灾难。建议设100-500个时间单位,够用就行。
3.4 如何防止丢包?
PFC防止丢包的核心逻辑就一句话:在队列溢出之前,让上游停下来。
具体怎么做?每个交换机端口有8个优先级队列。每个队列有两个阈值:
| 阈值名称 | 触发条件 | 动作 |
|---|---|---|
| XOFF阈值 | 队列占用超过此阈值 | 发送PFC暂停帧给上游 |
| XON阈值 | 队列占用低于此阈值 | 发送PFC恢复帧(暂停时间=0) |
XOFF和XON之间有个差值,叫滞后(Hysteresis)。为什么要加滞后?
你想想看,如果没有滞后,队列在阈值附近抖动,就会频繁发送暂停/恢复帧。这会导致链路利用率下降。加个滞后,让队列多消化一些再恢复,能减少控制帧的数量。
我举个例子:
- 队列深度1000个cell,XOFF设800,XON设600
- 队列涨到801,触发XOFF,发暂停帧
- 上游停止发送,队列开始下降
- 队列降到599,触发XON,发恢复帧
- 上游恢复发送
这个过程中,队列最大占用801,远小于队列深度1000。所以不会丢包。
注意:XOFF阈值不能设得太高。要留出足够的余量,因为从发送暂停帧到上游真正停止发送,有链路延迟。这个延迟内,上游可能还在发数据。如果XOFF设成990,那这10个cell的余量可能不够,队列就溢出了。
3.5 我曾经踩过的坑
讲几个真实案例吧。
案例1:PFC风暴
有一次,某个数据中心部署RoCEv2,结果网络性能极差。我上去一看,PFC帧满天飞。怎么回事?
原来,某个交换机的XOFF阈值设得太低,队列稍微一波动就触发暂停。上游收到暂停后,队列下降,又触发XON。然后上游又开始发。结果就是频繁暂停-恢复,链路利用率不到50%。
解决方案:把XOFF阈值调高,同时加大滞后。让队列有足够的缓冲能力,减少PFC帧的发送频率。
案例2:死锁
这个更坑。两个交换机互相发PFC暂停帧,形成死锁。A停了B的优先级3,B停了A的优先级5。结果两个优先级都停了,谁也发不出去。
为什么会这样?因为流量拓扑是环形的,或者有多个路径。PFC只关心优先级,不关心路径。一旦形成环路,就可能死锁。
解决方案:要么用DCQCN这种端到端拥塞控制替代PFC,要么在拓扑设计上避免环路。我个人更倾向于DCQCN,但那是另一个话题了。
3.6 PFC的优缺点
说了这么多,总结一下:
| 优点 | 缺点 |
|---|---|
| 逐跳响应快,延迟低 | 可能引发PFC风暴 |
| 粒度细,只暂停特定优先级 | 可能造成死锁 |
| 实现简单,硬件成本低 | 公平性问题:一个流捣乱,整个优先级遭殃 |
| 兼容现有以太网 | 需要精细调参,否则性能差 |
说白了,PFC是个好东西,但用不好就是双刃剑。我建议你在部署前,先做充分的测试。特别是XOFF阈值、暂停时间这些参数,要根据你的流量模型来调。
核心要点回顾:
- PFC是逐跳的,不是端到端的
- 每个优先级独立做流控
- XOFF触发暂停,XON触发恢复
- 阈值设置要留余量,防止溢出
- 避免PFC风暴和死锁
好了,PFC的原理就讲到这里。记住,它只是无损网络的基础设施之一。真正要玩转无损网络,还得结合ECN、DCQCN这些机制。后面我们会慢慢展开。
公众号:蓝海资料掘金营,微信deep3321