OVS与DPDK vHost User端口

40 篇文章 24 订阅

DPDK数据路径提供DPDK支持的vHost User端口作为与客户机交互的主要方式。有关vHost User的详细信息,请参阅’qemu’在同一文件上。

重要:

要使用任何基于DPDK的端口,你必须确保网桥已正确配置。更多信息请参见bridge.

快速示例

本示例演示如何添加两个dpdkvhostuserclient端口到已有的网桥br0中:

$ ovs-vsctl add-port br0 dpdkvhostclient0 \
    -- set Interface dpdkvhostclient0 type=dpdkvhostuserclient \
       options:vhost-server-path=/tmp/dpdkvhostclient0
$ ovs-vsctl add-port br0 dpdkvhostclient1 \
    -- set Interface dpdkvhostclient1 type=dpdkvhostuserclient \
       options:vhost-server-path=/tmp/dpdkvhostclient1

以上的示例要正常工作,相应的服务套接口必须在指定目录创建 (/tmp/dpdkvhostclient0/tmp/dpdkvhostclient1). 这些套接口可通过QEMU创建。详细信息参见vhost-user client一节.

vhost-user vs. vhost-user-client

Open vSwitch提供两种类型的vHost User 端口:

  • vhost-user (dpdkvhostuser)

  • vhost-user-client (dpdkvhostuserclient)

vHost User使用客户端-服务器模型。服务端创建/管理/销毁vHost User套接口,客户端连接到服务端。依据使用的端口类型,dpdkvhostuser 或者 dpdkvhostuserclient,客户端-服务器模型使用不同的配置。

对于vhost-user端口,Open vSwitch作为服务端,QEMU为客户端。这意味着如果OVS进程挂掉,所有的虚拟机必须重新启动。反之,对于vhost-user-client端口,OVS作为客户端,QEMU为服务器。这意味着OVS可以挂掉,并在不引起问题的情况下重新启动,也可重新启动客户机自身。由此原因,vhost-user-client端口为在所有已知情况下的首选类型。唯一的限制时vhost-user-client类型端口需要QEMU版本2.7. 端口类型vhost-user目前不赞成使用,并且将在以后的版本中移除。

vhost-user

重要:

使用vhost-user端口需要QEMU >= 2.2; vhost-user端口已被废弃.

要使用vhost-user 端口, 必须先将端口添加到交换机. DPDK vhost-user 端口可取任意的名称,但是不能包含反向和正向斜线。对于vhost-user,端口类型为dpdkvhostuser:

$ ovs-vsctl add-port br0 vhost-user-1 -- set Interface vhost-user-1 \
    type=dpdkvhostuser

此命令创建位于/usr/local/var/run/openvswitch/vhost-user-1的套接口, 在虚拟机的QEMU命令行需要提供此套接口地址.

注意:

如果你希望vhost-user的套接口创建在/usr/local/var/run/openvswitch的子目录下,需要在ovsdb中执行此目录:

   $ ovs-vsctl --no-wait \
       set Open_vSwitch . other_config:vhost-sock-dir=subdir

一旦在交换机中添加了vhost-user端口, 必须添加到客户机中。由两种方式可实现此操作:直接使用QEMU,或者使用libvirt.

注意:

IOMMU 和 Post-copy Live Migration 不支持vhost-user端口.

添加vhost-user端口到客户机 (QEMU)

首先,你必须将vhost-user设备套接字连接到客户机。要实现此操作,你必须将以下参数传递给QEMU:

-chardev socket,id=char1,path=/usr/local/var/run/openvswitch/vhost-user-1
-netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce
-device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1

其中vhost-user-1是添加到交换机中的vhost-user端口的名称.

对多个设备重复上述参数,更改chardev路径以及id值。注意,需要为每个vhost-user设备指定一个单独并且不同的chardev路径。例如,你的第二个vhost-user端口名为vhost-user-2,额外增加QEMU命令行参数如下:

-chardev socket,id=char2,path=/usr/local/var/run/openvswitch/vhost-user-2
-netdev type=vhost-user,id=mynet2,chardev=char2,vhostforce
-device virtio-net-pci,mac=00:00:00:00:00:02,netdev=mynet2

此外,QEMU必须在hugetlbfs上分配VM的内存。vhost-user端口访问virtio-net设备的虚拟环和数据包缓冲区,其为在Hugetlbfs上映射的虚拟机的物理内存。开启vhost-user端口以映射虚拟机的内存到进程地址空间中,需将以下参数传递给qemu:

-object memory-backend-file,id=mem,size=4096M,mem-path=/dev/hugepages,share=on
-numa node,memdev=mem -mem-prealloc

最后,您可能希望启用多队列支持。这是可选的,但是,如果要启用它,请运行:

-chardev socket,id=char2,path=/usr/local/var/run/openvswitch/vhost-user-2
-netdev type=vhost-user,id=mynet2,chardev=char2,vhostforce,queues=$q
-device virtio-net-pci,mac=00:00:00:00:00:02,netdev=mynet2,mq=on,vectors=$v

where:

$q
队列数量
$v
向量数量, 其值等于$q * 2 + 2

vhost-user端口在virtio设备连接之后,将根据需要自动重新配置Rx和Tx队列数。不支持手动配置n_rxq,因为OVS只能在n_rxq与QEMU中配置的队列数量匹配时正常工作。

如果目的地为配置了多队列设备的虚拟机的流量,由物理DPDK端口进入到了虚拟交换机中,则该物理DPDK端口的RX队列的数量也应设置为两个以上。此举可增加以下的可能性,即一个不同的PMD程序处理到客户机的多队列传输,其使用一个不同的vhost队列。

如果用户希望在客户机中使用多队列的接口,则客户机操作系统中的驱动程序也必须执行此配置。建议配置的队列数等于$q

例如,对于Linux内核的virtio-net驱动程序,使用以下命令实现:

$ ethtool -L <DEV> combined <$q>

where:

-L
更改指定网络设备的通道数
combined
更改多用途通道的数量.

Adding vhost-user ports to the guest (libvirt)

首先,必须更改运行QEMU的用户和组,然后重新启动libvirtd.

  • 在文件 /etc/libvirt/qemu.conf 中增加/编辑如下行:

    user = "root"
    group = "root"
    
  • 最后,重启libvirtd进程, 例如,在Fedora系统上:

    $ systemctl restart libvirtd.service
    

完成之后,示例化VM虚拟机. 此文件末尾提供了一个示例XML配置文件demovm. 保存此文件,然后,使用此文件创建虚拟机:

$ virsh create demovm.xml

创建完成后,你可连接到客户机的console控制台:

$ virsh console demovm

demovm XML文件的配置意在虚拟机中实现超越其自身的性能。这些增强功能包括:

  • 使用vcpupin工具将vcpus固定在CPU Socket 0的核心上.

  • 配置NUMA单元,并使用memAccess='shared'配置共享内存。

  • 禁用 mrg_rxbuf='off'

更多信息,请参见 libvirt documentation.

vhost-user-client

重要:

使用vhost-user-client端口要求 QEMU >= 2.7

要使用vhost-user-client端口,必须首先将所述端口添加到交换机。类似与DPDK vhost-user端口,DPDK vhost-user-client端口名称可以任意命名。但是,为端口指定的名称并不决定相应套接口设备的名称。相反,用户必须通过vhost-server-path选项配置套接口名称。对于vhost-user-client端口,端口类型为dpdkvhostuserclient

$ VHOST_USER_SOCKET_PATH=/path/to/socket
$ ovs-vsctl add-port br0 vhost-client-1 \
    -- set Interface vhost-client-1 type=dpdkvhostuserclient \
         options:vhost-server-path=$VHOST_USER_SOCKET_PATH

将vhost-user-client端口添加到交换机后,它们必须添加到客户机。类似vhost-user端口,有两种方法可以做到这一点:直接使用QEMU,或使用libvirt。这里只讨论QEMU的情况。

Adding vhost-user-client ports to the guest (QEMU)

将vhost-user设备套接口连接到客户机。要做到这一点,你必须给QEMU传递以下的参数:

-chardev socket,id=char1,path=$VHOST_USER_SOCKET_PATH,server
-netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce
-device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1

其中 vhost-user-1是添加到交换机中的vhost-user端口的名称.

如果相应的dpdkvhostuserclient端口还没有在OVS中配置参数vhost-server-path=/path/to/socket, QEMU 将打印类似于如下的日志信息:

QEMU waiting for connection on: disconnected:unix:/path/to/socket,server

QEMU将一直等待,直到OVS中的端口成功地创建出来,才开始启动VM。使用此模式的一个好处是vhost端口能够在交换机发生crash或被关闭后进行重新连接。一旦交换机重新启动,vHost端口将自动重新连接,并恢复正常服务。

vhost-user-client IOMMU Support

vhost IOMMU是限制virtio设备可访问的vhost内存的功能,因此在注重安全的部署环境中有益处。

可以通过全局配置值启用IOMMU支持:vhost-iommu-support。将此设置为true将为所有可用的vhost端口启用vhost IOMMU支持:

$ ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true

默认值为false.

重要:

修改此值需要重新启动daemon.

重要:

启用IOMMU功能将同时启用vhost user reply-ack协议;已知在QEMU 2.10.0版本上正常工作,但在旧版本上有错误(2.7.0-2.9.0,含2.7.0-2.9.0)。因此,IOMMU功能默认被禁用(如果使用上述版本的QEMU,应保存禁用)。从QEMU v2.9.1开始,vhost-iommu-support支持可以安全地启用,即使没有IOMMU设备,也没有性能损失。

vhost-user-client Post-copy Live Migration Support (experimental)

Post-copy迁移是在所有内存迁移之前,目标CPU已经启动的一种迁移模式。主要优势是可预测的迁移时间。多用做通常的pre-copy迁移之后的第二阶段,以防总得时间过长。

更多信息参见QEMU文档migration.

可以通过全局配置值vhost-postcopy-support启用Post-copy的支持。将其设置为true将为所有vhost-user-client端口启用Post-copy支持:

$ ovs-vsctl set Open_vSwitch . other_config:vhost-postcopy-support=true

默认值为false.

重要:

修改此值需要重新启动daemon.

重要:

DPDK Post-copy迁移模式使用userfaultfd 系统调用与内核交互缺页处理,以及使用基于巨页的共享内存。所以目标主机的Linux内核应该支持共享hugetlbfs之上的userfaultfd系统调用。此功能仅在内核上游版本4.11中引入。

DPDK自18.11.0版本以后,QEMU自2.12.0版本以后,开始支持Post-copy功能。但建议使用QEMU>=3.0.1,因为在3.0中修复了post-copy的迁移恢复,并且在3.0.1发布版中几乎没有其他额外修复。

DPDK Post-copy功能要求避免填充客户机内存(应用程序不能调用 mlock*类系统调用)。所以启用mlockall和dequeue zero-copy功能与post-copy功能不兼容。

请注意,在迁移vhost-user设备期间,PMD线程挂起从源主机下载出错页的一段时间。在10Gbps的链路上传输1GB Hugepage,速度可能非常慢。推荐使用2M大小的hugepage。

DPDK in the Guest

DPDKtestpmd应用程序可以在客户机VMs中运行,用于高速数据包在vhostuser端口之间转发。DPDK和testpmd应用程序必须在客户机虚拟机上编译。下面是在虚拟机中启动testpmd的步骤。

注意:

客户机中的DPDK支持要求 QEMU >= 2.2

首先,按照dpdk-vhost-userdpdk vhost user client的说明实例化一个客户机。启动后,连接到虚拟机,下载DPDK源码到VM并编译DPDK:

$ cd /root/dpdk/
$ wget http://fast.dpdk.org/rel/dpdk-18.11.1.tar.xz
$ tar xf dpdk-18.11.1.tar.xz
$ export DPDK_DIR=/root/dpdk/dpdk-stable-18.11.1
$ export DPDK_TARGET=x86_64-native-linuxapp-gcc
$ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
$ cd $DPDK_DIR
$ make install T=$DPDK_TARGET DESTDIR=install

编译 test-pmd 应用程序:

$ cd app/test-pmd
$ export RTE_SDK=$DPDK_DIR
$ export RTE_TARGET=$DPDK_TARGET
$ make

设置 huge pages 及 DPDK 设备绑定 UIO驱动:

$ sysctl vm.nr_hugepages=1024
$ mkdir -p /dev/hugepages
$ mount -t hugetlbfs hugetlbfs /dev/hugepages  # only if not already mounted
$ modprobe uio
$ insmod $DPDK_BUILD/kmod/igb_uio.ko
$ $DPDK_DIR/usertools/dpdk-devbind.py --status
$ $DPDK_DIR/usertools/dpdk-devbind.py -b igb_uio 00:03.0 00:04.0

注意:

vhost ports pci ids 可使用如下命令获取:

  lspci | grep Ethernet

最后,启动testpmd应用。

Sample XML

<domain type='kvm'>
  <name>demovm</name>
  <uuid>4a9b3f53-fa2a-47f3-a757-dd87720d9d1d</uuid>
  <memory unit='KiB'>4194304</memory>
  <currentMemory unit='KiB'>4194304</currentMemory>
  <memoryBacking>
    <hugepages>
      <page size='2' unit='M' nodeset='0'/>
    </hugepages>
  </memoryBacking>
  <vcpu placement='static'>2</vcpu>
  <cputune>
    <shares>4096</shares>
    <vcpupin vcpu='0' cpuset='4'/>
    <vcpupin vcpu='1' cpuset='5'/>
    <emulatorpin cpuset='4,5'/>
  </cputune>
  <os>
    <type arch='x86_64' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <cpu mode='host-model'>
    <model fallback='allow'/>
    <topology sockets='2' cores='1' threads='1'/>
    <numa>
      <cell id='0' cpus='0-1' memory='4194304' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2' cache='none'/>
      <source file='/root/CentOS7_x86_64.qcow2'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <interface type='vhostuser'>
      <mac address='00:00:00:00:00:01'/>
      <source type='unix' path='/usr/local/var/run/openvswitch/dpdkvhostuser0' mode='client'/>
       <model type='virtio'/>
      <driver queues='2'>
        <host mrg_rxbuf='on'/>
      </driver>
    </interface>
    <interface type='vhostuser'>
      <mac address='00:00:00:00:00:02'/>
      <source type='unix' path='/usr/local/var/run/openvswitch/dpdkvhostuser1' mode='client'/>
      <model type='virtio'/>
      <driver queues='2'>
        <host mrg_rxbuf='on'/>
      </driver>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
  </devices>
</domain>

QEMU documentation.

Jumbo Frames

DPDK vHost User端口可以配置为使用巨型帧。更多信息,请参阅:jumbo frames

vhost-user Dequeue Zero Copy (experimental)

通常,当从vHost User设备中出列(dequeue)一个数据包时,必须使用memcpy操作用于将该数据包从客户机地址空间复制到主机地址空间。通过启用Dequeue zero-copy功能,可以省去memcpy操作,如下所示:

$ ovs-vsctl add-port br0 dpdkvhostuserclient0 -- set Interface \
    dpdkvhostuserclient0 type=dpdkvhostuserclient \
    options:vhost-server-path=/tmp/dpdkvhostclient0 \
    options:dq-zero-copy=true

启用此功能后,会将指向数据包的引用(指针)传递给主机,而不是数据包的拷贝副本。移除此memcpy可以为某些用例带来性能改进,例如在不同的虚拟机之间交换大数据包。但是,可能会观察到额外的数据包丢失。

请注意,该功能在默认情况下是禁用的,必须显式启用。当指定host-server-path选项时通过将dq-zero-copy选项设置为true开启此功能。如果你想分为多个命令执行,确保在设置vhost-server-path之前设置dq-zero-copy

$ ovs-vsctl set Interface dpdkvhostuserclient0 options:dq-zero-copy=true
$ ovs-vsctl set Interface dpdkvhostuserclient0 \
    options:vhost-server-path=/tmp/dpdkvhostclient0

此功能仅对dpdkvhostuserclient类型端口可用.

存在这样一个限制,即如果来自设置了dq-zero-copy=true的vHost端口的数据包,目的地是dpdk类型端口,此端口的发送描述符数量(n_txq_desc)必须减少到一个较小的值,128为推荐值。这可以通过执行以下命令来实现:

$ ovs-vsctl set Interface dpdkport options:n_txq_desc=128

注意:VM将发送报文到的所有dpdk端口的TX描述符之和不应超过128。例如,如果绑定了两个物理端口,工作在balance-tcp模式的聚合接口,必须将128除以聚合中的链接数。

参考dpdk-queues-sizes 获取更多信息.

这种限制的原因是由zero-copy功能的实现造成的。vHost设备的tx used vring,是用于跟踪使用的发送描述符的virtio结构,其仅在NIC释放相应的mbuf时更新。如果我们释放mbuf的频度不是足够快,VRing将处于饥饿状态,数据包将得不到处理。一种确保我们不会遇到这种情况方法,即将n_txq_desc配置为足够小的数字,以便更频繁的达到NIC的mbuf free threshold阈值,因此能更频繁地释放mbuf。建议值为128,但是值64和256也已经过测试和验证能够工作,但是具有不同的性能表现。如果客户机中的virtio队列大小增加到1024(可在QEMU 2.10及更高版本中配置),也可以使用512。此值的设置方式如下:

$ qemu-system-x86_64 ... -chardev socket,id=char1,path=<sockpath>,server
  -netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce
  -device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1,
  tx_queue_size=1024

由于此限制, 此功能被认为是实验性质的.

注意:

Post-copy Live Migration 与 Dequeue zero-copy 不兼容.

进阶信息可参考文档DPDK documentation

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值