4、门控列表的结构:门控状态、时间间隔、循环计数

门控列表是 Qbv 调度的“灵魂”。说白了,它就是一张时间表,告诉交换机什么时候开门、什么时候关门、开多久、重复几次。我刚开始接触时觉得很简单,后来发现门控一致性验证出问题,十有八九都是这三个要素没配合好。

4.1 门控状态——开还是关?

每个门控条目里都有一个 门控状态(Gate State),它只有两个值:

  • 打开(Open):允许匹配流量通过。优先级队列的帧可以发送。
  • 关闭(Closed):阻塞所有帧。哪怕队列里有帧,也只能憋着等下一轮开门。

嗯,这里要注意:有些设备用 1 表示 Open,0 表示 Closed;但也有的厂家用位掩码来同时控制多个队列。我在项目中就见过一位工程师把掩码算反了,结果高优先级队列一直关门,低优先级反而跑通了——查了一下午。

状态值含义队列行为
1 (Open)门打开对应队列的数据可以发送
0 (Closed)门关闭队列数据被阻塞,延迟发送

4.2 时间间隔——每个状态持续多久

时间间隔(Time Interval)定义了当前门控状态保持多长时间,单位通常是纳秒(ns)。比如 50000ns 就是 50μs。你觉得这数值随便填就行?错了。

实际网络中,时间间隔必须精确到纳秒级,不能存在“间隙”或“重叠”。否则两个相邻条目之间会出现窗口对不齐,轻则丢帧,重则整个调度周期错乱。我曾经调试过一个工业以太网项目,现场老是出现保护报文超时,最后发现是门控列表里两个条目之间的间隔差了几十纳秒,导致门状态切换滞后。

下面是一个典型门控列表的代码片段,用类 C 语言表示:

// 门控列表条目结构
struct GateControlEntry {
    unsigned char  gateState;   // 0x01: Open, 0x00: Closed
    unsigned int   timeInterval; // 单位 ns
    unsigned short cycleCount;   // 循环次数,0 表示无限
};

// 示例:保护报文窗口
GateControlEntry gcl[] = {
    {0x01, 100000, 1},  // 开门 100μs,只执行一次
    {0x00, 200000, 1},  // 关门 200μs
    {0x01, 50000,  0},  // 无限循环,每 50μs 开门一次?
};

注意第三行 cycleCount = 0 表示“无限循环”时,这个条目会一直重复,直到调度停止。很多协议规定无限循环只能出现在最后一个条目,否则后续条目永远没机会执行。我见过有人把这写在了中间,结果调试仪表现场卡死。

4.3 循环计数——重复多少次?

循环计数(Cycle Count)控制当前门控条目重复执行的次数。常见的取值规则:

  • 正整数(如 1、2、5):该条目按时间间隔重复指定次数。
  • 0 或特定值:表示无限循环。
  • -1:某些芯片厂商用 -1 表示无限循环(比如 TI 的某款交换芯片)。

你想想看,如果不知道设备的具体定义,光看协议描述很容易踩坑。我建议在验证阶段先写一个小用例,把循环计数设成 1,然后在示波器上抓门控信号,确认时长是否正确,再逐渐增加循环次数。

循环计数取值含义典型设备
0无限循环802.1Qbv 标准推荐
1 ~ 65535重复 N 次多数交换机
-1无限循环(补码)部分老款 ASIC

关键点:一个门控列表中的循环计数通常只允许最后一个条目设为无限循环。前面的条目如果设成无限,调度器会永远停在那一条,整个周期就断了。

4.4 三元素如何组成完整的门控列表?

现在把三个元素拼起来。一个完整的门控列表由多个门控条目组成,每个条目包含门控状态 + 时间间隔 + 循环计数。调度器按照条目顺序执行,每个条目先持续执行 timeInterval × cycleCount 的时间(如果循环计数是无限则永久),然后切换到下一个条目,直到列表末尾再回到开头(如果最后一条不是无限循环)。

下面这张图可以帮你理清结构:

门控列表结构图 门控列表结构 门控状态 Open / Closed 时间间隔 50000 ns 循环计数 1 / 00 / 65535 门控列表条目 Open TimeInterval = 100000 CycleCount = 0 条目 2、条目 3 ... 多个条目组成完整调度周期 图:门控列表 = 一组 (门控状态 + 时间间隔 + 循环计数) 条目顺序执行

我个人习惯在验证时,先把循环计数全设为 1,然后按顺序抓一遍门控时间,确认每个条目的时长、状态切换点都跟预期一致。最后再改成最终的循环计数。

实用技巧:用 Wireshark 抓取 802.1Q 的 GateControl 报文,可以读出门控列表里的每个条目。但注意报文里的循环计数有时是编码后的,需要按厂商手册解码。

警告:门控列表中的时间间隔之和若超过调度周期长度,最后一个条目会被截断或溢出,导致下一个窗口提前开门。一定要保证 ∑(timeInterval × cycleCount) = 调度周期(无限循环条目除外)。

好了,这部分内容比较多,但搞懂这三项以后,门控一致性验证的核心就算拿下了。记住:门控状态决定能不能走,时间间隔决定走多久,循环计数决定重复几遍。三者缺一不可,顺序也不能乱。