Linux TC

linux 2024-07-22 248 次浏览 次点赞


TC

I. 1. 名称

tc - 显示/操作流量控制(traffic control)设置

II. 2. 语法

tc  [ OPTIONS ] qdisc [ add | change | replace | link | delete ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] [ ingress_block BLOCK_INDEX ]
[ egress_block BLOCK_INDEX ] qdisc [ qdisc specific parameters ]

tc [ OPTIONS ] class [ add | change | replace | delete ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]

tc [ OPTIONS ] filter [ add | change | replace | delete | get ] dev DEV [ parent qdisc-id | root ] [ handle filter-id ] protocol protocol prio priority
filtertype [ filtertype specific parameters ] flowid flow-id

tc  [  OPTIONS ] filter [ add | change | replace | delete | get ] block BLOCK_INDEX [ handle filter-id ] protocol protocol prio priority filtertype [filtertype specific parameters ] flowid flow-id

tc [ OPTIONS ] chain [ add | delete | get ] dev DEV [ parent qdisc-id | root ] filtertype [ filtertype specific parameters ]

tc [ OPTIONS ] chain [ add | delete | get ] block BLOCK_INDEX filtertype [ filtertype specific parameters ]

tc [ OPTIONS ] [ FORMAT ] qdisc { show | list } [ dev DEV ] [ root | ingress | handle QHANDLE | parent CLASSID ] [ invisible ]

tc [ OPTIONS ] [ FORMAT ] class show dev DEV

tc [ OPTIONS ] filter show dev DEV

tc [ OPTIONS ] filter show block BLOCK_INDEX

tc [ OPTIONS ] chain show dev DEV

tc [ OPTIONS ] chain show block BLOCK_INDEX

tc [ OPTIONS ] monitor [ file FILENAME ]

III. 3. 选项

OPTIONS := { [ -force ] -b[atch] [ filename ] | [ -n[etns] name ] | [ -N[umeric] ] | [ -nm | -nam[es] ] | [ { -cf | -c[onf]  }  [  filename  ]  ]  [-t[imestamp] ] | [ -t[short] | [ -o[neline] ] }
css
Copy code
FORMAT := { -s[tatistics] | -d[etails] | -r[aw] | -i[ec] | -g[raph] | -j[json] | -p[retty] | -col[or] }

IV. 4. 描述

tc 用于配置 Linux 内核中的流量控制。流量控制包括以下几个方面:

整形(SHAPING)
当流量被整形时,其传输速率会受到控制。整形不仅仅是降低可用带宽,它还用于平滑流量的突发,以改善网络行为。整形发生在出口端(egress)。

调度(SCHEDULING)
通过调度数据包的传输,可以改善需要交互的流量的表现,同时保证大流量传输的带宽。重新排序也称为优先级设置,仅在出口端发生。

检测(POLICING)
整形处理的是传输中的流量,而检测处理的是到达的流量。因此,检测发生在入口端(ingress)。

丢弃(DROPPING)
超出设定带宽的流量也可能会被立即丢弃,这在入口端和出口端都会发生。

流量处理由三种对象控制:qdiscs、classes 和 filters。

4.1. QDISCS

qdisc 是 “队列规则 (queueing disciplin)” 的简称,对于理解流量控制至关重要。每当内核需要将数据包发送到接口时,它会被排入配置好的 qdisc 中。紧接着,内核会尽可能多地从 qdisc 中取出数据包,交给网络适配器驱动。

简单的 QDISC 是 “pfifo”,它不进行任何处理,仅仅是一个纯粹的先进先出(FIFO)队列。它在网络接口暂时无法处理流量时,会存储这些流量。

4.2. CLASSES

一些 qdiscs 可以包含 classes,这些 classes 进一步包含 qdiscs——流量可能会被排入这些内部的 qdiscs 中。当内核尝试从这样的 classful qdisc 中取出数据包时,数据包可能来自任何 class。qdisc 可能例如通过尝试从某些 classes 中先取出数据包来优先处理某些类型的流量。

4.3. FILTERS

过滤器用于 classful qdisc 来确定数据包将被排入哪个 class。当流量到达一个具有子类的 class 时,它需要被分类。可以使用多种方法来实现分类,其中之一就是过滤器。所有附加到 class 的过滤器都会被调用,直到其中一个返回判决。如果没有做出判决,可能会有其他标准可用。这在不同的 qdisc 中有所不同。

需要注意的是,过滤器存在于 qdiscs 中——它们不是事件的控制者。

可用的过滤器包括:

  • basic: 基于 ematch 表达式过滤数据包。详见 tc-ematch(8)
  • bpf: 使用 (e)BPF 过滤数据包,详见 tc-bpf(8)
  • cgroup: 基于其进程的控制组过滤数据包。详见 tc-cgroup(8)
  • flow, flower: 基于流量的分类器,按流量(通过可选择的键识别)过滤数据包。详见 tc-flow(8)tc-flower(8)
  • fw: 基于 fwmark 过滤。将 fwmark 值直接映射到流量类。详见 tc-fw(8)
  • route: 基于路由表过滤数据包。详见 tc-route(8)
  • rsvp: 匹配资源预留协议(RSVP)数据包。
  • tcindex: 基于流量控制索引过滤数据包。详见 tc-tcindex(8)
  • u32: 在任意数据包数据上进行通用过滤,辅助以抽象常见操作的语法。详见 tc-u32(8)
  • matchall: 匹配每个数据包的流量控制过滤器。详见 tc-matchall(8)

4.4. QEVENTS

Qdiscs 可以在 qdisc 中发生某些感兴趣的事件时调用用户配置的操作。每个 qevent 可以是未使用的,或者附加一个 block。然后将过滤器附加到该 block,使用 “tc block BLOCK_IDX” 语法。当与附件点相关的 qevent 发生时,将执行该 block。例如,数据包可以被丢弃或延迟等,具体取决于 qdisc 和相关的 qevent。

示例:

tc qdisc add dev eth0 root handle 1: red limit 500K avpkt 1K \
   qevent early_drop block 10
tc filter add block 10 matchall action mirred egress mirror dev eth1

4.5. 无类 QDISCS

无类 qdiscs 包括:

  • choke: CHOKe(选择并保留响应流,选择并丢弃非响应流)是一种无类 qdisc,旨在识别并惩罚那些垄断队列的流量。CHOKe 是 RED 的一种变体,配置方式与 RED 类似。
  • codel: CoDel(发音为 "coddle")是一种自适应的 “无旋钮” 活跃队列管理算法(AQM),旨在解决 RED 及其变体的一些缺陷。它通过动态调整队列的丢弃概率来减少队列延迟和波动。
  • [p|b]fifo: 最简单的 qdisc,纯粹的先进先出(FIFO)行为。按数据包或字节限制队列长度。例如,pfifobfifo 分别表示基于数据包和字节的 FIFO 队列。
  • fq: Fair Queue Scheduler 实现 TCP 节流,并扩展到每个 qdisc 的数百万个并发流。它通过将流量公平地分配给所有流,避免了流量集中在少数流上,确保了多流环境中的公平性。
  • fq_codel: Fair Queuing Controlled Delay 是一种将公平排队与 CoDel AQM 方案结合的队列规则。FQ_Codel 使用随机模型将传入的数据包分类到不同的流中,为每个流提供公平的带宽份额。每个流的排队由 CoDel 规则管理,避免了流内的重新排序,因为 CoDel 内部使用 FIFO 队列。
  • fq_pie: FQ-PIE(带有比例积分控制器增强的流量排队)将 Flow Queuing 与 PIE AQM 方案结合。FQ-PIE 使用 Jenkins 哈希函数将传入的数据包分类到不同的流中,为所有流提供公平的带宽份额。每个流由 PIE 算法管理,旨在减少延迟和队列积压。
  • gred: Generalized Random Early Detection 将多个 RED 队列组合以实现多个丢弃优先级。这对于实现保证转发(如 RFC 2597)是必需的。通过使用多个队列,可以根据流量类型进行更精细的控制。
  • hhf: Heavy-Hitter Filter 区分小流和重流。其目标是捕捉重流,并将其移动到优先级较低的队列中,从而避免批量流量对关键流量的延迟影响。
  • ingress: 这是一个特殊的 qdisc,专门用于入口流量控制。它允许在数据包到达接口之前进行流量整形和处理。
  • mqprio: Multiqueue Priority Qdisc 是一种简单的队列规则,它允许使用优先级和可配置的优先级到流量类别映射,将流量流分配到硬件队列范围。这里的流量类别是指一组连续的 qdisc 类别,1:1 映射到一组硬件暴露的队列。
  • multiq: Multiqueue 是一种针对具有多个 Tx 队列的设备优化的 qdisc。它被添加用于硬件希望避免头部阻塞的情况。它将循环遍历各个带宽,并在出队数据包之前验证与带宽相关联的硬件队列是否未停止。
  • netem: Network Emulator 是 Linux 流量控制设施的增强功能,它允许向来自选定网络接口的数据包添加延迟、丢包、重复和其他特性。
  • pfifo_fast: 适用于 “Advanced Router” 启用内核的标准 qdisc。包括一个三带队列,它尊重服务类型标志以及可能分配给数据包的优先级。
  • pie: Proportional Integral controller-Enhanced (PIE) 是一种控制理论的活跃队列管理方案。它基于比例积分控制器,但旨在控制延迟。
  • red: Random Early Detection 通过在接近配置的带宽分配时随机丢弃数据包来模拟物理拥塞。非常适合带宽非常大的应用。
  • rr: Round-Robin qdisc 支持多队列网络设备。自 Linux 2.6.27 内核版本起被移除。
  • sfb: Stochastic Fair Blue 是一种基于数据包丢失和链路利用历史的无类 qdisc,旨在管理拥塞,同时尝试防止非响应流(即不对拥塞标记或丢包做出反应的流)影响响应流的性能。与 RED 不同,BLUE 尝试自动确定理想的标记概率,而不需要配置标记概率。
  • sfq: Stochastic Fairness Queueing 重新排序排队的流量,以便每个 “会话” 轮流发送数据包。
  • tbf: Token Bucket Filter 适合将流量减速到精确配置的速率。对大带宽具有良好的扩展性。

4.6. 配置无类 QDISCS

在没有类 qdiscs 的情况下,无类 qdiscs 只能附加在设备的根节点上。完整的语法为:

tc qdisc add dev DEV root QDISC QDISC-PARAMETERS

要删除,请执行:

tc qdisc del dev DEV root

在没有配置 qdisc 的情况下,pfifo_fast qdisc 是自动默认的。

4.7. 类别 QDISCS

类别 qdiscs 包括:

  • ATM
    将流映射到基础异步传输模式设备的虚拟电路中。
  • CBQ
    基于类别的排队实现了丰富的链路共享层次结构。它包含了形状元素和优先级功能。形状通过基于平均数据包大小和基础链路带宽的链路空闲时间计算进行。对于某些接口,带宽可能不明确。
  • DRR
    缺额轮询调度器是对随机公平排队(SFQ)的更灵活的替代方案。与 SFQ 不同,它没有内置队列——你需要添加类别,然后设置过滤器以相应地分类数据包。这对于使用具有不同设置的 RED qdisc 来处理特定流量可能很有用。没有默认类别——如果数据包无法分类,则会被丢弃。
  • DSMARK
    根据 TOS 字段对数据包进行分类,根据分类更改数据包的 TOS 字段。
  • ETS
    ETS qdisc 是一个合并了 PRIO 和 DRR qdiscs 功能的调度程序。ETS 使配置一组严格和带宽共享的带宽变得简单,以实现 802.1Qaz 中描述的传输选择。
  • HFSC
    分层公平服务曲线为叶类别提供精确的带宽和延迟分配,并公平分配多余的带宽。与 HTB 不同,它通过丢弃数据包来实现低延迟,从而使交互式会话受益。
  • HTB
    分层令牌桶实现了具有丰富链路共享层次结构的类别,强调符合现有实践。HTB 促进了对类别的带宽保证,同时允许指定类别间共享的上限。它包含基于 TBF 的形状元素,并可以对类别进行优先级排序。
  • PRIO
    PRIO qdisc 是一个非形状容器,具有可配置数量的类别,这些类别按照顺序出队。这允许轻松地对流量进行优先级排序,其中较低的类别只有在较高类别没有数据包可用时才会发送。为了方便配置,默认情况下会遵守服务类型位。
  • QFQ
    快速公平排队是一个 O(1) 调度器,提供接近最优的保证,它是第一个以常数成本实现这一目标的调度器,并且在处理组和数据包长度方面也保持常数。QFQ 算法没有循环,并使用非常简单的指令和数据结构,适合硬件实现。

4.8. 操作原理

类别形成一个树形结构,每个类别有一个单一的父节点。一个类别可以有多个子节点。某些 qdiscs 允许在运行时添加类别(如 CBQ、HTB),而其他 qdiscs(如 PRIO)则以静态数量的子节点创建。

允许动态添加类别的 qdiscs 可以有零个或多个子类别,用于排队流量。

此外,每个类别包含一个叶子 qdisc,默认具有 pfifo 行为,虽然可以用其他 qdisc 替代。这个 qdisc 可能再次包含类别,但每个类别只能有一个叶子 qdisc。

当数据包进入类别 qdisc 时,它可以被分类到其中的一个类别。分类的三个标准如下,但并非所有 qdiscs 都会使用这三个标准:

  • tc 过滤器
    如果 tc 过滤器附加到类别上,它们首先被查阅以获取相关指令。过滤器可以匹配数据包头的所有字段,以及由 iptables 应用的防火墙标记。
  • 服务类型(TOS)
    一些 qdiscs 内置了根据 TOS 字段分类数据包的规则。
  • skb->priority
    用户空间程序可以使用 SO_PRIORITY 选项在 'skb->priority' 字段中编码类别 ID。

树中的每个节点可以有自己的过滤器,但较高级别的过滤器也可以直接指向较低级别的类别。

如果分类失败,数据包会被排队到该类别附加的叶子 qdisc 上。具体细节请参考 qdisc 的手册页。

4.9. 命名

所有 qdiscs、类别和过滤器都有 ID,这些 ID 可以指定,也可以自动分配。

ID 由一个主编号和一个次编号组成,以冒号分隔 - 主编号:次编号。主编号和次编号都是十六进制数字,并且限制在 16 位内。有两个特殊值:root 由全 1 的主编号和次编号表示,未指定则为全 0。

  • QDISCS
    一个可能拥有子节点的 qdisc 被分配一个主编号,称为 'handle',而次编号命名空间则留给类别。handle 表达为 '10:'。通常,预计会有子节点的 qdiscs 会明确分配一个 handle。
  • CLASSES
    居于 qdisc 下的类别共享它们的 qdisc 主编号,但每个类别都有一个称为 'classid' 的单独次编号,该编号与其父类别无关,仅与其父 qdisc 相关。类别的命名遵循与 qdiscs 相同的习惯。
  • FILTERS
    过滤器有一个三部分 ID,只有在使用哈希过滤器层次结构时才需要。

4.10. 参数

以下参数在 TC 中被广泛使用。有关其他参数,请参见个别 qdiscs 的手册页。

  • 速率(RATES)
    带宽或速率。这些参数接受浮点数,可能后跟单位(支持 SI 和 IEC 单位),或者是浮点数后跟 '%' 字符以指定为设备速度的百分比(例如 5%,99.5%)。警告:将速率指定为百分比意味着是当前速度的一个分数;如果速度发生变化,值不会重新计算。

    • bit 或裸数
      每秒位数
    • kbit
      每秒千比特
    • mbit
      每秒兆比特
    • gbit
      每秒千兆比特
    • tbit
      每秒太比特
    • bps
      每秒字节数
    • kbps
      每秒千字节
    • mbps
      每秒兆字节
    • gbps
      每秒千兆字节
    • tbps
      每秒太字节
    • 指定 IEC 单位时,替换 SI 前缀(k-、m-、g-、t-)为 IEC 前缀(ki-、mi-、gi-、ti-)。
    • TC 内部将速率存储为 32 位无符号整数,单位为 bps,因此可以指定最大速率为 4294967295 bps。
  • 时间(TIMES)
    时间长度。可以指定为浮点数后跟可选单位:

    • s、sec 或 secs
      整秒
    • ms、msec 或 msecs
      毫秒
    • us、usec、usecs 或裸数
      微秒
    • TC 定义了自己的时间单位(等于微秒),并将时间值存储为 32 位无符号整数,因此可以指定最大时间值为 4294967295 微秒。
  • 大小(SIZES)
    数据量。可以指定为浮点数后跟可选单位:

    • b 或裸数
      字节
    • kbit
      千比特
    • kb 或 k
      千字节
    • mbit
      兆比特
    • mb 或 m
      兆字节
    • gbit
      千兆比特
    • gb 或 g
      千兆字节
    • TC 内部将大小存储为 32 位无符号整数,单位为字节,因此可以指定最大大小为 4294967295 字节。
  • 值(VALUES)
    其他没有单位的值。这些参数默认按十进制解释,但可以通过添加 '0' 或 '0x' 前缀分别指示 TC 按八进制或十六进制解释它们。

V. 5. TC 命令

以下命令适用于 qdiscs、类别和过滤器:

  • add
    向节点添加 qdisc、类别或过滤器。对于所有实体,必须传递父节点,方法是通过其 ID 或直接附加到设备的根节点。当创建 qdisc 或过滤器时,可以使用 handle 参数进行命名。类别使用 classid 参数进行命名。
  • delete
    通过指定其 handle(也可以是 'root')删除 qdisc。所有子类别及其叶子 qdiscs 将被自动删除,以及任何附加到它们的过滤器。
  • change
    某些实体可以“就地”修改。与 'add' 共享语法,唯一的区别是 handle 不能更改,父节点也不能更改。换句话说,change 不能移动节点。
  • replace
    在现有节点 ID 上执行几乎原子的删除/添加操作。如果节点尚不存在,则会创建它。
  • get
    显示给定接口 DEV、qdisc-id、优先级、协议和过滤器 ID 的单个过滤器。
  • show
    显示附加到给定接口的所有过滤器。必须传递有效的父 ID。
  • link
    仅适用于 qdiscs,执行替换,其中节点必须已经存在。

5.1. 监控

tc 工具可以监控由内核生成的事件,例如添加/删除 qdiscs、过滤器或操作,或修改现有的。

以下命令适用于监控:

  • file
    如果给出 file 选项,tc 不会监听内核事件,而是打开给定的文件并转储其内容。文件必须是二进制格式并包含 netlink 消息。

5.2. 选项

  • -b, -b filename, -batch, -batch filename
    从提供的文件或标准输入中读取命令并执行。第一次失败将导致 tc 终止。
  • -force
    在批处理模式下遇到错误时不要终止 tc。如果在执行命令时发生错误,应用程序的返回码将为非零。
  • -o, -oneline
    将每条记录输出到单行,用 \ 字符替换换行符。这在你想用 wc(1) 统计记录数或用 grep(1) 搜索输出时很方便。
  • -n, -net, -netns
    tc 切换到指定的网络命名空间 NETNS。实际上,这只是简化了执行以下操作:

    ip netns exec NETNS tc [ OPTIONS ] OBJECT { COMMAND | help }

    为:

    tc -n[etns] NETNS [ OPTIONS ] OBJECT { COMMAND | help }
  • -N, -Numeric
    直接打印协议、作用域、dsfield 等的数字,而不是将其转换为可读名称。
  • -cf, -conf
    指定配置文件的路径。此选项与其他选项(如 -nm)一起使用。
  • -t, -timestamp
    tc 监控运行时,在事件消息之前打印时间戳,格式为:

    Timestamp: <Day> <Month> <DD> <hh:mm:ss> <YYYY> <usecs> usec
  • -ts, -tshort
    tc 监控运行时,在事件消息之前打印简短时间戳,格式为:

    [<YYYY>-<MM>-<DD>T<hh:mm:ss>.<ms>]

5.3. 格式

show 命令有额外的格式化选项:

  • -s, -stats, -statistics
    输出更多有关数据包使用的统计信息。
  • -d, -details
    输出关于速率和单元大小的更详细信息。
  • -r, -raw
    输出句柄的原始十六进制值。
  • -p, -pretty
    对于 u32 过滤器,解码偏移量和掩码值为基于 TCP/IP 的等效过滤器命令。在 JSON 输出中,添加空格以提高可读性。
  • -iec
    以 IEC 单位打印速率(例如 1K = 1024)。
  • -g, -graph
    以 ASCII 图形显示类别。如果指定了 -s 选项,则在每个类别下打印通用统计信息。类别只能通过 dev 选项过滤。
  • -ccolor
    配置彩色输出。如果省略参数或选择 always,则无论标准输出状态如何,彩色输出都会启用。如果选择 auto,则在启用彩色输出之前会检查标准输出是否为终端。如果选择 never,则禁用彩色输出。如果指定多次,最后一个参数将优先。如果同时给出了 -json,则此标志会被忽略。
  • -j, -json
    以 JSON 格式显示结果。
  • -nm, -name
    /etc/iproute2/tc_cls 文件或由 -cf 选项指定的文件中解析类别名称。此文件仅为类别 ID 到类别名称的映射:

    # 这里是注释
    1:40   voip # 这里是另一个注释
    1:50   web
    1:60   ftp
    1:2    home

    如果指定了 -nm 而未指定 -cf,且 /etc/iproute2/tc_cls 文件不存在,tc 不会失败,这使得可以传递 -nm 选项以创建 tc 别名。

  • -br, -brief
    仅打印识别过滤器和操作(句柄、cookie 等)以及统计信息所需的基本数据。此选项目前仅支持 tc filter showtc actions ls 命令。

5.4. 示例

  • tc -g class show dev eth0
    以 ASCII 图形显示 eth0 接口上的类别。
  • tc -g -s class show dev eth0
    以 ASCII 图形显示类别,并在每个类别下方显示统计信息。

VI. 6. 历史

tc 由 Alexey N. Kuznetsov 编写,并在 Linux 2.2 中添加。

VII. 7. 参见

tc-basic(8)`, `tc-bfifo(8)`, `tc-bpf(8)`, `tc-cake(8)`, `tc-cbq(8)`, `tc-cgroup(8)`, `tc-choke(8)`, `tc-codel(8)`, `tc-drr(8)`, `tc-ematch(8)`, `tc-ets(8)`, `tc-flow(8)`, `tc-flower(8)`, `tc-fq(8)`, `tc-fq_codel(8)`, `tc-fq_pie(8)`, `tc-fw(8)`, `tc-hfsc(7)`, `tc-hfsc(8)`, `tc-htb(8)`, `tc-mqprio(8)`, `tc-pfifo(8)`, `tc-pfifo_fast(8)`, `tc-pie(8)`, `tc-red(8)`, `tc-route(8)`, `tc-sfb(8)`, `tc-sfq(8)`, `tc-stab(8)`, `tc-tbf(8)`, `tc-tcindex(8)`, `tc-u32(8)

用户文档请访问 http://lartc.org/,但请将 bug 报告和补丁发送到:netdev@vger.kernel.org

VIII. 8. 作者

手册页由 bert hubert(ahu@ds9a.nl)维护。

iproute2 2001年12月16日 TC(8)


本文由 Jay 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处,点赞0

还不快抢沙发

添加新评论