轮询模式驱动程序(Poll Mode Driver,PMD)线程负责处理DPDK数据路径上的大部分工作,并执行诸如输入端口的连续轮询等任务。一旦接收到数据包及对其进行分类,分类完成后进行处理动作。
PMD线程使用接收(RX)和发送(TX)队列,通常称为rxqs和txqs。TX队列的配置自动产生,RX队列可以由用户进行配置。这可以通过以下两种方式之一实现:
-
对于物理接口,配置通过工具
ovs-appctl
实现. -
对于虚拟接口,配置也是通过工具
ovs-appctl
实现,但是此配置必须反映在客户机的配置中(例如,QEMU的命令行参数)。
ovs-appctl
工具也提供一些命令查询PMD线程以及相关队列信息,以下讨论这些。
PMD线程统计
显示当前统计信息:
$ ovs-appctl dpif-netdev/pmd-stats-show
清除统计信息:
$ ovs-appctl dpif-netdev/pmd-stats-clear
分配到PMD线程的端口/RX队列
PMD线程及其使用的RX队列需要正确配置,以便达到最大的性能。这一点尤其正确对于启用诸如multipqueue之类的功能的物理接口dpdk phy multipqueue和vhost用户接口dpdk vhost user。
显示端口/RX队列分配情况:
$ ovs-appctl dpif-netdev/pmd-rxq-show
RX队列可能手动固定在某个核心上。这将改变默认的到PMD线程的RX队列分配:
$ ovs-vsctl set Interface <iface> \
other_config:pmd-rxq-affinity=<rxq-affinity-list>
where:
<rxq-affinity-list>
表示CSV格式列表:<queue-id>:<core-id>
。
例如:
$ ovs-vsctl set interface dpdk-p0 options:n_rxq=4 \
other_config:pmd-rxq-affinity="0:3,1:7,3:8"
以上命令设置 4 个RX队列,配置如下:
- 队列 #0 固定在核心3
- 队列 #1 固定在核心7
- 队列 #2 未固定
- 队列 #3 固定在核心8
RX队列被固定的核心上运行的PMD线程将处于隔离状态。这意味着该线程只能轮询被固定的RX队列。
警告:
如果不存在未隔离的PMD线程,未固定的RX队列将得不到轮询。同样,如果参数中要求固定的核心<core-id>
不可用(例如,<core-id>
不在pmd-cpu-mask
掩码内),相应的RX队列也不会被任何PMD线程的轮询。
如果没有未RX队列指定pmd-rxq-affinity
参数, 它们将自动的分配到PMDs线程(核心)。
为PMDs线程自动分配RXQs的算法可由以下命令设置:
$ ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=<assignment>
默认情况下,使用cycles
分配法,即首先将每个RXQs队列按照测量的处理周期排序,之后以降序方式公平的分配到PMDs线程,如果PMD线程数量小于队列数量,分配过程将以多轮次完成(由上到下,再由下到上). 例如,5个接收队列和3个核心 - 3,7和8. 最近一个时间间隔在每个队列上测量到的核心周期使用情况如下:
- 队列 #0: 30%
- 队列 #1: 80%
- 队列 #3: 60%
- 队列 #4: 70%
- 队列 #5: 10%
RX接收队列将以如下的次序分配到核心上:
- Core 3: Q1 (80%) |
- Core 7: Q4 (70%) | Q5 (10%)
- Core 8: Q3 (60%) | Q0 (30%)
另外, 也可以使用roundrobin
分配法,即以循环方式将RXQs队列分配到PMDs进程. 在OVS 2.9版本前,这是默认使用的分配算法. 例如, 有以下的端口和队列:
- 端口 #0 队列 #0 (P0Q0)
- 端口 #0 队列 #1 (P0Q1)
- 端口 #1 队列 #0 (P1Q0)
- 端口 #1 队列 #1 (P1Q1)
- 端口 #1 队列 #2 (P1Q2)
RX队列可能以如下的次序分配到核心上:
Core 3: P0Q0 | P1Q1
Core 7: P0Q1 | P1Q2
Core 8: P1Q0 |
查看关于每个RX队列占用的PMD核心周期数,在当下测量出来的占用历史信息:
$ ovs-appctl dpif-netdev/pmd-rxq-show
注意:
为每个RX队列记录和显示一分钟的历史记录,以允许流量模式高峰。由于流量模式或重新配置,所引起的RX队列的PMD核心周期的任何更改,需要一分钟才能完全反映在统计数据中。
每当配置发生更改,或者通过以下命令的执行,都将触发RX队列到PMD线程的分配变动:
$ ovs-appctl dpif-netdev/pmd-rxq-rebalance
pmd-rxq-show
命令于OVS 2.6.0版本加入。
基于利用率的RX队列到PMD的分配和pmd-rxq-rebalance
命令添加于OVS 2.9.0。在此之前,分配采用循环方法,没有考虑处理周期。
此外,pmd-rxq-show
命令的输出被修改为包括以百分比表示的PMD的RX队列利用率。在此之前,跟踪统计数据是不可行的。
自动分配到PMD线程的端口/RX队列 (实验性质)
基于周期或利用率的RX队列分配到PMD线程可以提高负荷分布效率,但不适应随时间变化的流量模式。这会导致PMD之间的负载不均匀,从而导致总体吞吐量的降低。
为解决此问题,可启用PMD自动负载均衡:
$ ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"
如果pmd-auto-lb设置为true,并且启用了基于周期的分配方法,如果存在2个或多个非隔离的PMD线程,其中至少一个PMD正在轮询多个RX队列,自动负载均衡将启用。所以,需要满足以下条件才能启用自动负载均衡:
- RX队列到PMD的基于周期的分配已启用.
- pmd-auto-lb参数设置为true.
- 存在两个或多个非隔离PMD线程.
- 并且至少一个非隔离的PMD线程具有多个轮询队列.
如果不满足上述任一条件,则禁用PMD自动负载均衡。
一旦设置了自动负载均衡,每个非隔离PMD都会每10秒钟测量一次其每个关联队列的处理负荷。如果PMD连续6个间隔的合并负荷达到95%,PMD认为自己已经过载。
如果任一PMD进程过载,OVS主线程执行PMD分配算法的预检运行。预检运行不会更改现有队列的PMD分配。
如果预检运行的结果表明负荷分布的提升,将执行实际重新分配。
注意:
如果队列在不同NUMA节点分配,则PMD自动负载均衡当前不起作用,因为与预检的预测相比实际处理负荷可能会变得更糟。
两个连续的PMD自动负载均衡操作之间的最短时间可可通过以下方式配置:
$ ovs-vsctl set open_vswitch .\
other_config:pmd-auto-lb-rebal-interval="<interval>"
参数<interval>
的单位为分钟. 默认间隔为1分钟,设置为0意味值恢复1分钟的默认值。
用户可以使用此选项避免频繁触发PMD自动负载均衡。例如,设置此值(以分钟为单位),使其在几小时,一周或一天内发生一次。
注意:
在某些场景下,可能不希望自动负载均衡触发。例如,如果特定RX队列的流量模式频繁的变化,并且由于dpctl和EMC中对新添加流的更改,将打乱处理器缓存。在这种情况下,用户应该相应地配置重新均衡间隔避免频繁的再均衡发生。