Linux平台上DPDK入门指南(二)

4. 编译和运行简单应用程序

本章介绍如何在DPDK环境下编译和运行应用程序。还指出应用程序的存储位置。
注意:此过程的部分操作也可以使用脚本来完成。

4.1. 编译一个简单应用程序

一个DPDK目标环境创建完成时(如 x86_64-native-linuxapp-gcc),它包含编译一个应用程序所需要的全部库和头文件。
当在Linux* 交叉环境中编译应用程序时,以下变量需要预先导出:

  • RTE_SDK - 指向DPDK安装目录。
  • RTE_TARGET - 指向DPDK目标环境目录。

以下是创建helloworld应用程序实例,该实例将在DPDK Linux环境中运行。

该目录包含 main.c 文件。该文件与DPDK目标环境中的库结合使用时,调用各种函数初始化DPDK环境,然后,为每个要使用的core启动一个入口点(调度应用程序)。 默认情况下,二进制文件存储在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目录之外,以保证DPDK的结构不变。 下面的例子, 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

4.2. 运行一个简单的应用程序

注意: UIO驱动和hugepage必须在程序运行前设置好。

注意:应用程序使用的任何端口,必须绑定到合适的内核驱动模块上,如章节 网络端口绑定/解绑定到内核去顶模块 描述的那样。
应用程序与DPDK目标环境的环境抽象层(EAL)库相关联,该库提供了所有DPDK程序通用的一些选项。

以下是EAL提供的一些选项列表:

./rte-app -c COREMASK [-n NUM] [-b ] \
          [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] \
          [--proc-type ] [-- xen-dom0]

选项描述如下:

  • -c COREMASK: 要运行的内核的十六进制掩码。注意,平台之间编号可能不同,需要事先确定。
  • -n NUM: 每个处理器插槽的内存通道数目。
  • -b : 端口黑名单,避免EAL使用指定的PCI设备。
  • --use-device: 仅使用指定的以太网设备。使用逗号分隔 [domain:]bus:devid.func 值,不能与 -b 选项一起使用。
  • --socket-mem: 从特定插槽上的hugepage分配内存。
  • -m MB: 内存从hugepage分配,不管处理器插槽。建议使用 --socket-mem 而非这个选项。
  • -r NUM: 内存数量。
  • -v: 显示启动时的版本信息。
  • --huge-dir: 挂载hugetlbfs的目录。
  • --file-prefix: 用于hugepage文件名的前缀文本。
  • --proc-type: 程序实例的类型。
  • --xen-dom0: 支持在Xen Domain0上运行,但不具有hugetlbfs的程序。
  • --vmware-tsc-map: 使用VMware TSC 映射而不是本地RDTSC。
  • --base-virtaddr: 指定基本虚拟地址。
  • --vfio-intr: 指定要由VFIO使用的中断类型。(如果不支持VFIO,则配置无效)。
    其中 -c 是强制性的,其他为可选配置。

将DPDK应用程序二进制文件拷贝到目标设备,按照如下命令运行(我们假设每个平台处理器有4个内存通道,并且存在core0~3用于运行程序):.

./helloworld -c f -n 4

注意:选项 --proc-type 和 --file-prefix 用于运行多个DPDK进程。

4.2.1. 应用程序使用的逻辑Core

对于DPDK应用程序,coremask参数始终是必须的。掩码的每个位对应于Linux提供的逻辑core ID。 由于这些逻辑core的编号,以及他们在NUMA插槽上的映射可能因平台而异,因此建议在选择每种情况下使用的coremaks时,都要考虑每个平台的core布局。

在DPDK程序初始化EAL层时,将显示要使用的逻辑core及其插槽位置。可以通过读取 /proc/cpuinfo 文件来获取系统上所有core的信息。例如执行 cat /proc/cpuinfo。 列出来的physical id 属性表示其所属的CPU插槽。当使用了其他处理器来了解逻辑core到插槽的映射时,这些信息很有用。

注意:可以使用另一个Linux工具 lstopo 来获取逻辑core布局的图形化信息。在Fedora Linux上, 可以通过如下命令安装并运行工具:

sudo yum install hwloc
./lstopo

注意:逻辑core在不同的电路板上可能不同,在应用程序使用coremaks时需要先确定。

4.2.2. 应用程序使用的Hugepage内存

当运行应用程序时,建议使用的内存与hugepage预留的内存一致。如果运行时没有 -m 或 --socket-mem 参数传入,这由DPDK应用程序在启动时自动完成。

如果通过显示传入 -m 或 --socket-mem 值,但是请求的内存超过了该值,应用程序将执行失败。 但是,如果用户请求的内存小于预留的hugepage-memory,应用程序也会失败,特别是当使用了 -m 选项的时候。 因为,假设系统在插槽0和插槽1上有1024个预留的2MB页面,如果用户请求128 MB的内存,可能存在64个页不符合要求的情况:

内核只能在插槽1中将hugepage-memory提供给应用程序。在这种情况下,如果应用程序尝试创建一个插槽0中的对象,例如ring或者内存池,那么将执行失败 为了避免这个问题,建议使用 --socket-mem 选项替代 -m 选项。
这些页面可能位于物理内存中的任意位置,尽管DPDK EAL将尝试在连续的内存块中分配内存,但是页面可能是不连续的。在这种情况下,应用程序无法分配大内存。
使用socket-mem选项可以为特定的插槽请求特定大小的内存。通过提供 --socket-mem 标志和每个插槽需要的内存数量来实现的,如 --socket-mem=0,512 用于在插槽1上预留512MB内存。 类似的,在4插槽系统上,如果只能在插槽0和2上分配1GB内存,则可以使用参数–socket-mem=1024,0,1024 来实现。 如果DPDK无法在每个插槽上分配足够的内存,则EAL初始化失败。

4.3. 其他示例程序

其他的一些示例程序包含在${RTE_SDK}/examples 目录下。这些示例程序可以使用本手册前面部分所述的方法进行构建运行。

4.4. 附加的测试程序

此外,还有两个在创建库时构建的应用程序。这些源文件位于 DPDK/app目录下,称为test和testpmd程序。创建库之后,可以在build目录中找到。

  • test程序为DPDK中的各种功能提供具体的测试。
  • testpmd程序提供了许多不同的数据包吞吐测试,例如,在Intel® 82599 10 Gigabit Ethernet Controller中如何使用Flow Director。

5. 启用附加功能

5.1. 高精度事件定时器(HPET)功能

5.1.1. BIOS支持

要使用HPET功能时,必须先在平台BIOS上开启高精度定时器。否则,默认情况下使用时间戳计数器(TSC)。通常情况下,起机时按F2 可以访问BIOS。然后用户可以导航到HPET选项。在Crystal Forest平台BIOS上,路径为:Advanced -> PCH-IO Configuration -> High Precision Timer -> (如果需要,将Disabled 改为 Enabled )。

在已经起机的系统上,可以使用以下命令来检查HPET是否启用

grep hpet /proc/timer_list

如果没有条目,则必须在BIOS中启用HPET,镔铁重新启动系统。

5.1.2. Linux内核支持

DPDK通过将定时器计数器映射到进程地址空间来使用平台的HPET功能,因此,要求开启 HPET_MMAP 系统内核配置选项。
注意:在Fedora或者其他常见的Linux发行版本(如Ubuntu)中,默认不会启用 HPET_MMAP 选项。

5.1.3. DPDK中使能HPET

默认情况下,DPDK配置文件中是禁用HPET功能的。要使用HPET,需要将CONFIG_RTE_LIBEAL_USE_HPET设置为y来开启编译。
对于那些使用 rte_get_hpet_cycles()及rte_get_hpet_hz()API接口的应用程序,并且选择了HPET作为rte_timer库的默认时钟源,需要在初始化时调用 rte_eal_hpet_init()API。这个API调用将保证HPET可用,如果HPET不可用(例如,内核没有开启 HPET_MMAP 使能),则向程序返回一个错误值。 如果HPET在运行时不可用,应用程序可以方便的采取其他措施。
注意:对于那些仅需要普通定时器API,而不是HPET定时器的应用程序,建议使用 rte_get_timer_cycles() 和 rte_get_timer_hz() API调用,而不是HPET API。 这些通用的API兼容TSC和HPET时钟源,具体时钟源则取决于应用程序是否调用 rte_eal_hpet_init()初始化,以及运行时系统上可用的时钟。

5.2. 没有Root权限情况下运行DPDK应用程序

虽然DPDK应用程序直接使用了网络端口及其他硬件资源,但通过许多小的权限调整,可以允许除root权限之外的用户运行这些应用程序。 为了保证普通的Linux用户也可以运行这些程序,需要调整如下Linux文件系统权限:

  • 所有用于hugepage挂载点的文件和目录,如 /mnt/huge
  • /dev 中的UIO设备文件,如 /dev/uio0, /dev/uio1 等
  • UIO系统配置和源文件,如 uio0:
    • /sys/class/uio/uio0/device/config
    • /sys/class/uio/uio0/device/resource*
  • 如果要使用HPET,那么 /dev/hpet 目录也要修改

注意:在某些Linux 安装中, /dev/hugepages 也是默认创建hugepage挂载点的文件。

5.3. 电源管理和节能功能

如果要使用DPDK的电源管理功能,必须在平台BIOS中启用增强的Intel SpeedStep® Technology。否则,sys文件夹下 /sys/devices/system/cpu/cpu0/cpufreq 将不存在,不能使用基于CPU频率的电源管理。

例如,在某些Intel参考平台上,开启Enhanced Intel SpeedStep® Technology 的路径为:

Advanced
  -> Processor Configuration
  -> Enhanced Intel SpeedStep® Tech

此外,C3 和 C6 也应该使能以支持电源管理。C3 和 C6 的配置路径为:

Advanced
  -> Processor Configuration
  -> Processor C3 Advanced
  -> Processor Configuration
  -> Processor C6

5.4. 使用Linux Core隔离来减少上下文切换

虽然DPDK应用程序使用的线程固定在系统的逻辑核上,但Linux调度程序也可以在这些核上运行其他任务。为了防止在这些核上运行额外的工作负载,可以使用 isolcpus Linux 内核参数来将其与通用的Linux调度程序隔离开来。

例如,如果DPDK应用程序要在逻辑核2,4,6上运行,应将以下内容添加到内核参数表中:

isolcpus=2,4,6

5.5. 加载 DPDK KNI 内核模块

要运行DPDK Kernel NIC Interface (KNI) 应用程序,需要将一个额外的内核模块(kni模块)加载到内核中。 该模块位于DPDK目录kmod子目录中。与 igb_uio 模块加载类似,(假设当前目录就是DPDK目录):

insmod kmod/rte_kni.ko

5.6. Linux IOMMU Pass-Through使用Intel® VT-d运行DPDK

要在Linux内核中启用Intel® VT-d,必须配置一系列内核选项,包括:

IOMMU_SUPPORT
IOMMU_API
INTEL_IOMMU

另外,要使用Intel® VT-d运行DPDK,使用igb_uio驱动时必须携带iommu=pt参数。这使得主机可以直接通过DMA重映射查找。另外,如果内核中没有设置 INTEL_IOMMU_DEFAULT_ON 参数,那么也必须使用 intel_iommu=on 参数。这可以确保 Intel IOMMU 被正确初始化。

请注意,对于igb_uio 驱动程序,使用iommu = pt是必须的,vfio-pci驱动程序实际上可以同时使用iommu = pt和iommu = on。

5.7. 40G NIC上的小包处理高性能

由于在最新版本中可能提供用于性能提升的固件修复,因此最好进行固件更新以获取更高的性能。 请和 Intel’s Network Division 工程师联系以进行固件更新。 

5.7.1. 使用16B大小的RX描述符

由于 i40e PMD 支持16B和32B的RX描述符,而16B大小的描述符可以帮助小型数据包提供性能,因此,配置文件中 CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC 更改为使用16B大小的描述符。

5.7.2. 高性能和每数据包延迟权衡

由于硬件设计,每个数据包描述符回写都需要NIC内部的中断信号。中断的最小间隔可以在编译时通过配置文件中的 CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL 指定。 虽然有默认配置,但是该配置可以由用户自行调整,这取决于用户所关心的内容,整体性能或者每数据包延迟。

6. 使用脚本快速构建

usertools目录中的dpdk-setup.sh脚本,向用户提供了快速执行如下任务功能:

  • 构建DPDK库
  • 加载/卸载DPDK IGB_UIO内核模块
  • 加载/卸载VFIO内核模块
  • 加载/卸载DPDK KNI内核模块
  • 创建/删除NUMA 或 non-NUMA平台的hugepages
  • 查看网络端口状态和预留给DPDK应用程序使用的端口
  • 设置非root用户使用VFIO的权限
  • 运行test和testpmd应用程序
  • 查看meminfo中的hugepages
  • 列出在 /mnt/huge 中的hugepages
  • 删除内置的DPDK库
    对于其中一个EAL目标,一旦完成了这些步骤,用户就可以编译自己的在EAL库中链接的应用程序来创建DPDK映像。

6.1. 脚本组织

dpdk-setup.sh脚本在逻辑上组织成用户按顺序执行的一系列步骤。每个步骤都提供了许多选项来指导用户完成所需的任务。以下是每个步骤的简单介绍:

Step 1: Build DPDK Libraries

最开始,用户必须指定tagert的类型以便编译正确的库。

如本入门指南前面的章节描述,用户必须在此之前就安装好所有的库、模块、更新和编译器。

Step 2: Setup Environment

用户需要配置Linux* 环境以支持DPDK应用程序的运行。 可以为NUMA 或non-NUMA系统分配Hugepages。任何原来已经存在的hugepages将被删除。 也可以在此步骤中插入所需的DPDK内核模块,并且可以将网络端口绑定到此模块供DPDK使用。

Step 3: Run an Application

一旦执行了其他步骤,用户就可以运行test程序。该程序允许用户为DPDK运行一系列功能测试。也可以运行支持数据包接收和发送的testpmd程序。

Step 4: Examining the System

此步骤提供了一些用于检查Hugepage映射状态的工具。

Step 5: System Cleanup

最后一步具有将系统恢复到原始状态的选项。

6.2. Use Cases

以下是使用dpdk-setup.sh的示例。脚本应该使用source命令运行。脚本中的某些选项在继续操作之前提示用户需要进一步的数据输入。

注意:必须与root权限运行dpdk-setup.sh。

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

Option:

以下选项演示了 “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系统中创建hugepage。为每个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

以下操作说明了启动测试应用程序以在单个core上运行

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>>

6.3. 应用程序

一旦用户运行和dpdk-setup.sh脚本,构建了目标程序并且设置了hugepages,用户就可以继续构建和运行自己的应用程序或者源码中提供的示例。

/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

7. 如何获取Intel平台上网卡的最佳性能

本文档一步一步教你如何在Intel平台上运行DPDK程序以获取最佳性能。

7.1. 硬件及存储需求

为了获得最佳性能,请使用Intel Xeon级服务器系统,如Ivy Bridge,Haswell或更高版本。

确保每个内存通道至少插入一个内存DIMM,每个内存通道的内存大小至少为4GB。 Note: 这对性能有最直接的影响。

可以通过使用 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个通道,从 A 到 H,每个通道都有2个DIMM。

你也可以使用 dmidecode 来确定内存频率:

dmidecode -t memory | grep Speed

Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
Speed: 2133 MHz
Configured 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

输出显示2133 MHz(DDR4)和未知(不存在)的速度。这与先前的输出一致,表明每个通道都有一个存储。

7.1.1. 网卡需求

确保每个网卡已经更新最新版本的NVM/固件。

使用PCIe Gen3 插槽,如 Gen3 x8 或者 Gen3 x16 ,因为PCIe Gen2 插槽不能提供2 x 10GbE或更高的带宽。 可以使用 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+ ...

当将NIC插入PCI插槽时,需要查看屏幕输出,如 CPU0 或 CPU1,以指示连接的插槽。

同时应该注意NUMA,如果使用不同网卡的2个或更多端口,最好确保这些NIC在同一个CPU插槽上,下面进一步展示了如何确定这一点。

7.1.2. BIOS 设置

以下是关于BIOS设置的一些建议。不同的平台可能会有不同的名字,因此如下仅用于参考:

  • 开始之前,请考虑将所有BIOS设置为默认值
  • 禁用所有省电选项,如电源性能调整、CPU P-State, CPU C3 Report and CPU C6 Report。
  • 选择 Performance 作为CPU电源及性能策略。
  • 禁用Turbo Boost以确保性能缩放随着内核数量的增加而增加。
  • 将内存频率设置为最高可用的值,NOT auto。
  • 当测试NIC的物理功能时,禁用所有的虚拟化选项,如果要使用VFIO,请打开 VT-d if you wants to use VFIO.

7.1.3. Linux引导选项

以下是GRUB启动选项的一些建议配置:

  • 使用默认的grub文件作为起点
  • 通过grub配置保留1G的hugepage。例如,保留8个1G大小的页面:
default_hugepagesz=1G hugepagesz=1G hugepages=8

隔离将用于DPDK的CPU core.如:

isolcpus=2,3,4,5,6,7,8

如果要使用VFIO,请使用以下附加的grub参数:

iommu=pt intel_iommu=on

7.2. 运行DPDK前的配置

构建目标文件,预留hugepage。

以下命令为具体过程:

# 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

使用命令 cpu_layout 来检查CPU布局:

cd dpdk_folder
usertools/cpu_layout.py

或者运行 lscpu 检查每个插槽上的core。
检查NIC ID和插槽ID:

列出所有的网卡的PCI地址及设备ID.

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节点:

cat /sys/bus/pci/devices/0000\:xx\:00.x/numa_node

通常的,0x:00.x 表示在插槽0,而 8x:00.x 表示在插槽1。 Note: 为了说去最佳性能,请保证core和NIC位于同一插槽中。 在上面的例子中 85:00.0 在插槽1,因此必须被插槽1上的core使用才能获得最佳性能。
将测试端口绑定到DPDK兼容的驱动程序,如igb_uio。例如,将两个端口绑定到兼容DPDK的驱动程序并检查状态:

绑定端口 82:00.0 和 85:00.0 到DPDK驱动

./dpdk_folder/usertools/dpdk-devbind.py -b igb_uio 82:00.0 85:00.0

检查端口驱动状态

./dpdk_folder/usertools/dpdk-devbind.py --status

运行 dpdk-devbind.py --help 以获取更多信息。

7.3. 网卡最佳性能实践举例

以下是运行DPDK l3fwd 例程并获取最佳性能的例子。使用 Intel 服务平台和Intel XL710 NICs。

本例场景是通过两个Intel XL710 40GbE端口获取最优性能。

Linux平台上DPDK入门指南(二)_第1张图片

Fig. 7.1 性能测试搭建

将两个Intel XL710 NIC添加到平台,并使用每个卡一个端口来获得最佳性能。使用两个NIC的原因是克服PCIe Gen3的限制,因为它不能提供80G带宽。 对于两个40G端口,但两个不同的PCIe Gen3 x8插槽可以。 

82:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]

 将端口连接到打流机,对于高速测试,最好有专用的打流设备。
检测PCI设备的numa节点,并获取该插槽id上的core。 在本例中, 82:00.0 和 85:00.0 都在插槽1上,插槽1上的core id为18-35 和 54-71。
注意: 不要在同一个core上使用两个逻辑核(e.g core18 有两个逻辑核core18 and core54),而是使用来自不同core的两个逻辑核。
将这两个端口绑定到igb_uio。
对于XL710 40G 端口,我们需要至少两个队列来实现最佳性能,因此每个端口需要两个队列,每个队列将需要专用的CPU内核来接收/发送数据包。
使用DPDK示例程序 l3fwd 做性能测试,两个端口进行双向转发,使用默认的lpm模式编译 l3fwd sample。
运行l3fwd的命令如下所示:

./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),(core18,port1,队列1)。
配置打流机用于发包

创建流
设置报文类型为Ethernet II type to 0x0800。

你可能感兴趣的:(linux,运维,服务器,网络协议,网络)