本章介绍如何在DPDK环境下编译和运行应用程序。还指出应用程序的存储位置。
注意:此过程的部分操作也可以使用脚本来完成。
一个DPDK目标环境创建完成时(如 x86_64-native-linuxapp-gcc),它包含编译一个应用程序所需要的全部库和头文件。
当在Linux* 交叉环境中编译应用程序时,以下变量需要预先导出:
以下是创建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
注意: 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]
选项描述如下:
将DPDK应用程序二进制文件拷贝到目标设备,按照如下命令运行(我们假设每个平台处理器有4个内存通道,并且存在core0~3用于运行程序):.
./helloworld -c f -n 4
注意:选项 --proc-type 和 --file-prefix 用于运行多个DPDK进程。
对于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时需要先确定。
当运行应用程序时,建议使用的内存与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初始化失败。
其他的一些示例程序包含在${RTE_SDK}/examples 目录下。这些示例程序可以使用本手册前面部分所述的方法进行构建运行。
此外,还有两个在创建库时构建的应用程序。这些源文件位于 DPDK/app目录下,称为test和testpmd程序。创建库之后,可以在build目录中找到。
要使用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,镔铁重新启动系统。
DPDK通过将定时器计数器映射到进程地址空间来使用平台的HPET功能,因此,要求开启 HPET_MMAP 系统内核配置选项。
注意:在Fedora或者其他常见的Linux发行版本(如Ubuntu)中,默认不会启用 HPET_MMAP 选项。
默认情况下,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()
初始化,以及运行时系统上可用的时钟。
虽然DPDK应用程序直接使用了网络端口及其他硬件资源,但通过许多小的权限调整,可以允许除root权限之外的用户运行这些应用程序。 为了保证普通的Linux用户也可以运行这些程序,需要调整如下Linux文件系统权限:
注意:在某些Linux 安装中, /dev/hugepages 也是默认创建hugepage挂载点的文件。
如果要使用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
虽然DPDK应用程序使用的线程固定在系统的逻辑核上,但Linux调度程序也可以在这些核上运行其他任务。为了防止在这些核上运行额外的工作负载,可以使用 isolcpus Linux 内核参数来将其与通用的Linux调度程序隔离开来。
例如,如果DPDK应用程序要在逻辑核2,4,6上运行,应将以下内容添加到内核参数表中:
isolcpus=2,4,6
要运行DPDK Kernel NIC Interface (KNI) 应用程序,需要将一个额外的内核模块(kni模块)加载到内核中。 该模块位于DPDK目录kmod子目录中。与 igb_uio 模块加载类似,(假设当前目录就是DPDK目录):
insmod kmod/rte_kni.ko
要在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。
由于在最新版本中可能提供用于性能提升的固件修复,因此最好进行固件更新以获取更高的性能。 请和 Intel’s Network Division 工程师联系以进行固件更新。
由于 i40e PMD 支持16B和32B的RX描述符,而16B大小的描述符可以帮助小型数据包提供性能,因此,配置文件中 CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC 更改为使用16B大小的描述符。
由于硬件设计,每个数据包描述符回写都需要NIC内部的中断信号。中断的最小间隔可以在编译时通过配置文件中的 CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL 指定。 虽然有默认配置,但是该配置可以由用户自行调整,这取决于用户所关心的内容,整体性能或者每数据包延迟。
usertools目录中的dpdk-setup.sh脚本,向用户提供了快速执行如下任务功能:
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
最后一步具有将系统恢复到原始状态的选项。
以下是使用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>>
一旦用户运行和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
本文档一步一步教你如何在Intel平台上运行DPDK程序以获取最佳性能。
为了获得最佳性能,请使用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)和未知(不存在)的速度。这与先前的输出一致,表明每个通道都有一个存储。
确保每个网卡已经更新最新版本的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插槽上,下面进一步展示了如何确定这一点。
以下是关于BIOS设置的一些建议。不同的平台可能会有不同的名字,因此如下仅用于参考:
以下是GRUB启动选项的一些建议配置:
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
构建目标文件,预留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 以获取更多信息。
以下是运行DPDK l3fwd 例程并获取最佳性能的例子。使用 Intel 服务平台和Intel XL710 NICs。
本例场景是通过两个Intel XL710 40GbE端口获取最优性能。
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。