OVS DPDK的安装使用

网上关于dpdk的技术文章有很多,虽然前段时间也去调研了一下该技术,看了些文章,简单做了点实践,但是感觉理解的不透彻,就不在这里讲dpdk的大道理来误导大家了。
简单说说自己使用ovs dpdk遇到的问题及解决方法吧。
稍微啰嗦两句,DPDK 不是网络协议栈,不提供诸如三层转发、IPsec、防火墙之类的功能。DPDK是一个开源的数据平面开发工具集,提供了一个用户空间下的高效数据包处理库函数,它通过环境抽象层旁路内核协议栈、轮询模式的报文无中断收发、优化内存/缓冲区/队列管理、基于网卡多队列和流识别的负载均衡等多项技术,实现了在x86处理器架构下的高性能报文转发能力,用户可以在Linux用户态空间开发各类高速转发应用。它的几大关键技术就是: 大页技术,轮询技术和cpu亲和技术。


一、怎么看你的网卡是否支持dpdk
最简单的方法,从其官方文档 http://dpdk.org/doc/nics可以查到支持的厂商及型号;
稍微复杂点的方法,可以查看lib/librte_eal/common/include/rte_pci_dev_ids.h  这文件,步骤如下:
/sbin/ethtool -i eth0|grep bus-info 
cat /sys/bus/pci/devices/0000\:01\:00.0/device 或者lspci -nn|grep Ethernet 得到[8086:10fb] 后面的10fb即设备号
再拿着0x10fb 这个数去rte_pci_dev_ids.h 文件中找,如果有,说明支持你的网卡

二、怎么看你的cpu是否支持大页技术
一般的来说,我们可以通过查看cpu的flags来确定是否大页表。如果/proc/cpuinfo的flags表项里包含了pge项,表明支持2M的大页内存;
如果cpuflags包含了pdpe1gb,表明支持1G的大页内存。一般对于64位的应用来说,建议使用1GB的hugepage,并且在系统启动前就在bios里设置完毕


三、ovs dpdk安装前提条件、
DPDK: 16.07 (这个是当前最新的版本,支持packet capture框架)
OVS: 2.6  (从这个版本开始DPDK不再是experiment版本)
Kernel:3.6.0版本以上 (这个主要是需要支持VFIO)
QEMU: >=2.2.0 (主要是需要支持vhost user这个参数)
网卡:宿主机至少双网卡,选择intel或者amd的,具体型号参见dpdk.org/doc/nics。
关于内核版本,在安装的时候还遇到过一个问题,启动ovs-vswitchd,报错Requested device 0000:01:00.0 cannot be used
查了查代码,发现是在EAL初始化的时候调用一个函数rte_eal_pci_map_device,在这里有一个宏VFIO_PRESENT发现其没定义,而从代码看,只要内核版本大于3.6,这个宏肯定会定义,当时我用的内核版本是3.10.45,按理无论如何应该没问题。 最后才发现,我们内核版本和其libc的库版本不匹配,
因为LINUX_VERSION_CODE这个是在linux/version.h定义的,这个文件在包linux-libc-dev中,更新一下包版本到对应的内核版本就解决了。

四、编译和安装
1.首先需要预留内存:
为支持 hugepage 并使用 VFIO 用户空间驱动程序,将参数附加至下列 /etc/default/grub 中的 GRUB_CMDLINE_LINUX,
然后运行 grub 更新并重启系统然后mount:
default_hugepagesz=1G hugepagesz=1G hugepages=16 hugepagesz=2M hugepages=2048 iommu=pt intel_iommu=on
mkdir /dev/huge
mount -t hugetlbfs nodev /dev/huge
如果不想使用VFIO, 我们也可以使用igb_uio,此时的iommu这两个选项可以不开。
如果仅仅想使用2M的大页内存,也可以在系统启动后再预留:
echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
以上命令对于有两个NUMA node的系统每个socket预留了2G内存。
启动完毕后,可通过grep Huge  /proc/meminfo 查看内存预留情况。
2.其次编译和安装OVS DPDK:
DPDK_TARGET选择x86_64-native-linuxapp-gcc,ovs的configure配置带上--with-dpdk=$DPDK_BUILD(就是DPDK_TARGET所在的目录),其他和以前并没有什么区别。  如果需要dpdk的packet dump功能,则需要打开DPDK的编译选项CONFIG_RTE_LIBRTE_PMD_PCAP,CONFIG_RTE_LIBRTE_PDUMP 以及RTE_PORT_PCAP
3.启动VSWITCHD
首先需要给物理网卡换驱动,若使用vfio方式,则:
modprobe vfio-pci
tools/dpdk-devbind.py --bind=vfio-pci eth1
注意一下,属于同一个IOMMU group的网卡需要同时更改其驱动,否则在vswitchd启动的时候会报错VFIO group is not viable。通过命令行find /sys/kernel/iommu_groups/ -type l可以查出所有pci设备的IOMMU group。
若使用uio方式,则:
modprobe uio
insmod kmod/igb_uio.ko
vswitchd启动的时候要将dpdk-init置为true然后按正常方式启动就可以了。
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
4.启动qemu
ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev
ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk
ovs-vsctl add-port br0 dpdkvhostuser0 -- set Interface dpdkvhostuser0 type=dpdkvhostuser
注意要把bridge的类型设置为netdev,dpdk类型的端口和绑定的物理网卡一一对应,也就是说绑定了多少个vfio-pci驱动的端口,就只能创建多少个dpdk类型的端口,要不然会报错“could not open network device dpdk0”
QEMUBINnameVM_NAME -enable-kvm -cpu host -m GUESTMEMobjectmemorybackendfile,id=mem,size=GUEST_MEM,mem-path=/dev/hugepages,share=on -numa node,memdev=mem -mem-prealloc -smp sockets=1,cores=1 -drive file= QCOW2IMAGEchardevsocket,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  --nographic –snapshot
启动qemu的时候其内存不得小于hugepage的大小,比如如果是1G的pagesize,则内存必须大于1G,不然会有报错” memory size 0x20000000 must be equal to or larger than huge page size 0x40000000”


五、参数说明
在vswitchd启动的时候,我们还可以设置其他的一些DPDK的EAL参数,来增强报文处理能力,比如线程的亲和性。
dpdk-lcore-mask可以设置thread使用的core list,这是一个16进制的数值,每个bit代表一个logical core,其中最低一个有效的lcore被用作master core,用于和vswitchd衍生出所有其他线程绑定;其他的lcore用于做slave core,主要用于做packet forwarding。
pmd-cpu-mask用于设置pmd thread的cpu亲和性,这里的lcore必须包含在dpdk-lcore-mask里面,比如若dpdk-lcore-mask设置为0XFF, 而pmd-cpu-mask却设置为F00,则设置无效。每个NUMA node都可以有一个或多个pmd thread,不过特定的NUMA node上有没有pmd线程,要看该NUMA node有没有相应的端口。一般来说,物理网卡类型的端口其NUMA node要看其和node的绑定关系,可以通过/sys/bus/pci/devices/0000:01:00.1/numa_node来查看网卡所属的numaid,其他类型的端口其numaid则是其线程所绑定的cpu核所在的numa node。
pmd-rxq-affinity用来设置queue和cpu的亲和性。一般的,一个端口创建的时候会默认有一个rxq和txq。不过我们可以修改dpdk端口的rxq数目和每个queue与cpu的绑定关系。

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者陈跃芳授权发布。