3、Linux TC与OVS QoS:TC原理简介、OVS如何利用TC实现限速

聊到OVS的QoS,绕不开Linux TC。说实话,很多刚接触SDN的朋友会觉得OVS的QoS是个黑盒子,配置完就完事了。但在我多年的运维经验里,不懂TC就去配OVS限速,出了问题你根本不知道从哪查起。

这一节,我就带你扒开OVS QoS的底层——看看它到底是怎么借助Linux TC来实现流量整形和限速的。

3.1 Linux TC是什么?

TC,全称Traffic Control,是Linux内核自带的流量控制工具。说白了,它就是内核里一个“交通警察”,负责决定数据包什么时候发、按什么顺序发、能不能发。

TC的核心组件有三个:

  • qdisc(排队规则):数据包要出去,得先排队。qdisc就是管这个队的。
  • class(类):把队列分成多个子队列,每个子队列可以有不同的规则。
  • filter(过滤器):决定哪个数据包进哪个类。

你可以把网卡想象成一个收费站出口。qdisc就是收费站的排队通道,class是不同车型的专用道(小车、货车、ETC),filter就是收费员看你车牌把你引到对应车道。

核心要点:TC工作在出口方向(egress)和入口方向(ingress)。OVS主要利用的是出口方向的qdisc来做限速。

3.2 常用的qdisc类型

我个人在实际项目中用得最多的就三种:

qdisc类型 特点 适用场景
pfifo_fast 默认qdisc,先入先出,三个优先级band 普通场景,无特殊需求
HTB(Hierarchical Token Bucket) 分层令牌桶,支持带宽借用和层级结构 多级限速、租户隔离、带宽保证
TBF(Token Bucket Filter) 令牌桶,简单粗暴,精确限速 单端口固定速率限制

嗯,这里要注意。HTB是OVS QoS的默认选择。为什么?因为它支持分层。你想想看,一个物理网卡上可能跑着几十个虚拟机,每个虚拟机还要再细分不同的流量类型,HTB这种树形结构正好派上用场。

我的经验:曾经有个客户说OVS限速不准,我上去一看,他用的pfifo_fast。这玩意儿根本不限速,只排队。换成HTB后,问题立刻解决。

3.3 OVS如何利用TC实现限速?

OVS本身不直接操作网卡队列。它把限速任务“外包”给了Linux TC。具体流程是这样的:

  1. OVS创建一个内部端口(比如vnet0)
  2. OVS通过Netlink接口,调用TC命令在该端口上挂载qdisc
  3. TC根据qdisc规则,对经过该端口的数据包进行排队和丢弃

说白了,OVS只负责“告诉”TC要限多少速,具体怎么限、怎么丢包,全是TC干的活。

我们来看一个实际的例子。假设我要限制一个虚拟机网卡vnet0的出口带宽为100Mbps:

# OVS内部会执行类似这样的TC命令
tc qdisc add dev vnet0 root handle 1: htb default 30

tc class add dev vnet0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

tc filter add dev vnet0 protocol ip parent 1:0 prio 1 u32 \
    match ip dst 192.168.1.0/24 flowid 1:1

这段代码什么意思?

  • 第一行:在vnet0上挂载一个HTB qdisc,根节点handle为1:
  • 第二行:创建一个类1:1,保证速率和最大速率都是100Mbps
  • 第三行:用u32过滤器,把去往192.168.1.0/24网段的数据包归到类1:1里

当然,OVS不会让你手动敲这些。它通过OpenFlow的QoS配置,自动帮你生成对应的TC规则。

3.4 OVS QoS与TC的映射关系

OVS里配置QoS时,你会接触到几个关键概念。它们和TC的对应关系是这样的:

OVS概念 对应TC组件 说明
QoS表项 qdisc(根节点) 定义限速策略类型(如linux-htb)
Queue队列 class(子类) 每个队列对应一个带宽限制
Ingress Policing ingress qdisc + filter 入口方向的速率限制

我记得有一次排查一个限速不生效的问题。OVS里配了QoS,但TC规则没生成。后来发现是OVS的ovs-vswitchd进程没有权限调用TC。嗯,权限问题,老生常谈了。

避坑指南:我曾经遇到过OVS版本和内核TC不兼容的情况。OVS 2.5以下版本对HTB的支持有限,建议使用OVS 2.8及以上版本。另外,如果内核没有编译HTB模块,OVS的限速会直接失败。

3.5 查看TC规则的方法

当你配完OVS QoS后,怎么确认TC规则已经生效?用下面几条命令:

# 查看所有qdisc
tc qdisc show dev vnet0

# 查看所有class
tc class show dev vnet0

# 查看filter
tc filter show dev vnet0

# 实时监控流量
tc -s qdisc show dev vnet0

加上-s参数,能看到每个队列的发送字节数、丢包数、超限次数。这些数据对排查限速是否生效非常有用。

举个例子,如果你发现某个队列的丢包数一直在涨,但速率没达到上限,那可能是burst参数设置太小了。burst是令牌桶的突发容量,太小会导致瞬间流量被误杀。

3.6 小结

这一节我们讲了Linux TC的基本原理,以及OVS如何利用TC来实现限速。说白了,OVS的QoS就是个“翻译官”,把你的限速需求转成TC能理解的规则。

下一节,我会带你实战配置OVS的QoS,包括如何创建QoS表项、如何绑定Queue、如何验证限速效果。到时候我会用真实的抓包数据来展示限速前后的区别,敬请期待。