Open vSwitch结合DPDK的使用

Open vSwitch结合DPDK的使用

本文档描述Open vSwitch结合DPDK数据路径的使用。

重点:
要使用DPDK数据路径功能需要在OVS编译时开启DPDK支持选项。OVS与DPDK的版本对应关系可能随发布版本不同而变化。版本对应信息可参考OVS文档releases FAQ。编译指令可参考/intro/install/dpdk。

接口和网桥

ovs-vsctl工具可用来创建网桥和其它Open vSwitch支持的特性。网桥创建时应指定选项datapath_type=netdev::

    $ ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev

ovs-vsctl工具也可用来添加DPDK设备。ovs-vswitchd应在日志文件中打印发现到的DPDK设备数量::

    $ ovs-vsctl add-port br0 dpdk-p0 -- set Interface dpdk-p0 type=dpdk \
        options:dpdk-devargs=0000:01:00.0
    $ ovs-vsctl add-port br0 dpdk-p1 -- set Interface dpdk-p1 type=dpdk \
        options:dpdk-devargs=0000:01:00.1

一些网卡(如,Mellanox ConnectX-3)仅有一个PCI地址关联与多个网口。以上的配置方式将无法工作。所以,建议以下的用法::

    $ ovs-vsctl add-port br0 dpdk-p0 -- set Interface dpdk-p0 type=dpdk \
        options:dpdk-devargs="class=eth,mac=00:11:22:33:44:55"
    $ ovs-vsctl add-port br0 dpdk-p1 -- set Interface dpdk-p1 type=dpdk \
        options:dpdk-devargs="class=eth,mac=00:11:22:33:44:56"

重点:

以上语法不支持热插拔的物理接口。此缺陷有望在DPDK v18.05的发布版中解决。关于物理口热插拔的信息,应参考port-hotplug。

在DPDK接口添加到网桥之后,轮询线程将不停的检测DPDK设备,消耗处理核心100%的资源,可通过以下的topps 命令查看::

    $ top -H
    $ ps -eLo pid,psr,comm | grep pmd

创建DPDK接口的聚合链路与创建系统接口的聚合链路稍有不同。对于DPDK而言,接口类型type和devarfs参数必须明确的指定。如下列::

    $ ovs-vsctl add-bond br0 dpdkbond p0 p1 \
        -- set Interface p0 type=dpdk options:dpdk-devargs=0000:01:00.0 \
        -- set Interface p1 type=dpdk options:dpdk-devargs=0000:01:00.1

要停止ovs-vswitchd服务,删除网桥,执行以下的命令::

    $ ovs-appctl -t ovs-vswitchd exit
    $ ovs-appctl -t ovsdb-server exit
    $ ovs-vsctl del-br br0

虚拟机内部的OVS与DPDK

如果你打算在QEMU虚拟机内部运行以DPDK作为后端的ovs-vswitchd服务,需要进行额外的配置。ovs-vswitchd服务为每个可用的处理器核心创建单独的DPDK发送队列。但是默认情况下,提供给客户机的VirtIO网卡仅支持单一的发送和接收队列,导致ovs-vswitchd在QEMU虚拟机中操作失败。为改变此行为,你需要为所有QEMU模拟并提供于DPDK使用的virtio-net-pci驱动网卡开启mq(多队列)的属性。你可以手动开启(修改QEMU命令行参数)或者,如果使用Libvirt,在所有DPDK使用的网路设备的部分增加以下的字符串::

    

where:

N
定义有多少队列可被客户机使用.

此配置需要 QEMU >= 2.2.

PHY-PHY

添加一个用户空间网桥和两个dpdk (PHY) 网口::

    # 添加用户空间网桥
    $ ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev

    # 添加两个DPDK网口
    $ ovs-vsctl add-port br0 phy0 -- set Interface phy0 type=dpdk \
          options:dpdk-devargs=0000:01:00.0 ofport_request=1

    $ ovs-vsctl add-port br0 phy1 -- set Interface phy1 type=dpdk
          options:dpdk-devargs=0000:01:00.1 ofport_request=2

添加测试流以便在DPDK网口0和1之间转发报文::

    # 清空当前流
    $ ovs-ofctl del-flows br0

    # 添加网口 1 (phy0) 与网口2 (phy1)之间流
    $ ovs-ofctl add-flow br0 in_port=1,action=output:2
    $ ovs-ofctl add-flow br0 in_port=2,action=output:1

在任一网口发送流量,应当由另外一个网口观察到返回的相同流量。

PHY-VM-PHY (vHost 回环)

添加用户空间网桥,两个dpdk (PHY)网口,以及两个dpdkvhostuser网口::

    # 添加用户空间网桥
    $ ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev

    # 添加两个DPDK网口
    $ ovs-vsctl add-port br0 phy0 -- set Interface phy0 type=dpdk \
          options:dpdk-devargs=0000:01:00.0 ofport_request=1

    $ ovs-vsctl add-port br0 phy1 -- set Interface phy1 type=dpdk
          options:dpdk-devargs=0000:01:00.1 ofport_request=2

    # 添加两个 dpdkvhostuser 网口
    $ ovs-vsctl add-port br0 dpdkvhostuser0 \
        -- set Interface dpdkvhostuser0 type=dpdkvhostuser ofport_request=3
    $ ovs-vsctl add-port br0 dpdkvhostuser1 \
        -- set Interface dpdkvhostuser1 type=dpdkvhostuser ofport_request=4

添加测试流以便在DPDK设备与VM网口之间转发报文::

    # 清空当前流
    $ ovs-ofctl del-flows br0

    # 添加流
    $ ovs-ofctl add-flow br0 in_port=1,action=output:3
    $ ovs-ofctl add-flow br0 in_port=3,action=output:1
    $ ovs-ofctl add-flow br0 in_port=4,action=output:2
    $ ovs-ofctl add-flow br0 in_port=2,action=output:4

    # Dump flows
    $ ovs-ofctl dump-flows br0

按照以下配置创建虚拟机:

Configuration Values Comments
QEMU version 2.2.0 n/a
QEMU thread affinity core 5 taskset 0x20
Memory 4GB n/a
Cores 2 n/a
Qcow2 image CentOS7 n/a
mrg_rxbuf off n/a

你可通过QEMU的qemu-system-x86_64应用直接完成以上配置::

    $ export VM_NAME=vhost-vm
    $ export GUEST_MEM=3072M
    $ export QCOW2_IMAGE=/root/CentOS7_x86_64.qcow2
    $ export VHOST_SOCK_DIR=/usr/local/var/run/openvswitch

    $ taskset 0x20 qemu-system-x86_64 -name $VM_NAME -cpu host -enable-kvm \
      -m $GUEST_MEM -drive file=$QCOW2_IMAGE --nographic -snapshot \
      -numa node,memdev=mem -mem-prealloc -smp sockets=1,cores=2 \
      -object memory-backend-file,id=mem,size=$GUEST_MEM,mem-path=/dev/hugepages,share=on \
      -chardev socket,id=char0,path=$VHOST_SOCK_DIR/dpdkvhostuser0 \
      -netdev type=vhost-user,id=mynet1,chardev=char0,vhostforce \
      -device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1,mrg_rxbuf=off \
      -chardev socket,id=char1,path=$VHOST_SOCK_DIR/dpdkvhostuser1 \
      -netdev type=vhost-user,id=mynet2,chardev=char1,vhostforce \
      -device virtio-net-pci,mac=00:00:00:00:00:02,netdev=mynet2,mrg_rxbuf=off

关于以上命令以及其它可用的配置实现方法,诸如通过libvirt启动虚拟机等的解释,请参考[/topics/dpdk/vhost-user].

一旦客户机配置好并完成启动,配置DPDK报文在客户机中的转发。要完成此配置,按照[dpdk-testpmd]中的描述编译testpmd。编译完成之后,启动应用::

    $ cd $DPDK_DIR/app/test-pmd;
    $ ./testpmd -c 0x3 -n 4 --socket-mem 1024 -- \
        --burst=64 -i --txqflags=0xf00 --disable-hw-vlan
    $ set fwd mac retry
    $ start

完成测试之后,将虚拟网卡绑定会内核驱动::

    $ $DPDK_DIR/usertools/dpdk-devbind.py --bind=virtio-pci 0000:00:03.0
    $ $DPDK_DIR/usertools/dpdk-devbind.py --bind=virtio-pci 0000:00:04.0

注意::

以上示例中必须制定有效的PCI IDs。PCI IDs可使用以下命令获取::

      $ $DPDK_DIR/usertools/dpdk-devbind.py --status

更多关于dpdkvhostuser网口的信息可参见[/topics/dpdk/vhost-user].

PHY-VM-PHY (vHost 回环) (内核转发)

上节[dpdk-vhost-loopback] 详述了PHY-VM-PHY 回环拓扑的测试用例步骤,其中报文的转发使用客户机中的DPDK testpmd应用完成。对于希望内核协议栈完成报文转发的用户,需要在客户机中执行以下的命令::

    $ ip addr add 1.1.1.2/24 dev eth1
    $ ip addr add 1.1.2.2/24 dev eth2
    $ ip link set eth1 up
    $ ip link set eth2 up
    $ systemctl stop firewalld.service
    $ systemctl stop iptables.service
	# 打开IPv4转发功能
    $ sysctl -w net.ipv4.ip_forward=1
	# 关闭反向路径过滤(Reverse Path Filtering)
    $ sysctl -w net.ipv4.conf.all.rp_filter=0
    $ sysctl -w net.ipv4.conf.eth1.rp_filter=0
    $ sysctl -w net.ipv4.conf.eth2.rp_filter=0
    $ route add -net 1.1.2.0/24 eth2
    $ route add -net 1.1.1.0/24 eth1
	# 添加静态邻居表项
    $ arp -s 1.1.2.99 DE:AD:BE:EF:CA:FE
    $ arp -s 1.1.1.99 DE:AD:BE:EF:CA:EE

PHY-VM-PHY (vHost 多队列)

vHost多队列功能也可使用PHY-VM-PHY配置拓扑来验证。首先,遵照[dpdk-phy-phy]一节描述的步骤创建和初始化数据库,启动ovs-vswitchd服务,并且添加dpdk类型设备到网桥br0中。完成之后,执行以下的步骤:

  1. 配置PMD和RXQs.

    例如,DPDK网口的接收队列数量至少设置为2,vHost-user接口的接收队列数量在virtio设备连接之后将被自动配置,不需要手动配置::

       $ ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0xc
       $ ovs-vsctl set Interface phy0 options:n_rxq=2
       $ ovs-vsctl set Interface phy1 options:n_rxq=2
  1. 通过QEMU命令行实例化虚拟机

    我们必须使用合适的软件版本以确保此特性是被支持的。

Setting value
QEMU version 2.5.0
QEMU thread affinity 2 cores (taskset 0x30)
Memory 4 GB
Cores 2
Distro Fedora 22
Multiqueue Enabled

以下命令实例化客户机::

       $ export VM_NAME=vhost-vm
       $ export GUEST_MEM=4096M
       $ export QCOW2_IMAGE=/root/Fedora22_x86_64.qcow2
       $ export VHOST_SOCK_DIR=/usr/local/var/run/openvswitch
       $ taskset 0x30 qemu-system-x86_64 -cpu host -smp 2,cores=2 -m 4096M \
           -drive file=$QCOW2_IMAGE --enable-kvm -name $VM_NAME \
           -nographic -numa node,memdev=mem -mem-prealloc \
           -object memory-backend-file,id=mem,size=$GUEST_MEM,mem-path=/dev/hugepages,share=on \
           -chardev socket,id=char1,path=$VHOST_SOCK_DIR/dpdkvhostuser0 \
           -netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce,queues=2 \
           -device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1,mq=on,vectors=6 \
           -chardev socket,id=char2,path=$VHOST_SOCK_DIR/dpdkvhostuser1 \
           -netdev type=vhost-user,id=mynet2,chardev=char2,vhostforce,queues=2 \
           -device virtio-net-pci,mac=00:00:00:00:00:02,netdev=mynet2,mq=on,vectors=6

注意::
以上队列数应匹配OVS中配置的队列数目,参数vector的值应当设置为"number of queues x 2 + 2"。

  1. 配置客户机接口

    假设客户机有两个接口eth0,eth1,以下命令检查接口的channel配置,并且设置virtio设备的combined channel数目为2::

       $ ethtool -l eth0
       $ ethtool -L eth0 combined 2
       $ ethtool -L eth1 combined 2

更多信息可参见vHost walkthrough一节。

  1. 配置内核报文转

    配置IP地址并使能接口::

       $ ip addr add 5.5.5.1/24 dev eth0
       $ ip addr add 90.90.90.1/24 dev eth1
       $ ip link set eth0 up
       $ ip link set eth1 up

配置IP转发,并添加路由条目::

       $ sysctl -w net.ipv4.ip_forward=1
       $ sysctl -w net.ipv4.conf.all.rp_filter=0
       $ sysctl -w net.ipv4.conf.eth0.rp_filter=0
       $ sysctl -w net.ipv4.conf.eth1.rp_filter=0
       $ ip route add 2.1.1.0/24 dev eth1
       $ route add default gw 2.1.1.2 eth1
       $ route add default gw 90.90.90.90 eth1
       $ arp -s 90.90.90.90 DE:AD:BE:EF:CA:FE
       $ arp -s 2.1.1.2 DE:AD:BE:EF:CA:FA

查看多个队列上的流量::

       $ cat /proc/interrupts | grep virtio

流的硬件卸载 (实验性质)

默认情况下,流的硬件卸载功能是关闭的,可使用如下命令开启::

    $ ovs-vsctl set Open_vSwitch . other_config:hw-offload=true

目前为止,仅实现了部分流卸载。而且,仅在PMD驱动的rte_flow动作支持"MARK + RSS"的条件下工作。

验证过的网卡有:

  • Mellanox (ConnectX-4, ConnectX-4 Lx, ConnectX-5)
  • Napatech (NT200B01)

硬件卸载支持的协议有:

  • L2: Ethernet, VLAN
  • L3: IPv4, IPv6
  • L4: TCP, UDP, SCTP, ICMP

延伸阅读

更多详细信息可参考DPDK topics section文档。

你可能感兴趣的:(DPDK,网络虚拟化,交换)