注:本文是参照了一些其他文章,原文地址点击这里

概念


首先说NUMA(non-uniform memory access),他的引入是为了解决CPU、内存和IO等扩展性的问题,他用node进行区分,每个node都有自己独立的CPU、本地内存和IO槽口等。他们通过互联模块进行连接和信息交互,因为任意一个CPU都可以访问整个系统的内存,但是访问速度就差距很大了,本地节点>邻居节点>远端节点。所以扩展的越多,访问远端的节点耗费时间越长,而我们要做的尽量让每个CPU都处理本地的内存数据。

接下来说DPDK中的NUMA,DPDK从2.2版本引入了NUMA的概念,为了更好的应用在ovs-dpdk中,我们首先需要理解vhost-user设备包含的3中类型的内存:

*Memory managed byDescription
1DPDKDevice tracking memory
2OVSBackend buffers (mbufs)
3QEMUGuest memory (device and memory buffers)

对于一个已经优化了的datapath,所有以上的三种类型内存都需要分配在同一个节点上。在DPDK2.2之前这是不可能实现的,因为每一个DPDK管理的设备都必须存在于同一个节点上,而VM使用的Guest memory就可能不会在同一个节点上,这就造成了如下图Intel QPI(QuickPath Interconnect)流量和潜在的性能问题。

请输入图片描述

DPDK 2.2之后,vhost结构和Guest memory进行了动态关联,当vhost设备申请时,他是临时存储的,当他连接的VM的Guest memory的信息通过qemu传递给DPDK。DPDK利用该信息将vhost设备也驻留在该NUMA的节点。

之前我们没有提及的时mbufs,也就是ovs分配的内存,他必须和Guest memory和Device tracking memroy在相同的节点。DPDK通过讲guest的信息发送给ovs,然后ovs在相应的节点申请mbufs。在这之前,mbufs都是存在于DPDK的master lcore所在节点。

最后的一个难题就是关于OVS的PMD(poll mode driver)线程的位置。PMD是负责轮询所有的输入端口,一旦收到数据就会进行一系列的操作。以前ovs的PMD线程都必须固定在同一个NUMA节点的lcore上,该节点就是DPDK的mater lcore。但是现在PMD线程可以放置在和Device tracking memory、Guest memory相同的节点上,如下图所示:

请输入图片描述

其实这个我们可以看到至少需要两个PMD线程,也就是每个NUMA需要一个PMD的线程,需要两个lcore,这就需要我们自己去评估有没有必要使用这么多的CPU。

测试环境


测试环境需要至少有两个NUMA节点的主机,主机运行ovs-dpdk,并且为ovs-dpdk配置两个vhostuser设备。两个VM在两个单独的NUMA节点上,分别链接两个vhostuser设备,如下表所示:

ProcessorIntel® Xeon® processor E5-2695 v3 @ 2.30 GHz
Kernel4.2.8-200
OSFedora* 22
QEMU*v2.6.0
DPDKv16.04
Open vSwitch*914403294be2

配置


安装DPDK和OVS之前,确保NUMA的一些库已经安装了

sudo yum install numactl-libs
sudo yum install numactl-devel

DPDK的配置做如下改动

CONFIG_RTE_LIBRTE_VHOST_NUMA=y

按照上面的介绍,ovs的两个PMD线程要跑在两个NUMA节点上,我们核心0-13位于NUMA节点0,14-27位于NUMA节点1上,所以我们需要配置ovs的PMD线程绑定lcore的掩码

ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=10001

运行虚拟机之前,可以确认一下PMD线程,确认vhostuser的Device tracking memory和PMD线程位于同一个NUMA节点上

ovs-appctl dpif-netdev/pmd-rxq-show

pmd thread numa_id 0 core_id 0:
        port: dpdkvhostuser1    queue-id: 0
        port: dpdkvhostuser0    queue-id: 0

接下来启动两个VM,使用taskset来确认两个VM分别位于两个NUMA节点上

sudo taskset 0x2 qemu-system-x86_64 -name VM0 -cpu …
sudo taskset 0x2000 qemu-system-x86_64 –name VM1 -cpu …

检查VM的日志,VM1打印的信息如下:

VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
VHOST_CONFIG: reallocate vq from 0 to 1 node
VHOST_CONFIG: reallocate dev from 0 to 1 node

这意味着Device tracking memory已经从之前的临时存储在节点0,切换到指定的节点1了。

另一种验证成功的方式就是通过使用pmd-rxq-show检查PMD

pmd thread numa_id 1 core_id 20:
        port: dpdkvhostuser1    queue-id: 0
pmd thread numa_id 0 core_id 0:
        port: dpdkvhostuser0    queue-id: 0

dpdkvhostuser1运行的线程是在NUMA节点1。

最后修改:2021 年 08 月 20 日
如果觉得我的文章对你有用,请随意赞赏