Release 17.02.0node
目录python
Linux环境下DPDK入门... 1linux
1 引言... 2c++
2 资料集... 2shell
3 系统需求... 2ubuntu
3.1 x86平台的先决条件BIOS设置... 2性能优化
3.2 编译DPDK. 3服务器
3.3 运行DPDK程序... 3数据结构
4 编译DPDK源码... 5架构
4.1 安装DPDK和浏览源码... 5
4.2 安装DPDK目标(target)开发环境... 6
4.3 浏览安装好的DPDK环境target. 6
4.4 加载DPDK用户态IO模块... 7
4.5 加载VFIO模块... 7
4.6 从内核模块绑定和解绑网卡... 7
5 编译和运行例子程序... 8
5.1 编译例子程序... 8
5.2 运行例子程序... 9
5.2.1 程序使用的逻辑核... 9
5.2.2 程序使用的大页内存... 10
5.3 其它例子程序... 10
5.4 其它的测试程序... 10
6 开启其它功能... 10
6.1 高精度定时器(HPET)功能... 10
6.1.1 BIOS支持... 10
6.1.2 linux内核支持... 11
6.2 非root用户运行DPDK程序... 11
6.3 电源管理和省电功能... 11
6.4 使用DPDK的CPU亲和性减小上下文切换的开销... 12
6.5 加载DPDK KNI内核模块... 12
6.6 使用linux IOMMU透传来在INTEL VT-d虚拟化环境下运行DPDK. 12
6.7 40G网口高性能小包处理... 12
6.7.1 使用16个字节的RX描述符... 12
6.7.2 高性能和报文时延间的均衡... 12
7 快速安装启动脚本... 12
7.1 脚本结构... 13
7.2 用例... 13
7.3 应用程序... 15
8 怎么在intel平台上得到网卡的最好性能... 17
8.1 硬件和内存需求... 17
8.1.1 网卡需求... 18
8.1.2 BIOS设置... 18
8.1.3 Linux内核启动参数... 18
8.2 运行DPDK前的配置... 18
8.3 获取intel网卡的最好性能例子... 19
文档是安装配置DPDK操做说明,旨在帮助客户快速上手和运行程序。文档介绍了在linux开发环境下如何编译和运行DPDK程序,可是并不深刻细节。
以前曾经尝试着翻译来着,当时由于要离职,一时兴起就想着翻译,翻译的太烂,如今从新翻译,一方面是方便新入职的同事可以快速入门,另一方面是如今工做的须要,还有一方面是学习KVM想休息一下,看内存那块弄得头昏脑胀,并且后面的例子会涉及到虚拟话那块的。下一个将翻译样例那本书(以及在本身机器上运行可能遇到的问题),同时会参杂着介绍开发者手册中的一些我的理解。
下面列出了全部DPDK文档资料的建议读取顺序:
l 版本说明:提供了各个版本相关的信息,包括支持的特性,限制,修复的bug,出现的问题等等。也对频繁提到的问题以FAQ的方式作了回答。
l 入门手册(本文的):讲述了如何安装配置DPDK;意在帮助开发者快速上手和运行程序。
l 开发者手册:
n 软件架构和(经过例子)在linux环境下使用它
n DPDK的内容包括构建系统(包括在DPDK根目录下构建开发环境和程序使用的命令)和移植程序指南。
n 在已有软件和要新开发的软件中须要考虑到的优化。
还提供了一个专有术语表。
l API索引:提供了DPDK函数,数据结构和其它开发用到的结构体的详细信息。
l 范例用户手册:介绍了一系列的范例程序。每个章节介绍一个程序,展现程序的特殊功能,说明如何编译,运行和使用范例程序。
本章介绍了编译DPDK须要的安装包。
注意:若是DPDK要运行在intel 89xx系统通信芯片平台,请翻阅对应该系列的linux入门手册。
对于主流的平台,使用DPDK的基本功能并不须要专门的BIOS设置,然而,对于额外的功能像HPET(高精度定时器),电量管理功能,以及在40G网卡上高性能小包处理,须要修改BIOS设置。修改设置的详细信息见第六章。
须要的工具:
注意:已经在Fedora18上测试运行过,在其它系统上安装命令和须要的安装包可能不同,要知道其它版本linux发行版测试详细的细节,请查看DPDK版本说明。
l GNU make
l coreutils:cmp,sed,grep,arch,等等。
l gcc:4.9版本或者是全部平台带的更新的版本。在一些gcc版本中,不少特殊的编译标志和连接标志默认是打开的,会影响到性能(好比,-fstatck-protector)。请查阅对应版本的文档和执行gcc –dumpspecs。
l libc hreaders,一般打包成gcc-multilib(intel 64位架构上是glibc-devel.i686/libc6-dev-i386;glibc-devel.x86_64/libc6-dev,IBM power架构则是glibc-devel.ppc64)
l 编译内核模块须要的内核头文件和源文件(kernel-devel.x86_64;kernel-devel.ppc64)
l 在64位机器上编译32位程序而外须要的库:
n glibc.i686, libgcc.i686, libstdc++.i686 and glibc-devel.i686 for Intel i686/x86_64;
n glibc.ppc64, libgcc.ppc64, libstdc++.ppc64 and glibc-devel.ppc64 for IBM ppc_64;
注意:x86_x32 ABI库旨在ubuntu13.10以上版本或者最新Debian版本上支持。只支持gcc4.9+版本。
l python,要使用dpdk安装包中各类帮助脚本必需的python版本2.7+或者是3.2+。
其它的工具:
l intel编译器icc:须要安装额外的库。在编译器安装文档看中icc安装说明。
l IBM powerlinux高级工具链:这是一系列的开源开发工具和运行时库,可以让用户用到IBM最新的power硬件特性。要安装的话看IBM的官方安装文档。
l libpcap头文件和库(libpcap-devel)编译和使用基于libpcap的轮询驱动。这个驱动默认是禁用的,能够经过修改编译时的配置文件参数CONFIG_RTE_LIBRTE_PMD_PCAP=y来打开。
l libarchive头文件和库在单元测试用打开源文件用到。
要运行DPDK程序,在目的机器上须要一些定制化的东西。
要求:
l 内核版本>=2.6.34:经过命令uname –r查看内核版本号
l glibc>=2.7(要用到cpuset特性):能够经过命令ldd –version命令查看gcc版本号
l 内核配置
在Fedora操做系统和其它通用发行版,例如Ubuntu,红帽企业版linux,发行商提供的内核配置基本能够跑绝大多数DPDK程序。
对于在其它内核上构建DPDK,下面几个选项须要能支持:
n UIO(用户态IO)
n HUGETLBFS(大页内存)
n PROC_PAGE_MONITOR支持
n HPET和HPET_MMAP配置项必须打开,若是用到HPET,具体细节看第六章。
对于大的报文内存池内存分配,大页内存是必须的。(前一章说过运行的内核必须支持大页内存)。使用大页内存来分配,即便是小部分页要用到,性能也可以获得提高。减小了TLBmiss,对应就减小了虚拟地址转物理地址的时间。使用小页4K内存页,很高频率的TLBmiss发生会致使性能低下。
申请大页给DPDK使用
大页内存的分配最好是在系统启动时或者是尽可能在系统启动后越早越好,这样能够减小分配的物理内存页物理地址碎片化。申请大页内存须要在内核启动时传递一个命令行参数。
对于2MB内存页,分配1024个2MB内存页参数以下:
hugepages=1024
其它尺寸的大内存页,例如1G页,必须指定申请的内存页个数和默认内存页的大小。例如分配4个1G的内存页,须要指定的参数以下:
default_hugepagesz=1G hugepagesz=1G hugepages=4
注意:大页内存的尺寸是CPU支持的大小来决定的。intel的机器上经过查看CPU flags来查看支持的大页内存尺寸。好比pse 表明支持2MB的内存页,pdpe1gb表明支持1G内存页。在IBM power架构机器上,支持大页内存尺寸为16MB和16GB。
注意:对于64位的应用,若是平台支持,建议使用1G内存页。
在双插槽的NUMA系统中,申请的大页内存通常会平均在两个socket上分配(假定两个socket都有足够的内存)。
能够看linux内核源码树中Documentation/kernel-parameters.txt获取更多内核选项的细节。
备选项:
对于2M的页,能够在系统启动后申请分配。echo想要分配的大页内存页个数到/sys/devices目录下的nr_hugepages文件。对于单NUMA(非NUMA)节点的系统,以下命令所示(假设须要1024个2M页):
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
在一个NUMA机器上,分别在不一样node上分配指定数目的内存页:
echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
注意:1G的内存页在系统启动后是没法申请。
DPDK使用大页
一旦申请到大页内存,要想其被DPDK使用到,执行如下步骤:
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
要想是挂载即便是重启也永久有效,须要把下面一行加到/etc/fstab文件中:
nodev /mnt/huge hugetlbfs defaults 0 0
1GB内存页,必须在挂载的时候将内存页的大小做为参数指定:
nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
现有的内存管理基于linux内核的大页机制。在Xen虚拟机管理器上,大页内存对非特权域(DomainU)的支持意味着DPDK在客户机上能够像普通机器上同样跑。
然而,特权域(domain0)并不支持大页内存。须要插入新的内核模块rte_dom0_mm以便绕过这个限制来申请和映射大页内存,经过ioctl来申请,mmap来映射。
开启DPDK对Xen Dom0支持
默认状况下,Xen Dom0模式支持在DPDK的build配置文件中是禁用的。要想支持Xen Dom0,配置项CONFIG_RTE_LIBRTE_XEN_DOM0须要在编译时改为y。
此外,配置项CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID也必须置成y,以防万一收到错误的socket ID。
加载rte_dom0_mm模块
要在Xen Dom0中跑dpdk程序,rte_dom0_mm模块必须带上rsv_memsize参数加载到运行的内核中。能够在编译的DPDK目标目录的子目录中找到该模块。该模块的加载以下使用insmod命令(假设当前处于DPDK编译的目标目录下):
sudo insmod kmod/rte_dom0_mm.ko rsv_memsize=X
X的值能够大于4095MB。
配置DPDK使用的内存
在rte_dom0_mm.ko模块加载完成后,用户必须配置DPDK使用的内存。将须要的内存大小echo到/sys/devices/目录下的memsize文件中便可。使用以下命令(假设须要2048MB内存):
echo 2048 > /sys/kernel/mm/dom0-mm/memsize-mB/memsize
用户也能够检查已经使用了多少内存:
cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_rsvd
Xen Dom0不支持NUMA配置,因此参数--socket-mem对于Xen Dom0是无效的。
注意:内存大小值不能超过rsv_memsize值。
在Xen Domain0中运行DPDK程序
要跑DPDK程序须要额外提供一个命令行参数--xen-dom0。
注意:本章写的部分安装过程也能够经过后续<快速安装脚本>一章中描述的脚本实现。
首先,解压压缩包并移动到解压的DPDK源码目录:
tar xJf dpdk-<version>.tar.xz
cd dpdk-<version>
DPDK包含如下几个子目录:
l lib:DPDK库的源码
l drivers:DPDK轮询驱动的源码
l app:DPDK应用程序的源码(自动化测试)
l examples:DPDK应用程序样例源码
l config,buildtools,mk:框架相关的Makefiles,脚本和配置文件
DPDK target格式是:
ARCH-MACHINE-EXECENV-TOOLCHAIN
详解:
l ARCH 能够是:i686,x86_64,ppc_64
l MACHINE 能够是:native,power8
l EXECENV 能够是:linuxapp,bsdapp
l TOOLCHAIN 能够是:gcc,icc
将要被安装的target环境取决于要安装的机器上的包是32位仍是64位。能够编译产生的target在DPDK/config目录下定义了。不要用defconfig_前缀,就是编译的时候不要带上这个前缀。
注意:配置文件是RTE_MACHINE下的最优配置集合。在配置文件中,RTE_MACHINE被定义为native,意味着这是针对本机环境下最佳优化的编译。对于这些设置的更多信息,能够采用的值,看DPDK开发者手册。
当使用ICC编译器时,下面的命令分别对应32位和64位环境使用。注意这个shell脚本更新$PATH环境变量,所以换个会话就失效了。编译安装的目录多是不一样的:
source /opt/intel/bin/iccvars.sh intel64
source /opt/intel/bin/iccvars.sh ia32
安装和生成target,在DPDK的根目录下使用make install T=<target> 命令。
例如,使用icc编译64位target:
make install T=x86_64-native-linuxapp-icc
使用gcc编译32位的:
make install T=i686-native-linuxapp-gcc
只是作建立target的准备,而不是编译,例如,在编译以前须要手动修改配置文件的,使用命令make config T=<target>:
make config T=x86_64-native-linuxapp-gcc
警告:
任何内核模块,好比igb_uio,kni等,必须编译时的内核和要运行时的内核一致。若是DPDK不是在编译产生的目标机器上运行, RTE_KERNELDIR环境变量必须指向要运行target机器对应内核版本。
一旦目标环境建立完成,用户可能须要进入目标环境目录,修改源码并从新编译。用户也可能修改编译时的DPDK配置项,经过编辑build目录下的.config文件(这个文件是从顶层目录的config目录下defconfig文件拷贝到本地来的):
cd x86_64-native-linuxapp-gcc
vi .config
make
此外,make clean命令能够清除全部以前编译留下的文件。
一旦target建立完成就包含全部的苦,包括轮询驱动,和用户程序编译须要的DPDK环境头文件。此外,test和testpmd程序在build/app目录下建立完成,可用于测试。kmod目录下包含须要加载到内核中的几个内核模块。
运行DPDK程序,一个合适的uio模块须要加载到运行中的内核。在不少例子中,标准的uio_pci_generic LINUX内核模块能够提供用户态驱动能力。该模块加载以下:
sudo modprobe uio_pci_generic
和上述不一样的是,DPDK提供了igb_uio模块来实现(在kmod目录下):
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
注意:对于缺少对传统中断支持的设备,好比VF设备,igb_uio模块可能须要被uio_pci_generic替换掉。
在DPDK1.7以前版本提供了对VFIO的支持,在支持VFIO的平台上UIO就不是必须的了。
使用VFIO的DPDK应用程序,vfiopci模块必须加载:
sudo modprobe vfio-pci
须要注意的是要使用VFIO,你的内核必须支持才行。VFIO内核模块在LINUX内核3.6.0版本以后就囊括经来了,默认是有的。然而,请翻阅linux发行版文档肯定一下。
使用VFIO,BIOS和内核都必须支持,BIOS须要打开支持虚拟化的配置选项(例如Intel® VT-d).
在非特权用户下运行DPDK程序,要正确的操做VFIO,须要创建正确的权限设置。这个能够经过DPDK安装脚本实现(dpdk-setup.sh,位于usertools目录下)
在1.4版本,DPDK程序再也不自动解绑全部支持DPDK的网口,当网口绑定在内核驱动上且正在运行时。取而代之的是,DPDK程序在运行前,必须将使用的全部网口绑定到uio_pci_generic,igb_uio或者是vfio-pci模块上。任何linux控制下的网口将被DPDK轮询驱动忽略,不能被DPDK程序使用。
警告:DPDK默认再也不在启动时自动解绑内核驱动管理的网口。任何PDDK程序使用的网口必须在程序运行前解除linux控制,绑定到对应的驱动上(uio_pci_generic,igb_uio或者是vfio-pci).
将绑定到DPDK的网口解绑并交给linux控制,可使用usertool子目录下的dpdk_nic_bind.py脚本。这个脚本能够展现当前系统中全部网口的状态,能够将其从不一样的内核模块间解绑和绑定,包括uio和vfio模块。下面是使用脚本的例子。要想获取脚本的所有使用描述和参数,能够带上—help或者是—usage参数启动脚本。注意,uio或者是vfio内核模块须要在运行dpdk-nic-bind.py脚本以前加载到内核中。
查看系统中全部网口的状态:
./usertools/dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:82:00.0 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
0000:82:00.1 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
Network devices using kernel driver
===================================
0000:04:00.0 'I350 1-GbE NIC' if=em0 drv=igb unused=uio_pci_generic *Active*
0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=uio_pci_generic
0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=uio_pci_generic
0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=uio_pci_generic
Other network devices
=====================
<none>
绑定设备eth1,“04:00.1”到uio_pci_generic驱动上:
./usertools/dpdk-devbind.py --bind=uio_pci_generic 04:00.1
或者是:
./usertools/dpdk-devbind.py --bind=uio_pci_generic eth1
恢复设备82:00.0到原始的内核驱动上:
./usertools/dpdk-devbind.py --bind=ixgbe 82:00.0
本章讲的是怎么在DPDK环境下编译和运行程序。也指出了样例程序保存在哪里。
注意:本章写的部分安装过程也能够经过后续<快速安装脚本>一章中描述的脚本实现。
DPDK目标环境目录建立完成(例如x86_64-native-linuxapp-gcc),就包含了建立一个dpdk应用程序须要的库和头文件。
当在linux DPDK环境下编译程序,下面两个环境遍历必须export:
l RTE_SDK 指向DPDK编译安装目录即target所在目录
l RTE_TARGET 指向DPDK target目录名
下面展现的是运行在linux DPDK环境下的例子helloworld。能够在$RTE_SDK/examples目录下找到。
目录下包含main.c文件,默认编译生成的二进制文件在build目录下:
cd examples/helloworld/
export RTE_SDK=$HOME/DPDK
export RTE_TARGET=x86_64-native-linuxapp-gcc
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
ls build/app
helloworld helloworld.map
注意:在上面的例子中,helloworld是在DPDK框架目录中,为了保证DPDK框架的完整性,能够把helloworld移动到外部。在下面的例子中,helloworld被拷贝到一个新目录中从新编译。
export RTE_SDK=/home/user/DPDK
cp -r $(RTE_SDK)/examples/helloworld my_rte_app
cd my_rte_app/
export RTE_TARGET=x86_64-native-linuxapp-gcc
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
警告:必须在运行DPDK程序前安装好UIO驱动和大页内存。
警告:任何进程使用的网口在程序启动以前必须绑定到适当的内核模块上,如以前<从内核模块上绑定和解绑网卡>章节所述。
程序必须连接DPDK target环境EAL(环境抽象层)库,这个库提供了每个DPDK程序通用的选项。
下面是能够传递给EAL的参数列表:
./rte-app -c COREMASK [-n NUM] [-b <domain:bus:devid.func>] \
[--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] \
[--proc-type <primary|secondary|auto>] [-- xen-dom0]
EAL参数以下:
l -c COREMASK:要使用CPU core16进制掩码。注意core编号在不一样的平台不同,须要事先肯定好。
l -n NUM:每一个处理器socket的内存通道数
l -b <domain:bus:devid.func>:网口黑名单,EAL不能使用的PCI设备(能够同时存在多个-b选项)
l --socket-mem:在指定socket上分配大页内存
l -m MB:指定分配大大页内存数,不限处理器的socket。加以使用—socket-mem代替这个参数。
l -r NUM:内存的rank数
l -v:显示程序版本号
l --huge-dir:大页内存的挂载点
l --file-prefix:大页内存文件的前缀
l --proc-type:进程类型
l --xen-dom0:支持程序在Xen Domain0中非大页内存下运行
l --vmware-tsc-map:使用VMware TSC代替本地的RDTSC
l --base-virtaddr :指定虚拟地址的基址
l --vfio-intr:指定VFIO使用的中断类型(若是不是用VFIO则无效)
-c是必须的,其它都是可选的。
运行例子程序(假设该平台每一个处理器socket有4个内存通道,有4个cpu核,且程序都使用上):
./helloworld -c f -n 4
注意:--proc-type和—file-prefix EAL参数用于DPDK多进程。能够查阅DPDK范例程序一书中多进程章节和DPDK开发手册获取更多细节。
CPU核掩码参数是DPDK程序必须带上的。掩码的每一个bit位表明linux显示的每一个逻辑核的编号。不一样的平台之间,逻辑核编号和逻辑核编号与NUMA socket的映射关系是不一样的,因此建议在选在使用核以前先弄清楚该平台的核分布。
在初始化DPDK 环境抽象层时,会打印出要使用的逻辑核以及其所在的socket。这些信息也能够经过查看/proc/cpuinfo文件来知道,例如,执行 cat /proc/cpuinfo。每一个逻辑核的物理ID属性代表其属于哪一个CPU socket。
注意:逻辑核分布视图能够经过使用linux工具lstopo获取。在Fedora系统中,可使用下面的命令安装使用:
sudo yum install hwloc
./lstopo
警告:逻辑核的分布在不一样的主板上是不同的,在选择使用的核以前要检查一下。
运行DPDK程序,建议大页内存用多少就分配多少。若是没有传入-m或者是—socket-mem参数,DPDK程序在启动时自动完成。
若是实际使用的内存超过了传入参数值指定的值,程序将失败并退出。然而,若是用户要申请使用的内存小于预先分配的内存大小,特别是使用了-m选项时,程序自身也会失败。假定系统在socket0和socket1上各预先分配有1024个2MB内存页,用户请求使用128MB内存,64个页可能不符合要求:
l 内核给予应用程序分配的大页内存都在socket1上。这种状况下,若是应用程序试图在socket0上建立一个对象,好比一个无锁队列或者是内存池,程序会失败。要避免这种问题,建议使用—socket-mem选项代替-m选项。
l 那些大页内存在物理上是分布在各处的,然而DPDK EAL试图分配在物理地址上连续的一段内存,而可能现有的内存页不是连续的,这种情形下,应用程序没法申请大的内存池而失败。
socket-mem选项能够在指定的socket上分配指定大小的内存页。要想作到这个,就得在这个选项后面接上要在各个socket上分配内存大小,例如:--socket-mem=0,512,就是在socket1上分配512MB内存。同理,在4socket的系统中,只在socket0和2上各分配1GB内存:--socket-mem=1024,0,1024。某一个CPUsocket上没有内存分配,那么就不须要显式的引用,例如前面socket3就是。若是不能在指定的socket上分配到足够的内存,EAL初始化失败。
其它的例子程序在$RTE_SDK./example目录下。这些程序的编译和运行方式与本文中以前章节介绍的差很少。此外,能够查阅DPDK范例程序手册,该手册介绍了在编译和执行程序时的特殊命令参数,以及代码的说明。
另外,有两个额外的测试程序在DPDK库建立的时候编译出来。源码在DPDK/app目录下,名为test和testpmd。DPDK目标库建立完成,那么就能够在build/app目录中找到。
l test程序提供了DPDK各类函数的特定测试。
l testpmd程序提供了一些不一样的报文吞吐测试和特性,例如如何使用intel82599万兆网卡的Flow Director(引流)特性。
要使用HPET必须BIOS中支持,不然默认采用TSC。通常状况下,在系统启动的时候按F2键能够进入BIOS。用户能够开启HPET选项。在intel的Crystal Forest平台BIOS上,路径是Advanced -> PCH-IO Configuration -> High Precision Timer -> (Change from Disabled to Enabled if necessary).
在已经启动的系统中,下面的命令能够查看HPET是否开启:
grep hpet /proc/timer_list
若是返回为空,那么必须重启机器并在BIOS中开启HPET(重复上述的指令)。
DPDK经过将时间戳计数器映射处处理器地址空间来利用平台的HPET,如此须要HPET_MMAP内核配置项支持。
警告:在Fedora系统和其余通用linux发行版,例如ubuntu,HPET_MMAP内核选项是默认关闭的。带此参数从新编译内核,请查阅发行版文档了解相关操做。
在DPDK中使用HPET
默认状况下,DPDK编译配置文件中HPET选项是关闭的。要使用HPET,CONFIG_RTE_LIBEAL_USE_HPET配置项必须改为y,须要在编译时修改参数。
程序使用rte_get_hpet_cycles()和rte_get_hpet_hz()接口调用,在程序初始化时调用rte_eal_hpet_init()接口来将HPET做为rte_timer库的默认时间源。这个接口将确保HPET可用,若是不可用则返回错误值。例如,若是HPET_MMAP内核不支持。那么程序能够针对支持或者是不支持而决定采起什么动做。
注意:若是程序须要时间API,可是HPET不支持,建议采用rte_get_timer_cycles()和rte_get_timer_hz()接口代替HPET接口。这个通用接口既可使用TSC,也可使用HPET做为时间源,取决因而否在程序启动是调用rte_eal_hpet_init()接口,若是调用了的话,系统是否支持。
尽管程序经过DPDK可以直接使用网口和硬件资源,可是这些程序若是是做为普通用户而不是root用户,那么须要作一些小的权限调整。要实现这个,下面这些linux系统文件的全部者和权限必须调整,以便普通linux用户也能在使用DPDK的时候访问它们:
l 全部的大页内存挂载点目录,例如/mnt/huge
l 在/dev目录下的用户态IO设备文件,/dev/uio0,/dev/uio1,等等。
l 用户态IO系统文件配置和资源文件,例如uio0:
/sys/class/uio/uio0/device/config
/sys/class/uio/uio0/device/resource
l 若是要使用HPET,文件/dev/hpet
注意:在一些linux系统上安装时,/dev/hugepages会默认做为大页内存的挂载点建立。
若是要使用DPDK的电源管理功能,那么必须在平台BIOS中开启加强型INTEL SpeedStep(步进?)技术开关。不然,系统文件/sys/devices/system/cpu/cpu0/cpufreq不会存在,且基于CPU主频调节的电源管理就没法使用。查阅相关的BIOS文档肯定这些设置如何访问。
例如,在一些INTEL平台BIOS是不一致的,加强型INTEL SpeedStep技术的路径是:
Advanced
-> Processor Configuration
-> Enhanced Intel SpeedStep® Tech
此外,要开启电源管理C3和C6也同样要打开。C3和C6在一样的BIOS平台:
Advanced
-> Processor Configuration
-> Processor C3 Advanced
-> Processor Configuration
-> Processor C6
当一些线程被DPDK程序使用时,这些线程每个会被固定到系统中的一个逻辑核心上(一个线程对应一个逻辑核心),对于linux调度器来讲,也有可能会在这些核心上运行其余任务。为了阻止调度器将其余任务调度到DPDK使用的核心上,须要使用内核参数isolcpus来将这些核心从Linux调度器中隔离开来.
例如,DPDK程序使用逻辑核性2,4,6运行程序,下面的这个选项须要加到内核启动参数中:
isolcpus=2,4,6
要运行DPDK KNI例子程序,须要额外加载一个内核模块(kni模块)到运行的linux内核中。能够在DPDK target目录下的kmod目录中找到。同理如加载igb_uio模块,加载kni也是经过ismod命令来(假设咱们当前处于DPDK target目录下):
insmod kmod/rte_kni.ko
要在linxu内核中开启intel VT-d,一系列的内核配置项须要设置:
l IOMMU_SUPPORT
l IOMMU_API
l INTEL_IOMMU
此外,要在intel VT-d虚拟化环境下运行DPDK,当使用igb_uio驱动时,必须设置内核参数iommu=pt。这个是主机中DMAR(DMA Remapping(DMA地址重映射)透传的结果。INTEL_IOMMU_DEFAULT_ON在内核中也没有设置,内核参数inte_iommu=on必须使用。这能够确保intel IOMMU按照指望被初始化。
请注意,使用igb_uio驱动时必须使用iommu=pt参数,而vfio-pci驱动则是使用iommu=pt和iommu=on两者均可以运行。
在最新版本的固件镜像中,性能加强的问题解决了,固件更新能够获取更高的性能。用户须要检查本地的intel网卡驱动版本。用户须要查阅DPDK版本说明文档肯定这个版本对应的网卡i40E驱动版本。
i40e轮询驱动支持16和32字节的RX描述符大小,而16个字节的可以提供更高的小包处理性能。须要在配置文件中修改CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC参数为使用16个字节的RX描述符。
因为硬件设计的缘由,每一个报文描述符的回写须要在网卡内产生一个中断信号。最小的中断间隔须要在编译时修改配置文件中的CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL参数。尽管有默认配置,用户能够根据本身的实际状况,看是更在意性能仍是时延来调优这个参数。
dpdk-setup.sh脚本,在usertools子目录下,能够帮助用户执行下面的任务:
l 编译DPDK库
l 插入和移走DPDK IGB_UIO内核模块
l 插入和移走VFIO内核模块
l 插入和移走DPDK KNI内核模块
l 建立和删除NUMA和非NUMA下的大页内存
l 网口状态试图展现和分配网口给DPDK程序使用
l 为使用VFIO的非特权用户分配权限
l 运行test和testpmd程序
l 展现在meminfo中的大页信息
l 列出/mnt/huge中的大页
l 删除建立的DPDK库
dpdk-setup.sh脚本是用户按照用户的执行命令逻辑顺序来组织起来的一系列的步骤。每个步每一步都提供了一些提示信息帮助用户完成要求的任务。下面是每一步的简单概述。
step 1:编译DPDK库
最开始,用户必须选择一个DPDK target,匹配类型和编译选项,以便生成正确的库。
用户必须按照前面章节所述,将全部须要的库,模块,更新和编译须要的东西安装好。
step2:安装环境
用户配置DPDK程序运行所需的linux环境。大页内存的创建。任何已存的大页内存会被移除。DPDK用到的内核模块也在这步中插入,DPDK程序使用的网卡接口也绑定到对应的模块。
step3:运行程序
用户可能须要在上面步骤完成后运行test程序。test程序容许执行一系列的DPDK功能测试。testpmd支持收发包相关的测试。
step4:检查系统
这步提供了一些工具来检查系统的大页内存状态。
step5:系统还原
最后一步是恢复系统到原有的状态。
下面是一些使用dpdk-setup.sh脚本的用例。这个脚本应该使用source命令来运行。
警告:脚本须要在root权限下运行。
source usertools/dpdk-setup.sh
------------------------------------------------------------------------
RTE_SDK exported as /home/user/rte
------------------------------------------------------------------------
Step 1: Select the DPDK environment to build
------------------------------------------------------------------------
[1] i686-native-linuxapp-gcc
[2] i686-native-linuxapp-icc
[3] ppc_64-power8-linuxapp-gcc
[4] x86_64-native-bsdapp-clang
[5] x86_64-native-bsdapp-gcc
[6] x86_64-native-linuxapp-clang
[7] x86_64-native-linuxapp-gcc
[8] x86_64-native-linuxapp-icc
------------------------------------------------------------------------
Step 2: Setup linuxapp environment
------------------------------------------------------------------------
[11] Insert IGB UIO module
[12] Insert VFIO module
[13] Insert KNI module
[14] Setup hugepage mappings for non-NUMA systems
[15] Setup hugepage mappings for NUMA systems
[16] Display current Ethernet device settings
[17] Bind Ethernet device to IGB UIO module
[18] Bind Ethernet device to VFIO module
[19] Setup VFIO permissions
------------------------------------------------------------------------
Step 3: Run test application for linuxapp environment
------------------------------------------------------------------------
[20] Run test application ($RTE_TARGET/app/test)
[21] Run testpmd application in interactive mode ($RTE_TARGET/app/testpmd)
------------------------------------------------------------------------
Step 4: Other tools
------------------------------------------------------------------------
[22] List hugepage info from /proc/meminfo
------------------------------------------------------------------------
Step 5: Uninstall and system cleanup
------------------------------------------------------------------------
[23] Uninstall all targets
[24] Unbind NICs from IGB UIO driver
[25] Remove IGB UIO module
[26] Remove VFIO module
[27] Remove KNI module
[28] Remove hugepage mappings
[29] Exit Script
选项:
下面是展现选择建立x86_64-native-linuxapp-gcc DPDK库的例子:
Option: 9
================== Installing x86_64-native-linuxapp-gcc
Configuration done
== Build lib
...
Build complete
RTE_TARGET exported as x86_64-native-linuxapp-gcc
下面是展现插入DPDK UIO驱动的例子:
Option: 25
Unloading any existing DPDK UIO module
Loading DPDK UIO module
下面的选择是展现建立NUMA系统下的大页内存。分别在两个node上各分配1024个2MB内存页。那么程序就须要系统-m 4096参数来访问这两块内存。(若是没有提供-m参数,那么程序会自动执行)。
注意:若是提示移除临时文件,输入y。
Option: 15
Removing currently reserved hugepages
mounting /mnt/huge and removing directory
Input the number of 2MB pages for each node
Example: to have 128MB of hugepages available per node,
enter '64' to reserve 64 * 2MB pages on each node
Number of pages for node0: 1024
Number of pages for node1: 1024
Reserving hugepages
Creating /mnt/huge and mounting as hugetlbfs
下面是展现选择加载test程序到一个逻辑核上运行:
Option: 20
Enter hex bitmask of cores to execute test app on
Example: to execute app on cores 0 to 7, enter 0xff
bitmask: 0x01
Launching app
EAL: coremask set to 1
EAL: Detected lcore 0 on socket 0
...
EAL: Master core 0 is ready (tid=1b2ad720)
RTE>>
一旦用户运行dpdk-setup.sh脚本,编译EAL库,创建好大页内存(加入使用的是linxu EAL目标),用户可能接着会去编译和运行本身的程序或者是例子程序。
在/examples目录下的例子提供了解DPDK操做的好的起点。下面的命令展现了helloworld程序是怎么编译和运行的。如同上述章节建议的,<程序使用的逻辑核心>,逻辑核心在平台上的分布应该在选择程序使用的逻辑核掩码时肯定好。
cd helloworld/
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
sudo ./build/app/helloworld -c 0xf -n 3
[sudo] password for rte:
EAL: coremask set to f
EAL: Detected lcore 0 as core 0 on socket 0
EAL: Detected lcore 1 as core 0 on socket 1
EAL: Detected lcore 2 as core 1 on socket 0
EAL: Detected lcore 3 as core 1 on socket 1
EAL: Setting up hugepage memory...
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0add800000 (size = 0x200000)
EAL: Ask a virtual area of 0x3d400000 bytes
EAL: Virtual area found at 0x7f0aa0200000 (size = 0x3d400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9fc00000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9f600000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9f000000 (size = 0x400000)
EAL: Ask a virtual area of 0x800000 bytes
EAL: Virtual area found at 0x7f0a9e600000 (size = 0x800000)
EAL: Ask a virtual area of 0x800000 bytes
EAL: Virtual area found at 0x7f0a9dc00000 (size = 0x800000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9d600000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9d000000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9ca00000 (size = 0x400000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a9c600000 (size = 0x200000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a9c200000 (size = 0x200000)
EAL: Ask a virtual area of 0x3fc00000 bytes
EAL: Virtual area found at 0x7f0a5c400000 (size = 0x3fc00000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a5c000000 (size = 0x200000)
EAL: Requesting 1024 pages of size 2MB from socket 0
EAL: Requesting 1024 pages of size 2MB from socket 1
EAL: Master core 0 is ready (tid=de25b700)
EAL: Core 1 is ready (tid=5b7fe700)
EAL: Core 3 is ready (tid=5a7fc700)
EAL: Core 2 is ready (tid=5affd700)
hello from core 1
hello from core 2
hello from core 3
hello from core 0
本章是在INTEL平台上DPDK程序得到高性能的一步步引导。
要最好的性能最好是使用intel至强系列服务器,例如Ivy Bridge,Haswell或者是更新的架构的服务器。
确保每个内存通道至少有一个内存DIMM插入,且内存的大小至少4GB。注意:这个在性能上有最直接的影响。
你能够检查内存配置经过dmidecode命令,以下:
dmidecode -t memory | grep Locator
Locator: DIMM_A1
Bank Locator: NODE 1
Locator: DIMM_A2
Bank Locator: NODE 1
Locator: DIMM_B1
Bank Locator: NODE 1
Locator: DIMM_B2
Bank Locator: NODE 1
...
Locator: DIMM_G1
Bank Locator: NODE 2
Locator: DIMM_G2
Bank Locator: NODE 2
Locator: DIMM_H1
Bank Locator: NODE 2
Locator: DIMM_H2
Bank Locator: NODE 2
上面的输出展现了总共8个内存通道,每一个通道有2个DIMM。
也能够经过dmidecode命令肯定内存的频率:
dmidecode -t memory | grep Speed
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
Speed: 2133 MHzConfigured Clock Speed: 2134 MHz
Speed: Unknown
...
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
上述输出代表内存为2133MHz的DDR4内存。和前面的信息结合起来能够肯定每一个内存通道有一根内存条。
使用DPDK支持的高端网卡,好比INTEL XL710 40GBE。
确保每个网卡刷入了最新版本的固件。
使用PCIe Gen3插槽,例如Gen3 x8或者是Gen3 x16,由于PCIe Gen2插槽没法提供足够的宽带,2X10Gbe或者是更高。能够经过使用lspci命令检查PCI插槽的使用信息:
lspci -s 03:00.1 -vv | grep LnkSta
LnkSta: Speed 8GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- ...
LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete+ ...
当擦汗如网卡到PCI插槽时总要检查说明信息,例如CPU0或者是CPU1链接到的是哪一个socket上。
多考虑一下NUMA。若是你使用2个或者是更多的不一样的网口,最好确保这些网卡在一样的CPU socket上。如何肯定看下面的例子。
下面是推荐的BIOS设置项。不一样的平台上可能有不一样的BIOS名称,因此下面主要是做为参考:
下面是GRUB启动参数建议设置:
default_hugepagesz=1G hugepagesz=1G hugepages=8
isolcpus=2,3,4,5,6,7,8
iommu=pt intel_iommu=on
下面的shell命令有助于编译和配置DPDK。
# Build DPDK target.
cd dpdk_folder
make install T=x86_64-native-linuxapp-gcc -j
# Get the hugepage size.
awk '/Hugepagesize/ {print $2}' /proc/meminfo
# Get the total huge page numbers.
awk '/HugePages_Total/ {print $2} ' /proc/meminfo
# Unmount the hugepages.
umount `awk '/hugetlbfs/ {print $2}' /proc/mounts`
# Create the hugepage mount folder.
mkdir -p /mnt/huge
# Mount to the specific folder.
mount -t hugetlbfs nodev /mnt/huge
cd dpdk_folder
usertools/cpu_layout.py
# List all the NICs with PCI address and device IDs.
lspci -nn | grep Eth
举例说明,假设输出是这样的:
82:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
82:00.1 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.1 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
检查PCI设备所述的NUMA节点ID:
cat /sys/bus/pci/devices/0000\:xx\:00.x/numa_node
一般状况下,0x:00.x是位于socket0上,8x:00.x位于socket1上。注意:为了得到更高的性能,确保cpu核心和网卡在一样的socket上。例如上面的85:00.0在socket1上,那么它被socket1上的核心使用能得到最好的性能。
# Bind ports 82:00.0 and 85:00.0 to dpdk driver
./dpdk_folder/usertools/dpdk-devbind.py -b igb_uio 82:00.0 85:00.0
# Check the port driver status
./dpdk_folder/usertools/dpdk-devbind.py –status
查看dpdk-devbind.py –help获取更多细节。
下面是运行DPDK3层转发例子:l3fwd程序,使用intel服务器平台和intelXL710网卡获的高性能。对于特殊的40GbE午那个卡的配置请查阅i40e网卡手册。
这个例子展现的是在两个INTELXL710 40GbE网口下得到的最好性能。
82:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
./l3fwd -c 0x3c0000 -n 4 -w 82:00.0 -w 85:00.0 \
-- -p 0x3 --config '(0,0,18),(0,1,19),(1,0,20),(1,1,21)'
这表明着程序使用core18转发port0的队列0,core19转发port0的队列1,core20转发port1的队列0,core21转发port1的队列1。
a) 在发包器上建立一个流
b) 设置以太网II类型为0x8000