流控是以太网的一项基本功能,可以防止在端口拥塞的情况下出现丢帧。在深入分析之前,先看一个简单的应用场景:
端口A和B接收报文,端口C向外转发报文。如果端口A和B的收包速率之和大于端口C的带宽,那么部分报文就会缓存在设备内部的报文buffer中。当buffer的占用率达到一定程度时,端口A和B就会向外发送PAUSE帧,通知对端暂停发送一段时间。PAUSE帧只能阻止对端发送普通的数据帧,不能阻止发送MAC控制帧。
以上的描述有个先决条件,那就是端口A和B工作在全双工模式下,并且使能了流控功能。另一方面,我们也一厢情愿地认为对端可以识别PAUSE帧,并可以做出适当的响应。换句话说,对端的端口也要开启流控功能。
需要注意的是,有的以太网设备只能对PAUSE帧做出响应,但是并不能发送PAUSE帧。
流控的基本原理不难理解,比较容易忽视的一点是--端口收到PAUSE帧之后,停止发送报文多长时间?其实,PAUSE帧中携带了时间参数。收到PAUSE帧的设备通过简单的解析,就可以确定停止发送的时长。对端设备出现拥塞的通常情况下,本端端口通常会连续收到多个PAUSE帧。只要对端设备的拥塞状态没有解除,相关的端口就会一直发送PAUSE.
PAUSE帧的结构
PAUSE帧的帧长为64字节,结构非常简单。如下所示:
PAUSE帧的目的MAC地址是保留的MAC地址01-80-C2-00-00-01(MAC Control的PAUSE帧使用),源MAC则是发送PAUSE帧的设备的MAC地址。
Length/Type域是十六进制数8808.
MAC Control Opcode域的值是0x0001.其实,PAUSE帧是MAC控制帧的一种,其他类型的MAC控制帧使用不同的opcode值,此处不做详细说明。后面会谈到和PAUSE类似的PFC帧,PFC帧中该域的取值是0x0101.
MAC Control Parameters域需要根据MAC Control Opcode的类型来解析。对于PAUSE帧而言,该域是个2字节的无符号数,取值范围是0~65535.该域的时间单位是pause_quanta,每个pause_quanta相当于512比特时间。
流控的自协商
现实中,大多数厂商的以太网交换机都有流控开关命令。部分厂商的设备可以在自协商功能中对流控进行协商,这种行为有IEEE标准作为依据。
在自协商的信息中,有两个流控的比特位,即PAUSE和ASM_DIR,分别表示Symmetric PAUSE和Asymmetric PAUSE.Symmetric PAUSE表示既可以发送又可以接收PAUSE帧,而Asymmetric PAUSE表示只能发送或只能接收PAUSE帧。
IEEE 802.3标准的28B.3中,描述了这两个比特位的解析方式。简单来讲,如果双方发送的协商信息中PAUSE位都是1,那么双方都能发送和接收PAUSE帧。如果有一方的PAUSE位是0,那么就需要根据ASM_DIR位的值结合PAUSE位的值来具体分析。
半双工模式如何实现流控?
在本文开头儿的地方说过,端口A和B要工作在全双工模式下,这是有原因的。如果端口工作在半双工模式下,那么PAUSE帧很可能和对端发送过来的报文产生冲突,对端收不到完好的PAUSE帧,也就无法实现PAUSE的功能。
对于半双工模式的问题,业界常见的解决方式是"back pressure"或者"jamming"机制。对于这两种机制,笔者都没有找到相应的标准,或许本来指的就是同一种机制。半双工模式下,端口向外发送一些信号来占用链路,对端也就没有机会发送报文。这样,可以间接达到和流控类似的效果。
基于优先级的流控(PFC)
以太网的数据转发是尽力而为的,并不能保证传输过程中不丢包。像FTP这样的上层协议,通过自身的确认机制来保证数据的完整性,一旦发现报文丢失,可以要求对端重传。正因为如此,以太网的这种尽力而为的转发方式,长期以来也没有遇到过太大的问题。
IEEE 802.3x流控虽然可以预防丢包,但是有一个不容忽视的问题。PAUSE帧会导致一条链路上的所有报文停止发送,在服务质量要求较高的网络中,这显然是不能接受的。由于这个原因,业界一度出现过对流控的反对声音。IEEE 802.1Qbb标准解决了这个问题。
IEEE 802.1Qbb的核心思想是,针对同一链路上不同优先级的流量,单独发送PASUSE帧。当某一优先级的业务发生拥塞时,只让该类报文暂停发送,而其他类型的业务不受影响。IEEE 802.1Qbb可以针对特定优先级的流量实现流控功能,因此也被称为PFC(Priority-based Flow Control)。
FCoE技术将Fiber Channel的数据帧封装在以太网帧中进行传输,FCoE的一个基本要求就是不能丢包。PFC成功地满足了FCoE的需求,同时也不会对其他业务造成影响。