一、流的队列分配:rx-steering
可以为特有的流量分配专门的队列,避免核心数据包丢包引起网络故障,比如LACP,可以单独使用一个队列,类似的。其他协议也可以做类似处理。
以ovs实现为例:假设有8个队列[0,1,2,3,4,5,6,7],那么一般以最后一个队列作为专用队列让LACP协议独享,其他数据包走0-6号队列,
(当然从实现而言,多个队列作为专用队列也不是不可以),具体操作为:
对于其他流量而言: 对rss分发表重新设置,屏蔽7号队列,只分配到0-6号队列,因此其他流量不会分到7号队列。
对于LACP流量而言:通过dpdk的rte_flow_*创建一条flow,协议指定为LACP,动作指定为 分配到队列7即可
如此一来,即使业务流量高到队列丢包的情况下,LACP由于单独一条队列也不会丢包。
因此同样的方法可以适用于其他特殊流量,比如VRRP等,只需多加一条规则即可。
这个从OVS来看,只适用于物理网卡,且和硬件卸载(主要是流量卸载到硬件处理)功能有冲突。如果启用了硬件卸载,则该功能失效。
二、队列的CORE分配:pmd-rxq-assign
这个主要是通过一定的策略将收包队列分配给不同的pmd线程(core)进行处理来均衡各个CPU的负载。
在ovs中,主要有三种算法策略来分配队列:cycles(默认)/group/roundrobin,分配依据是队列处理周期(measured processing cycles)。
当然,用户还能手动指定队列的绑定关系,pmd线程和队列绑定之后默认就是隔离的(isolated),隔离状态下就不能调度了,
不过在group调度模式下可以强制指定为非隔离的,上面的三种策略都是针对非隔离的队列和pmd线程进行调度处理的。
这个在跨numa情况下调度,性能可能会下降。
1. cycles计算:
1 | IDLE:一轮循环,没收发数据包,cycles算做IDLE |
2. 收包统计:
本轮收包(记录1次):只统计收包总时间,默认5s统计一次
直方图统计(记录12次):统计最近12次收包总时间,调度时排序会用这个作比较
3.调度过程:
收集非隔离队列:先将非隔离的队列按照统计到的收包处理周期从大到小排列(roundrobin算法不用排)(手动指定隔离的但是没有CPU处理的也算是非隔离的队列)。
当前非隔离线程:先看port对应的numa上没有非隔离线程,没有的话就找其他有非隔离线程的numa。
将队列分配给对应线程:调度算法为:最新版本默认是cycles算法,2.9以前默认是roundrobin算法。
cycles:
依次将队列分配给对应的线程,并且一轮分配完,按照逆序分配,即 1 → 2 → 3 → 3 → 2 → 1,
假设当前收集完有5个队列(0,1,3,4,5),3个线程(3,7,8):
1 | Queue #0: 30% |
最终结果:
1 | Core 3: Q1 (80%) | |
group:
直接找负载最小的pmd分配,
假设当前收集完有5个队列(0,1,3,4,5),3个线程(3,7,8):
1 | Queue #0: 10% |
最终结果:
1 | Core 3: Q1 (80%) | |
roundrobin:
和cycles策略类似,只不过每一轮都是从头开始,即 1 → 2 → 3 → 1 → 2 → 3,
假设当前收集完有5个队列(0,1,3,4,5),3个线程(3,7,8):
1 | Port #0 Queue #0 (P0Q0) |
最终结果:
1 | Core 3: P0Q0 | P1Q1 |
三、NETDEV WATCHDOG
网卡队列满(剩余空间小于预留值)的情况下,网卡会停止发包,当watchdog发现网卡处于up状态并且发送队列处于停止时间大于5秒时将触发看门狗机制,
dev_watchdog先找到停止的队列,然后调用igb_tx_timeout整个网卡队列做超时处理,igb_tx_timeout中对网卡做了DOWN、UP的操作。