返回学习路径

learn

Qbv 概念落地:交换机界面、tc-taprio 与标准对象对照

把 cycle time、base time、GCL、guard band、queueMaxSDU 对到真实 TSN 交换机配置字段和 Linux tc-taprio 命令,跨过“学完看不懂配置界面”的最后一公里。

第五章:时间感知调度落地配置IEEE 802.1QbvTAS18 分钟

first read

先抓住结论

把 cycle time、base time、GCL、guard band、queueMaxSDU 对到真实 TSN 交换机配置字段和 Linux tc-taprio 命令,跨过“学完看不懂配置界面”的最后一公里。

这节怎么读

先看学习目标和章节目录,再进入正文;后续核心概念会在这里直接暴露参数。

本节学习目标

  • 能把同一个 Qbv 概念在交换机界面、tc-taprio 和标准对象三处认出来。
  • 能读懂一条真实 tc-taprio 命令的每个字段。
  • 知道交换机界面的分子/分母 cycle time 和秒/纳秒 base time 对应标准里的什么。

本章目录

  1. 01GCL、cycle 与窗口:Qbv 的最小心智模型从 Gate Control List 的周期、base time、窗口和队列状态理解 Time-Aware Shaper。
  2. 02guard band 与路径接力:Qbv 真正难在端到端理解普通大帧跨窗、窗口余量、路径传播延迟和多跳接力如何影响 Qbv 可行性。
  3. 03base time 与 offset:窗口从什么时候开始才算对理解 Qbv 调度表里的 base time、cycle offset 和多设备窗口相位,避免每台设备都正确却端到端错位。
  4. 04调度可行性:标准定义机制,不替你求解排表理解 Qbv 真正困难的是多流、多跳、多约束下的可行排表,标准机制本身不会自动产生日程。
  5. 05流量模型与 flow set:排表前先把输入说清楚理解 Qbv 排表需要准确的周期、帧长、deadline、路径和优先级输入,flow set 描述不清会让调度结论失效。
  6. 06运行时更新与切换:新旧 GCL 混用会怎样出错理解 Qbv 配置变更时的 base time、版本一致性和回滚问题,避免多设备更新过程中出现短暂窗口错位。
  7. 07Qbv 调试信号:迟到时先看哪几类证据把 Qbv 失败拆成时间同步、队列映射、窗口相位、guard band、流量模型和设备执行几类证据,形成调试路径。
  8. 08Qbv 概念落地:交换机界面、tc-taprio 与标准对象对照把 cycle time、base time、GCL、guard band、queueMaxSDU 对到真实 TSN 交换机配置字段和 Linux tc-taprio 命令,跨过“学完看不懂配置界面”的最后一公里。
  9. 09动手:用 tc-taprio 配一张最小 GCL 并验证在 Linux 上用软件模式 tc-taprio 真正下发一张两窗口的 Gate Control List,并用 tc 计数和抓包验证它确实按时间开关。

解决什么问题

到这里,你已经知道 Qbv 的窗口为什么要有 cycle、base time、guard band,也知道 queueMaxSDU 为什么能保护窗口。但把这些概念变成真实配置时,会卡在一个很具体的地方:词对不上

课文说“周期”,交换机界面写“门控循环时间(分子/分母)”;课文说“门控表”,Linux 里是一行行 `sched-entry`;课文说“每队列最大帧”,设备页面叫“SDU-table”,标准里又叫 `queueMaxSDU`。同一个东西,三套名字。

这一节不引入任何新机制,只做一件事:把同一个 Qbv 概念,在交换机配置界面、Linux `tc-taprio`、IEEE 802.1Q 标准对象三个地方认出来。 跨过这一步,“懂 Qbv”才会变成“能配 Qbv”。

同一件事的三套说法

下面这张表是本节的核心。左边是本章一直在用的概念,右边是你在真实世界会遇到的三种写法。

概念(本章用语)交换机配置界面常见字段Linux `tc-taprio`IEEE 802.1Q 标准对象
周期 cycle time门控循环时间(分子/分母)`cycle-time`(纳秒);省略时为各 `sched-entry` 时长之和`AdminCycleTime`(Numerator/Denominator)
周期起点 base time循环开始基准时间(秒 + 纳秒)`base-time`(纳秒,基于 `clockid`)`AdminBaseTime`(PTPtime:seconds + nanoseconds)
门控表 GCLGCL 门控列表(每行:时长 + 各门开关)一串 `sched-entry S <gatemask> <interval>``AdminControlList`(GateState + TimeInterval)
某队列的门 开/关该流量类的 gate 位gate mask 里对应的一个 bit`gateStatesValue` 的一位
每队列最大帧流量类 N 最大 SDU(SDU-table)`max-sdu`(最多 16 个值的数组)`queueMaxSDU`
优先级→队列映射PCP / TC 映射表`num_tc` + `map` + `queues`Traffic Class Table
express / preemptable抢占使能`fp`(逐 TC)`framePreemptionStatusTable`

记住一个对应关系就够开路:界面里能配的每一项,`tc-taprio` 里几乎都有一个同义参数,标准里再有一个同义对象。 三者描述的是同一台设备的同一个调度行为。

读懂一条真实的 tc-taprio 命令

把抽象的表落到一条能跑的命令上。下面是一个 8 个流量类、带 `max-sdu` 的硬件 offload 配置(改写自 `tc-taprio(8)` 手册示例):

tc qdisc replace dev eth0 parent root handle 100 taprio \
    num_tc 8 \
    map 0 1 2 3 4 5 6 7 \
    queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
    max-sdu 0 0 0 0 0 200 0 0 \
    base-time 200 \
    sched-entry S 80 20000 \
    sched-entry S a0 20000 \
    sched-entry S 5f 60000 \
    flags 0x2

逐段拆开:

  • `num_tc 8` / `map ...` / `queues ...`:声明 8 个流量类,并定义“报文优先级 → 流量类 → 硬件队列”怎么映射。这对应界面里的 PCP/TC 映射表。
  • `base-time 200`:调度表在 `clockid` 的第 200 纳秒这个绝对时刻启动。即使这是个过去时刻,设备会自动加上整数倍 cycle,对齐到下一个周期边界再启动。
  • `sched-entry S <gatemask> <interval>`:这就是 GCL 的一行。`S` 是 SetGateStates;`interval` 是这一行持续多少纳秒;`gatemask` 是十六进制按位掩码,bit0 = TC0。
  • 三行算下来,cycle time = 20000 + 20000 + 60000 = 100us(没单独写 `cycle-time` 时,它就是各行之和)。
  • `max-sdu ... 200 ...`:第 5 个流量类(TC5)最大 SDU 限制为 200 字节,其余为 0(= 不额外限制,可到端口 MTU)。这正是 SW0 那张 SDU-table 的一行。
  • `flags 0x2`:整张表交给网卡硬件循环执行(full-offload);此时 `clockid` 要省略,因为硬件直接用 NIC 的 PTP 时钟。

把 gate mask 翻成人话:

sched-entrygatemask(hex)二进制这段时间哪些 TC 的门开着
`S 80 20000``80``1000 0000`只有 TC7
`S a0 20000``a0``1010 0000`TC7 + TC5
`S 5f 60000``5f``0101 1111`TC0–TC4 + TC6

把交换机界面的字段对回来

现在反过来,拿一台真实交换机的 Qbv 配置页(以本课常用的 SW0 界面为例)对照标准与 `tc-taprio`:

SW0 界面字段示例值它其实是对应到 tc-taprio
门控循环时间(分子 / 分母)2 / 3`AdminCycleTime` 的有理数 = 2/3 秒`cycle-time 666666667`(≈ 666.67ms,纳秒整数)
循环开始基准时间(秒 / 纳秒)4 / 23`AdminBaseTime` = 4s + 23ns 这个绝对时刻`base-time 4000000023`
流量类 0..7 最大 SDU(SDU-table 一行)2,0,0,0,0,0,3,…该端口的 `queueMaxSDU``max-sdu 2 0 0 0 0 0 3 ...`

两个容易困惑的设计点,在这里一次说清:

  • 为什么 cycle time 用分子/分母? 标准把 `AdminCycleTime` 定义成有理数(分子÷分母,单位秒),是为了精确表示 1/3、1/1500 这类无限小数周期,避免各设备用浮点各自取整、长期累积漂移。Linux `tc-taprio` 不暴露有理数,而是直接收整数纳秒——所以界面上的 2/3 秒,到 `tc` 里要先算成 `666666667` 纳秒。
  • 为什么 base time 拆成秒 + 纳秒? 这是 PTP 的 `PTPtime` 结构(秒 + 纳秒两段),因为它表达的是一个基于共同时间的绝对时刻,不是“开机后多久”。`tc-taprio` 把这两段合成一个纳秒整数,语义完全一样。

顺带一提:SW0 的 SDU-table 里出现的 2、3、4 这类字节值,小于以太网最小载荷 46B,是测试占位值;真实部署应填该队列允许的最大业务帧长,例如 1500。

一个判断练习

下面这条命令想配一个 cycle = 100us、关键流量(TC6)独占前 30us 的调度,但它有三个错误。试着在看答案前找出来:

tc qdisc replace dev eth0 parent root handle 100 taprio \
    num_tc 8 map 0 1 2 3 4 5 6 7 queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
    base-time 0 \
    sched-entry S 6 30000 \
    sched-entry S 255 80000 \
    clockid CLOCK_REALTIME

问题:

  1. 1gate mask 写错了。 想让 TC6 独占,掩码应是 `40`(`0100 0000`),而不是 `6`(`0000 0110` = TC1+TC2)。第二行想“全开”应是 `ff`,而不是十进制 `255`——`tc` 按十六进制解析 gatemask,`255` 会被读成 `0x255`,超出 8 个 TC 的范围。
  2. 2cycle 不自洽。 30000 + 80000 = 110us,不是声称的 100us。各 `sched-entry` 之和就是 cycle,声称值必须和它对上。
  3. 3时钟用错。 `CLOCK_REALTIME` 会跳变(NTP 调整、闰秒),TSN 调度必须用 `CLOCK_TAI` 且经 gPTP 同步;否则 `base-time 0` 这个绝对时刻在各设备根本不一致。

能一眼看出这三类错(掩码按位、cycle 自洽、时钟来源),你就具备了审一份真实 Qbv 配置的最低能力。

带来了什么新问题

这张对照表能让你认出字段,但它只是起点,不能替代具体设备手册。不同厂商对同一个概念的命名、单位和默认值并不统一:有的 `queueMaxSDU` 按 L2 payload 计,有的把头部也算进去;有的界面用纳秒,有的用 tick 或时隙数;offload 能力、支持的 `sched-entry` 条数上限也各不相同。

所以正确的用法是:用这张表把概念锚定到“大概是哪个字段”,再到目标设备手册里核对单位、范围和默认值。下一节就把概念真正下发到一块网卡上,让你看到“配置生效”到底长什么样。

检查点

  • 给定 `sched-entry S c0 50000`,这一段有哪些 TC 的门是开的?这段持续多久?
  • SW0 界面把 cycle time 写成分子/分母 `1 / 8000`,换算成 `tc-taprio` 的 `cycle-time` 是多少纳秒?
  • 一份配置 `base-time` 写了一个很大的未来时刻,且设备未做 PTP 同步。它能开始调度吗?会有什么风险?

掌握检查

读完本节后,先用下面这些问题校准自己,而不是只确认“看过了”。

  1. 1给定一条 tc-taprio 命令,能说出 cycle time、各窗口和每个 gate mask 开放了哪些 TC。
  2. 2能把交换机 SDU-table 的一行对到 tc-taprio 的 max-sdu 数组。

next steps

读完这一页,下一步可以这样走。