引言

Frame Preemption(帧抢占)机制,主要用于 TSN(Time-Sensitive Networking):让高优先级帧不必等一个正在发送的低优先级大帧发完。

为什么需要 Qbu?

普通以太网一旦开始发送一个帧,通常不能中途停下来。

假设端口是 100 Mbps,正在发送一个 1500B 的低优先级帧,此时一个高优先级控制报文到达:

时间 --------------------------------->
 
低优先级:
|========== 1500B Frame ==========|
 
高优先级:
        ↑ 到达
        |--------------------------> 必须等待

1500B 在 100 Mbps 链路上的序列化时间大约:

1500 × 8 / 100 Mbps ≈ 120 μs

再加上,帧前导码(Preamble),帧间隙(InterFrameGap,IFG), 实际阻塞时间还会略高。

对于工业控制、车载网络等 TSN 场景,100 多 μs 的额外延迟可能很重要。

802.1Qbu 的核心思想就是:允许高优先级帧“打断”低优先级帧。


铺垫

帧前导码

理解 Ethernet 的前导码(Preamble),对后面理解 802.1Qbu/802.3br 的 SMD 和分片很重要。

标准以太网帧在链路上传输时,MAC 帧前面实际上还有 Preamble + SFD

┌──────────────┬─────┬─────────────┬─────────┬──────┐
│ Preamble 7B  │ SFD │ Ethernet    │ Payload │ FCS  │
│              │ 1B  │ Header 14B  │         │ 4B   │
└──────────────┴─────┴─────────────┴─────────┴──────┘

通常说的 Ethernet Frame 是从 Destination MAC 开始的,因此 Preamble 和 SFD 一般不算 Ethernet MAC Frame 本身的一部分。

Preamble 有 7 字节,经典表示是:

55 55 55 55 55 55 55

二进制看起来就是不断交替的 0 和 1:

01010101 01010101 01010101 ...

它的主要作用是让接收端知道: 有帧要来了 。早期 Ethernet 接收电路需要利用这一串规律变化的信号进行同步。现代 PHY 实现细节更复杂,但协议层面仍保留了这个结构。

Preamble 后面紧跟一个 SFD(Start Frame Delimiter,帧起始定界符)。 SFD 的意义可以理解为: “同步阶段结束,真正的 MAC 帧马上开始。” 经典表示: D5

所以经常看到:

55 55 55 55 55 55 55 D5
└──── Preamble ─────┘ ↑
                     SFD

帧间隙

了解 Qbu,不需要了解帧间隙。只是它和帧前导比较”近”,所以这里顺带介绍下。现实世界可能复杂的多,我也不知道。

帧间隙(Inter-Packet Gap / Interframe Gap,IPG/IFG)是以太网上两个连续发送的帧之间必须保留的一段空闲时间。

它和刚才讲的 Preamble/SFD 连起来看:

时间方向 ─────────────────────────────────────────────→
 
        Frame 1                          Frame 2
┌────────┬─────┬───────────┬─────┐    ┌────────┬─────┬──────
│Preamble│ SFD │ MAC Frame │ FCS │    │Preamble│ SFD │ ...
└────────┴─────┴───────────┴─────┘    └────────┴─────┴──────
                                  │    │
                                  └────┘

                                   IPG

也就是说,一个帧发送完 FCS 后,发送端不能马上发送下一个 Preamble,中间需要留出 IPG。

经典 Ethernet 的标称帧间隙是 96 bit times,也就是发送 12 个字节的时间。 最初的 Ethernet 设计里,这段时间给接收端提供从上一帧恢复、准备接收下一帧的机会。从现在理解协议的角度,更重要的是把它看成 Ethernet 链路的固定开销之一。

人也一样。连续的工作间,需要插入 Gap。Gap 是生活的一部分。

IPv4 分片

从分片角度来说, 802.1Qbu 是在二层分片, IP Fragmentation 是在三层分片。虽然分片的目的不同,但是它们还有有些相似之处的。所以,本节也简单介绍下 IPv4。

网络分层处理。底层的每一种物理网络,能够承载的数据单元大小却不一样。三层不关心底层情况,只需要知道最多能承载多大的 IP 包就行。MTU 来描述这种能力边界。

一个 IP 数据包太大,超过 MTU 时,需要把它拆成多个较小的 IP 包传输,到目的端再重新拼起来。

目的端重组的时候,怎么知道这些分片来自同一个 IP 数据包呢?(后面我们看 Qbu 分片的时候,要始终考虑这个问题)

IPv4 Header 中有几个关键字段:

  • Identification用于关联分片。同一个原始 IP 包拆出来的分片通常具有相同的 Identification。
  • MF(More Fragments)表示后面还有没有分片
  • Fragment Offset(片偏移)表示当前分片的数据原本位于原始 IP 数据的什么位置。一个容易踩坑的地方是:它的单位不是 1 字节,而是 8 字节。
  • DF Flags = Don’t Fragment(禁止分片)

所以判断规则非常简单:

MFFragment Offset含义
00没有分片
10第一个分片
1> 0中间分片
0> 0最后一个分片

只要 MF = 1 或者 Fragment Offset != 0,这个包就是一个分片。

IPv6 的分片规则和 IPv4 又不同了,这里不再赘述。

Qbu 介绍

802.1Qbu 主要从桥接/TSN 的角度定义 Frame Preemption,例如哪些 Traffic Class 可以配置成 Express、哪些可以配置成 Preemptable。

真正涉及 MAC 层如何把帧暂停、形成 fragment、发送以及重新组合的机制,则和 IEEE 802.3br 密切相关。

下面两节,分别介绍这两部分。

Express(不可被抢占) 和 Preemptable(可被抢占) 队列

我们前面提到,高优先级的帧,可以打断低优先级的帧发送。

内部实现中,将高优先级的帧放入 Express 队列,将低优先级的帧放入 Preemptable 队列。Express 的包,可以抢占 Preemtable 包发送。

帧的优先级

首先,怎么判断一个帧的优先级?

一个帧的优先级,通常不是根据帧的内容、长度来判断,而是看二层帧中有没有携带 QoS 优先级字段。以最常见的以太网来说,核心就是 IEEE 802.1Q VLAN Tag 里的 PCP 字段。

| Dst MAC | Src MAC | 802.1Q Tag | EtherType | Payload | FCS |


                 ┌──────────────────┐
                 │ PCP │ DEI │ VID  │
                 │ 3bit│ 1bit│12bit │
                 └──────────────────┘

其中 PCP(Priority Code Point) 就是帧的二层优先级标记。因为 PCP 有 3 bit,所以范围是:

PCP = 0 ~ 7

一般来说数值越高,代表的业务优先级越高,但有一个重要细节:PCP 值并不简单等于交换机实际转发优先级。交换机通常会把 PCP 映射到内部 Traffic Class / Queue,再根据队列调度策略决定谁先发。

例如可能配置成:

PCP 0 ──→ Queue 1
PCP 1 ──→ Queue 0
PCP 2 ──→ Queue 0
PCP 3 ──→ Queue 2
PCP 4 ──→ Queue 3
PCP 5 ──→ Queue 4
PCP 6 ──→ Queue 5
PCP 7 ──→ Queue 5

所以更准确地说:PCP 是帧携带的“优先级标记”;真正决定帧何时发送的是设备的 QoS 分类、队列映射和调度机制。

除了在二层,标记包的优先级,我们还可以使用 IP 的 DSCP 标记优先级。

Express 和 Preemptable 队列

支持 Qbu 的设备中,网卡队列分为两类,Express 队列和 preemptable 队列。Express 队列包到了时,可以打断 preemptable 队列中的包发送。

              收到 Ethernet Frame


               分类 / 优先级识别

              例如读取 VLAN PCP


             映射到 Traffic Class


                  TX Queue

              ┌────────┴────────┐
              ▼                 ▼
           Express          Preemptable
              │                 │
              └──────┬──────────┘

              MAC Merge Sublayer


                    PHY

MAC Merge Sublayer(MAC Merge 子层)可以理解为 802.3br / 802.1Qbu 帧抢占机制中的“交通调度 + 分片/重组层”。它位于 MAC 与 PHY 之间附近的逻辑位置,核心任务是把两路流量——Express 和 Preemptable 合并到同一条物理链路上发送。

Preemptable Frame(可抢占帧) 和 fragment(分段)

Preemptable Frame 与普通帧的区别

Preemptable queue 中发出的包,经过 MAC Merge Sublayer 是 Preemptable Frame。

Preemptable Frame 可以转换成一个或多个 mPacket / fragment。

Preemptable Frame 和 普通的 Frame 是不同的,即使它从头到尾都没有被抢占。但是,因为 Preemptable Frame 不知道什么时候被抢占,所以它必须和普通的 Frame 不同。否则,被抢占前,已经发出去的内容,就没有办法区分是一个帧损坏了,还是要给帧的分段。它和 IP 分片的不同是,Preemptable Frame 是随时可能被抢占而分片,但是 IP 分片是发送前就根据 MTU 决定是否要分片了

和普通帧最核心的区别,在于开头的 SMD(Start mPacket Delimiter)。

可以理解为:

普通 / Express Frame:
 
Preamble       SFD       MAC Frame
   │            │
   ▼            ▼
┌─────────┬─────────┬──────────────────────────────┐
│  7 Byte │  1 Byte │ DA | SA | ... | Payload|FCS │
└─────────┴─────────┴──────────────────────────────┘

而一个没有被抢占的 Preemptable Frame,经过 MAC Merge 后:

Preemptable Frame(未发生抢占):
 
Preamble       SMD-S       MAC Frame
   │            │
   ▼            ▼
┌─────────┬─────────┬──────────────────────────────┐
│  6 Byte │  2 Byte │ DA | SA | ... | Payload|FCS │
└─────────┴─────────┴──────────────────────────────┘

至于 SMD-S 这个字节的具体内容是什么,见下一节。

SMD-S 和 SMD-C

SMD = Start mPacket Delimiter

其中有两大类:

类型含义用途
SMD-SStart mPacket Delimiter - Start表示一个新的 Preemptable Frame 的第一个 mPacket 开始
SMD-CStart mPacket Delimiter - Continue表示之前被抢占的 Preemptable Frame 的后续 mPacket 开始

假设一个 Preemptable Frame 被抢占 两次:

原始 Preemptable Frame A:
 
┌─────────────────────────────────────────────────────┐
│                    Frame A                          │
└─────────────────────────────────────────────────────┘

MAC Merge 后可能变成:

时间 ───────────────────────────────────────────────→
 
 
 SMD-S

┌──────┬──────────────┐
│SMD-S │ Fragment #1  │
└──────┴──────────────┘

            │ 被抢占

 
       ┌───────────────┐
       │ Express Frame │
       └───────────────┘
 
             SMD-C

       ┌──────┬──────────────┐
       │SMD-C │ Fragment #2  │
       └──────┴──────────────┘

                    │ 再次被抢占

 
               ┌───────────────┐
               │ Express Frame │
               └───────────────┘
 
                       SMD-C

                 ┌──────┬──────────────┐
                 │SMD-C │ Fragment #3  │
                 └──────┴──────────────┘

和 IPv4 分片一样,我们需要考虑这几个问题:1) Preemptable Frame 有没有分片;2) 分片的话,该分片在原始报文的什么位置; 3) 考虑不同分片是不是同一个帧的,不同帧的分片不能重组在一起;

这些问题,都是通过 SMD-S 和 SMD-C 编码的值决定的。

SMD-S 和 SMD-C 用了 八位帧前导的最后两位

核心规律是:报文编号 S0→S1→S2→S3;同一报文的 continuation 使用对应的 C0→C1→C2→C3;F 始终按 F0→F1→F2→F3→F0 循环。

第一个报文:S0 / C0

SMD-S0SMD-C0 + F0SMD-C0 + F1SMD-C0 + F2SMD-C0 + F3SMD-C0 + F0
Byte70x550x610x610x610x610x61
Byte80xE60xE60x4C0x7F0xB30xE6

第二个报文:S1 / C1

SMD-S1SMD-C1 + F0SMD-C1 + F1SMD-C1 + F2SMD-C1 + F3SMD-C1 + F0
Byte70x550x520x520x520x520x52
Byte80x4C0xE60x4C0x7F0xB30xE6

第三个报文:S2 / C2

SMD-S2SMD-C2 + F0SMD-C2 + F1SMD-C2 + F2SMD-C2 + F3SMD-C2 + F0
Byte70x550x9E0x9E0x9E0x9E0x9E
Byte80x7F0xE60x4C0x7F0xB30xE6

第四个报文:S3 / C3

SMD-S3SMD-C3 + F0SMD-C3 + F1SMD-C3 + F2SMD-C3 + F3SMD-C3 + F0
Byte70x550x2A0x2A0x2A0x2A0x2A
Byte80xB30xE60x4C0x7F0xB30xE6

比如:SMD-C2 + F1 —— 第三个报文的 continuation,并且 Fragment Count = 1。

SMD-S0、S1、S2、S3 的选择由一个 modulo-4 的 frame_count 决定。 IEEE 802.3br 明确说明,Preemptable frame 的 SMD 携带 frame count,而 frame count 是模 4 计数。所以,我们可以看到 S 和 F 都是以 4 为周期进行重复的。

分片帧的校验和

接收端要检查这一段传输有没有出错,所以每个 fragment 都需要检验和。(我怎么感觉屁事多呢,直接重组完,用最后的 FCS 检查就好了,校验失败,drop 就是了)

MAC Merge 给非最后 fragment加一个 mCRC:

First Fragment:
 
Preamble | SMD-S | DA | SA | Type | A | B | mCRC
                                             4B

Express Frame 发完之后:

Continuation / Final Fragment:
Preamble | SMD-C | Frag Count | C | D | E | FCS

                                      原始帧 FCS

之前,我了解了下 Ethernet-FCS 的校验和。

但是,mCRC 怎么计算的,不想查了,费劲。