OVS自身并不实现QoS功能,QoS功能的实现是在linux内核中,OVS只是能够配置部分OVS支持的QoS类型。
如果需要一些OVS不支持的QoS类型,可以通过patch来支持这些配置,也可以通过传统的TC流量控制工具直接进行QoS的策略配置。
文章目录
- 单个队列限速
- 底层原理
- 删除 QoS 设置
- 多队列限速
- 参考
QoS在OVS中的使用和传统网络一样,主要分为如下两种:
- Policing管制:用于控制接口上接收分组(ingress)的速率,是一种简单的QoS的功能,通过简单的丢包机制实现接口速率的限制,它既可以作用于物理接口,也可以作用于虚拟接口;
- Shaping整形:是作用于接口上的出口流量(egress)策略,可以实现多个QoS队列,不同队列里面处理不同策略,一般用这种方式。
单个队列限速
建立一个简单的拓扑:
mininet> links
s1-eth1<->h1-eth0 (OK OK)
s1-eth2<->h2-eth0 (OK OK)
h1为数据发送端,h2为数据接收端,使用 iPerf 打UDP流:
h2 iperf -s -p 5566 -i 1 -u &
h1 iperf -c h2 -p 5566 -b 100m -t 10 -i 1 -u
可以看到带宽能达到设置的100M:
接下来对出端口s1-eth2进行QoS设置。
其中 --
用于把命令分割成单独解析的命令行,\
用于换行。最大最小转发速率均为 1M,完整代码:
ovs-vsctl set port s1-eth2 qos=@newqos -- \
--id=@newqos create qos type=linux-htb queues=0=@q0 -- \
--id=@q0 create queue other-config:min-rate=1000000 other-config:max-rate=1000000
返回以下,上面一行是 qos 配置标识名qosID ,下面一行是 queue 标识名queueID 。
01043d15-d17d-4b27-bc45-52a0c9226adc
4a466860-c769-4cee-b2ff-ffd507924727
详细解释:
设置端口 s1-eth2 的 qos 规则名为 newqos
set port s1-eth2 qos=@newqos
创建 newqos 规则,类型为 linux-htb,连接key值为0的队列q0
id=@newqos create qos type=linux-htb queues=0=@q0
创建 q0 队列,设置最大最小转发速率均为 1M
id=@q0 create queue other-config:min-rate=1000000 other-config:max-rate=1000000
通过命令 ovs-vsctl list port s1-eth2
可以看到 s1-eth2 端口的 port 表中有 qos 配置:
通过命令 ovs-vsctl list qos
查看 qos 配置表,其中有 queue 配置:
通过命令 ovs-vsctl list queue
查看 queue 配置表,可看到限制的速率:
再通过上面同样的方法进行 iPerf 打流,可以看到速率被限制在 1M。
底层原理
前面提到过TC工具,其实qos底层也是使用的TC进行流量控制。
关于 TC 流量控制工具详解可看这篇博客
使用 tc -s -d qdisc show dev s1-eth2
,发现使用的 htb 队列:
使用 tc -s -d class show dev s1-eth2
,可以看到设置的类:
其中1:fffe
为ingress 入口队列的类。
删除 QoS 设置
若要取消某端口QoS设置,可以用下面的命令:
ovs-vsctl clear port s1-eth2 qos //使端口s1-eth2的qos设置失效
使用 ovs-vsctl list port s1-eth2
查看端口s1-eth2的话,会发现端口qos项的qosID没有了。虽然端口 s1-eth2 已经不受这一条qos限制了,但是之前设置的qos和queue还存在系统中,可以用 ovs-vsctl list qos
和 ovs-vsctl list queue
命令查看。
若要删除这些qos和queue,需要以下命令
ovs-vsctl destroy qos qosID //qosID 可通过前文list命令查看
ovs-vsctl destroy queue queueID //queueID 可通过前文list命令查看
ovs-vsctl -- destroy qos s1-eth2 -- clear port s1-eth2 qos //取消并删除qos一步达成,注意两条命令顺序不能换,不然先clear的话,轮到destroy去找s1-eth2的qos就找不见了
或者先取消所有端口绑定的qos后,直接全部删除:
ovs-vsctl -- --all destroy qos -- --all destroy queue
多队列限速
关闭拓扑重启后,之前创建的qos和queue仍然存在,只是没绑定到端口上,所以可以先运行ovs-vsctl -- --all destroy qos -- --all destroy queue
删除所有qos。
在以上拓扑交换机上多接一个主机h3,IP 为10.0.0.3/24。拓扑为:
mininet> links
s1-eth1<->h1-eth0 (OK OK)
s1-eth2<->h2-eth0 (OK OK)
s1-eth3<->h3-eth0 (OK OK)
对出端口s1-eth2进行QoS设置:
ovs-vsctl set port s1-eth2 qos=@newqos -- \
--id=@newqos create qos type=linux-htb other-config:max-rate=5000000 other-config:min-rate=5000000 queues=0=@q0,1=@q1 -- \
--id=@q0 create queue other-config:min-rate=1000000 other-config:max-rate=2000000 -- \
--id=@q1 create queue other-config:min-rate=4000000 other-config:max-rate=4000000
以上对 s1-eth2 被限速为5Mbits/s,对应设置了两个队列,队列0设置速率1 Mbits/s,队列1设置速率4 Mbits/s。返回qosID 和两个queueID:
2af78d23-3247-403c-bc8a-93d080d3cc51
ea3e24ad-c648-452c-a89d-95f4c01f47de
a20457f3-b2c4-4ada-b19f-865235cb3100
要使这些队列生效,还需要手动设置OVS流表,将数据包放入指定队列中。
以下命令将 s1-eth1 来的包放入q0,s1-eth3来的包放入q1:
ovs-ofctl -O OpenFlow13 add-flow s1 in_port="s1-eth1",actions=set_queue:0,output:"s1-eth2"
ovs-ofctl -O OpenFlow13 add-flow s1 in_port="s1-eth3",actions=set_queue:1,output:"s1-eth2"
使用命令 ovs-ofctl dump-flows -O OpenFlow13 s1
查看 s1 流表:
使用 iPerf 在5566端口打UDP流测试q0:
h2 iperf -s -p 5566 -i 1 -u &
h1 iperf -c h2 -p 5566 -u -b 100m -t 5 -i 1
在5567端口打TCP流测试q1:
h2 iperf -s -p 5567 -i 1 &
h3 iperf -c h2 -p 5567 -b 100m -t 5 -i 1
可以看到两个队列都限速成功。
设置OVS流表还可以通过目的端口、来源IP等来配置队列,具体可参考 OVS 流表操作:
ovs-ofctl -O OpenFlow13 add-flow s1 ip,udp,tp_dst=5566,actions=set_queue:0,output:"s1-eth2"
ovs-ofctl -O OpenFlow13 add-flow s1 ip,nw_src=10.0.0.3,actions=set_queue:1,output:"s1-eth2"
参考
Quality of Service (QoS)
Open vSwitch之QoS的实现
Open vSwitch 出口流量QoS实现