对dpdk-helloworld
示例源码进行介绍分析,Hello World
示例设置 DPDK
环境抽象层 (EAL
),并向每个启用 DPDK
的内核打印一条简单的“Hello World
”消息。此应用程序不进行任何数据包转发,但它是测试 DPDK
环境是否正确编译和设置的方法。
该篇主要介绍一下DPDK
环境抽象层 (EAL
)参数选项信息,通过对各个参数的解释,可以更好的了解后续其它样例中启动参数的含义。
操作系统版本: CentOS 8.4
dpdk版本: dpdk-20.11.1
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int
lcore_hello(__rte_unused void *arg)
{
unsigned lcore_id;
lcore_id = rte_lcore_id();
printf("hello from core %u\n", lcore_id);
return 0;
}
int
main(int argc, char **argv)
{
int ret;
unsigned lcore_id;
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_panic("Cannot init EAL\n");
/* call lcore_hello() on every worker lcore */
RTE_LCORE_FOREACH_WORKER(lcore_id) {
rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
}
/* call it on main lcore too */
lcore_hello(NULL);
rte_eal_mp_wait_lcore();
/* clean up the EAL */
rte_eal_cleanup();
return 0;
}
首先执行lscpu
命令查看虚拟机的CPU
信息,8
核
执行hello-world
程序(不添加EAL层参数选项)
执行hello-world
程序(添加EAL层参数选项)
Hello World
示例应用程序是可以编写的最简单的DPDK
应用程序示例。该应用程序只是在每个启用的 lcore
上打印一条helloworld
消息。
[root@localhost dpdk-helloworld]# ./build/cmdline_app-static --help
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
Usage: ./build/cmdline_app-static [options]
EAL common options:
-c COREMASK Hexadecimal bitmask of cores to run on
-l CORELIST List of cores to run on
The argument format is <c1>[-c2][,c3[-c4],...]
where c1, c2, etc are core indexes between 0 and 128
--lcores COREMAP Map lcore set to physical cpu set
The argument format is
'[<,lcores[@cpus]>...]'
lcores and cpus list are grouped by '(' and ')'
Within the group, '-' is used for range separator,
',' is used for single number separator.
'( )' can be omitted for single element group,
'@' can be omitted if cpus and lcores have the same value
-s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores
--main-lcore ID Core ID that is used as main
--mbuf-pool-ops-name Pool ops name for mbuf to use
-n CHANNELS Number of memory channels
-m MB Memory to allocate (see also --socket-mem)
-r RANKS Force number of memory ranks (don't detect)
-b, --block Add a device to the blocked list.
Prevent EAL from using this device. The argument
format for PCI devices is .
-a, --allow Add a device to the allow list.
Only use the specified devices. The argument format
for PCI devices is <[domain:]bus:devid.func>.
This option can be present several times.
[NOTE: allow cannot be used with block option]
--vdev Add a virtual device.
The argument format is [,key=val,...]
(ex: --vdev=net_pcap0,iface=eth2).
--iova-mode Set IOVA mode. ' pa' for IOVA_PA
'va' for IOVA_VA
-d LIB.so|DIR Add a driver or driver directory
(can be used multiple times)
--vmware-tsc-map Use VMware TSC map instead of native RDTSC
--proc-type Type of this process (primary|secondary|auto)
--syslog Set syslog facility
--log-level= Set global log level
--log-level=:
Set specific log level
--trace=
Enable trace based on regular expression trace name.
By default, the trace is disabled.
User must specify this option to enable trace.
--trace-dir=
Specify trace directory for trace output.
By default, trace output will created at
$HOME directory and parameter must be
specified once only.
--trace-bufsz=
Specify maximum size of allocated memory
for trace output for each thread. Valid
unit can be either ' B|K|M' for 'Bytes',
'KBytes' and 'MBytes' respectively.
Default is 1MB and parameter must be
specified once only.
--trace-mode=
Specify the mode of update of trace
output file. Either update on a file can
be wrapped or discarded when file size
reaches its maximum limit.
Default mode is ' overwrite' and parameter
must be specified once only.
-v Display version information on startup
-h, --help This help
--in-memory Operate entirely in memory. This will
disable secondary process support
--base-virtaddr Base virtual address
--telemetry Enable telemetry support (on by default)
--no-telemetry Disable telemetry support
--force-max-simd-bitwidth Force the max SIMD bitwidth
EAL options for DEBUG use only:
--huge-unlink Unlink hugepage files after init
--no-huge Use malloc instead of hugetlbfs
--no-pci Disable PCI
--no-hpet Disable HPET
--no-shconf No shared config (mmap'd files)
EAL Linux options:
--socket-mem Memory to allocate on sockets (comma separated values)
--socket-limit Limit memory allocation on sockets (comma separated values)
--huge-dir Directory where hugetlbfs is mounted
--file-prefix Prefix for hugepage filenames
--create-uio-dev Create /dev/uioX (usually done by hotplug)
--vfio-intr Interrupt mode for VFIO (legacy|msi|msix)
--vfio-vf-token VF token (UUID) shared between SR-IOV PF and VFs
--legacy-mem Legacy memory mode (no dynamic allocation, contiguous segments)
--single-file-segments Put all hugepage memory in single files
--match-allocations Free hugepages exactly as allocated
-c
设置要运行的内核的十六进制位掩码。比如需要用到cpu
的0-4
核,那么后面可以跟-c 0x1f
,因为十六进制0x0F
的二进制是00011111
运行截图如下:
-l
要运行的内核列表,参数格式是[-c2][,c3[-c4],...]
其中c1
、c2
等是 0 到 128 之间的核心索引。这个相比于-c
掩码参数,可以更直观的理解,比如想要加载0-4
核,直接-l 0-4
就可以了,如果需要非连续的0-1
和4-5
也可以写成-l 0-1,4-5
这样的格式,运行截图如下:
--lcores
将 lcore 集映射到物理 CPU 集 (EAL Thread 的 CPU 亲和性),参数格式为:
<lcores[@cpus]>[<,lcores[@cpus]>...]
--lcores
可以设置lcore
到CPU processer
的多对多映射关系,只需要简单的修改一下配置,基本上不需要做太多的代码调整。比如虚拟机本身CPU
只有0~7
这8个核,但是程序代码需要0~10
这11个核,那么就可以采用这种映射关系。这样既可以提供CPU processor
的伸缩扩展,同时也保证了EAL thread
的运行环境
[root@localhost dpdk-helloworld]# ./build/cmdline_app-static
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: No legacy callbacks, legacy socket not created
hello from core 1
hello from core 2
hello from core 3
hello from core 4
hello from core 5
hello from core 6
hello from core 7
hello from core 0
[root@localhost dpdk-helloworld]# ./build/cmdline_app-static --lcores "(0,1,2,3,4,5,6,7,8,9,10)@(0,1),(5,6,7,8)@3"
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: No legacy callbacks, legacy socket not created
hello from core 1
hello from core 2
hello from core 3
hello from core 5
hello from core 4
hello from core 6
hello from core 7
hello from core 8
hello from core 9
hello from core 10
hello from core 0
# lcores 0,1,2,3,4,5,6,7,8,9,10 绑定在 CPU0,CUP1
# lcore 5,6,7,8 绑定在 CPU3
注意:在给定的情况下,只能使用一个选项--lcores
,-l
或者-c
。
--main-lcore
用作主函数的core ID
。我的理解是对于dpdk
程序,每个线程都绑定一个core ID
也就是对应一个cpu
,比如可以设置1
核只用来收包,也就是RX
线程;2
核用来处理包,也就是work
线程;3
核用来发包,也就是TX
线程,那么相应的主函数当然是需要创建这些线程,以及处理其它未绑定核的事件,为了避免线程间占用一个CPU
调度竞争,也可以单独指定一个核心来用作主函数线程的处理。
运行截图如下:
-s
用作服务core
的十六进制位掩码具体解释可参考DPDK 服务核心说明。
注意:服务内核支持内置在EAL
中,因此-s
后面的掩码范围和-l
的范围是-s
∈-l
的关系。并且都包含刚开始的核,那么应该先分配给EAL
使用。
运行截图如下:
虽然0x1E
的二进制为00011110
,核1
虽然在-s
的范围内,但是由于是起始第一个,所以还是分配给EAL
使用了。
-b, --block <[domain:]bus:devid.func>
网口黑名单,禁止EAL
使用这些PCI
设备,允许多个 -b
选项。
-a, --allow <[domain:]bus:devid.func>
网口白名单,指定EAL
使用这些 PCI
设备,允许多个 -a
选项。
(对应老版本的-w
但是:Option -w, --pci-whitelist is deprecated, use -a, --allow option instead
)
假如绑定了好几个网卡,但是怎么让运行的DPDK
程序做出选择呢,就需要这两个参数了,一个是禁止使用某个网卡,一个是指定使用某个,可以自行选择。
-b
参数运行截图如下(由于helloworld
程序检测网卡PCI
但是未使用,所以禁用了也不受影响):
-a
参数运行截图如下:
**注:**禁用列表-b
不能与允许列表-a
选项一起使用。
--vdev
使用以下格式添加虚拟设备:<driver><id>[,key=val, ...]
例如:
--vdev 'net_pcap0,rx_pcap=input.pcap,tx_pcap=output.pcap'
-d
加载外部驱动程序。参数可以是单个共享对象文件,也可以是包含多个驱动程序共享对象的目录。允许多个 -d
选项。
--proc-type
设置当前进程的类型。可以实现启动多个DPDK
程序,实现一台虚拟机上跑两个DPDK-l2fwd
程序,如下所示:
第一个l2fwd
进程
[root@localhost dpdk-l2fwd]# ./build/l2fwd_app-static -c 0x3 -n 4 --proc-type=auto --file-prefix pg1 -a 02:05.0 -- -p 0x1
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Auto-detected process type: PRIMARY
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/pg1/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: using IOMMU type 8 (No-IOMMU)
EAL: Ignore mapping IO port bar(4)
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:05.0 (socket 0)
EAL: No legacy callbacks, legacy socket not created
MAC updating enabled
Notice: odd number of ports in portmask.
Lcore 0: RX port 0 TX port 0
Initializing port 0... EAL: Error enabling MSI-X interrupts for fd 23
done:
Port 0, MAC address: 00:0C:29:BE:75:B2
Checking link statusdone
Port 0 Link up at 1 Gbps FDX Autoneg
L2FWD: lcore 1 has nothing to do
L2FWD: entering main loop on lcore 0
L2FWD: -- lcoreid=0 portid=0
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 0
Packets received: 0
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 0
Total packets received: 0
Total packets dropped: 0
====================================================
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 11
Packets received: 11
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 11
Total packets received: 11
Total packets dropped: 0
====================================================
^C
Signal 2 received, preparing to exit...
EAL: Error disabling MSI-X interrupts for fd 23
Closing port 0... Done
Bye...
第二个l2fwd
进程
[root@localhost dpdk-l2fwd]# ./build/l2fwd_app-static -c 0x3 -n 4 --proc-type=auto --file-prefix pg2 -a 02:06.0 -- -p 0x1
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Auto-detected process type: PRIMARY
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/pg2/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: using IOMMU type 8 (No-IOMMU)
EAL: Ignore mapping IO port bar(4)
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:06.0 (socket 0)
EAL: No legacy callbacks, legacy socket not created
MAC updating enabled
Notice: odd number of ports in portmask.
Lcore 0: RX port 0 TX port 0
Initializing port 0... EAL: Error enabling MSI-X interrupts for fd 23
done:
Port 0, MAC address: 00:0C:29:BE:75:BC
Checking link statusdone
Port 0 Link up at 1 Gbps FDX Autoneg
L2FWD: lcore 1 has nothing to do
L2FWD: entering main loop on lcore 0
L2FWD: -- lcoreid=0 portid=0
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 0
Packets received: 0
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 0
Total packets received: 0
Total packets dropped: 0
====================================================
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 49
Packets received: 49
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 49
Total packets received: 49
Total packets dropped: 0
====================================================
^C
Signal 2 received, preparing to exit...
EAL: Error disabling MSI-X interrupts for fd 23
Closing port 0... Done
Bye...
使用ps -ef | grep l2fwd
可以查看,系统运行了两个dpdk-l2fwd
进程~
分隔符⭐️
上面实现了一个主机上运行两个DPDK
程序,下面运行一个dpdk-l2fwd
程序和一个dpdk-pdump
程序。即运行l2fwd
进行包转发,然后再启动pdump
进行包抓取(由于dpdk
绑定网卡后,不能在使用普通的tcpdump
命令去抓取 网卡流量,因此使用dpdk-pdump
程序来完成)。
首先要修改下dpdk-l2fwd
源代码(main.c
),添加pdump
功能:
。signal_handler()
中添加 rte_pdump_uninit()
。main()
中添加 rte_pdump_init()
。修改完毕后重新编译执行程序,启动成功后不要退出l2fwd
进程,让它持续循环转发着数据包~
[root@localhost dpdk-l2fwd]# ./build/l2fwd_app-static -c 0x3 -n 4 --proc-type=auto --file-prefix pg1 -a 02:05.0 -- -p 0x1
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Auto-detected process type: PRIMARY
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/pg1/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: using IOMMU type 8 (No-IOMMU)
EAL: Ignore mapping IO port bar(4)
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:05.0 (socket 0)
EAL: No legacy callbacks, legacy socket not created
MAC updating enabled
Notice: odd number of ports in portmask.
Lcore 0: RX port 0 TX port 0
Initializing port 0... EAL: Error enabling MSI-X interrupts for fd 23
done:
Port 0, MAC address: 00:0C:29:BE:75:B2
Checking link statusdone
Port 0 Link up at 1 Gbps FDX Autoneg
L2FWD: entering main loop on lcore 0
L2FWD: -- lcoreid=0 portid=0
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 0
Packets received: 0
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 0
Total packets received: 0
Total packets dropped: 0
====================================================
L2FWD: lcore 1 has nothing to do
Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent: 22
Packets received: 22
Packets dropped: 0
Aggregate statistics ===============================
Total packets sent: 22
Total packets received: 22
Total packets dropped: 0
====================================================
然后再打开一个新的窗口,编译dpdk-pdump
源代码,执行命令如下:
[root@localhost dpdk-pdump]# ./build/pdump_app-static --proc-type=auto --socket-mem 512 --file-prefix pg1 -a 02:05.0 -- --pdump 'port=0,queue=*,rx-dev=./l2fwd.pcap'
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/pg1/mp_socket_53548_a82d748cbafb
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: using IOMMU type 8 (No-IOMMU)
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:05.0 (socket 0)
EAL: No legacy callbacks, legacy socket not created
Port 1 MAC: 02 70 63 61 70 00
core (0), capture for (1) tuples
- port 0 device ((null)) queue 65535
其中执行参数要和l2fwd
运行参数保持一致。最后的./l2fwd.pcap
为抓取数据包保存的路径为当前路径,ctrl+c
退出dpdk-pdump
进行后,在当前文件目录可以看到l2fwd.pcap
文件,使用命令tcpdump -r ./l2fwd.pcap
可以查看数据包内容:
[root@localhost dpdk-pdump]# tcpdump -r ./l2fwd.pcap
reading from file ./l2fwd.pcap, link-type EN10MB (Ethernet)
dropped privs to tcpdump
17:37:33.114932 IP localhost.localdomain.ssh > 192.168.22.1.51060: Flags [P.], seq 765178800:765178916, ack 1106170907, win 391, length 116
17:37:33.114941 IP 192.168.22.1.51060 > localhost.localdomain.ssh: Flags [.], ack 116, win 4096, length 0
17:37:34.960881 IP 192.168.22.1.57113 > localhost.localdomain.ssh: Flags [P.], seq 3438565777:3438565813, ack 3478782653, win 4100, length 36
17:37:35.002947 IP localhost.localdomain.ssh > 192.168.22.1.57113: Flags [.], ack 36, win 426, length 0
17:37:35.372928 IP 192.168.22.1.51060 > localhost.localdomain.ssh: Flags [P.], seq 1:53, ack 116, win 4096, length 52
17:37:35.372934 IP localhost.localdomain.ssh > 192.168.22.1.51060: Flags [P.], seq 116:168, ack 53, win 391, length 52
17:37:35.413675 IP 192.168.22.1.51060 > localhost.localdomain.ssh: Flags [.], ack 168, win 4096, length 0
#...截取部分
分隔符
--base-virtaddr
尝试对主 DPDK
进程的所有内存映射使用不同的起始地址。如果由于地址映射中的冲突而无法启动辅助进程,可以提供帮助。-n
设置每个 Socket
的内存通道数。一般使用-n 4
-r
设置内存Ranks
数(默认自动检测)。-m
启动时预分配的内存量。(从hugepage
分配内存,不考虑处理器 Socket
。不建议使用)--in-memory
不要创建任何共享数据结构,完全运行在存储中。暗指 --no-shconf
和--huge-unlink
。--iova-mode
强制 IOVA
模式为特定值。--no-shconf
不创建共享文件(暗指不支持多进程)。
--no-huge
使用匿名存储而不是大页(暗指不支持多进程)。
--no-hpet
禁止使用 HPET
计时器。
--huge-unlink
创建大页文件后 Unlink
(暗指不支持多进程)。
--no-pci
禁用 PCI
总线。
--log-level
指定特定组件的日志级别。例如:
--log-level lib.eal:debug
--log-level lib.eal:error
--log-level lib.eal:info
--log-level lib.eal:warning
#可以使用多次
可以多次指定。
--trace=
启用基于正则表达式跟踪名称的跟踪。默认情况下,跟踪被禁用。用户必须指定此选项才能启用跟踪。例如:仅用于 EAL
的全局跟踪配置:
--trace=eal
所有组件的全局跟踪配置:
--trace=.*
可以指定多次,最多 32 次。
--trace-dir=
为跟踪输出指定跟踪目录。例如:配置/tmp/
为跟踪输出目录:
--trace-dir=/tmp
默认情况下,跟踪输出将创建在home
目录和参数必须只指定一次。
--trace-bufsz=
为每个线程的跟踪输出指定分配内存的最大大小。有效单位可以是B
或K
或M
for Bytes
, KBytes
and MBytes
。例如:
配置2MB
为跟踪输出文件的最大大小:
--trace-bufsz=2M
默认情况下,跟踪输出文件的大小是,1MB
并且参数只能指定一次。
--trace-mode=
指定跟踪输出文件的更新方式。当文件大小达到其最大限制时,可以包装或丢弃文件更新。例如:
要discard
更新跟踪输出文件:
--trace-mode=d or --trace-mode=discard
默认模式是overwrite
并且参数只能指定一次。
-h, --help
显示列出所有 EAL
参数的帮助消息。-v
启动时显示版本信息。--mbuf-pool-ops-name
mbuf
使用的池操作名称。--telemetry
启用遥测(默认启用)。--no-telemetry
禁用遥测。--force-max-simd-bitwidth=
指定要处理的最大 SIMD
位宽大小。这限制了采用哪些矢量路径(如果有),因为采用的任何路径都必须使用低于最大位宽限制的位宽。例如,要允许达到并包括 AVX-512
的所有 SIMD
位宽:--force-max-simd-bitwidth=512
以下示例显示将位宽限制为 64 位以禁用所有矢量代码:
--force-max-simd-bitwidth=64
要禁用最大 SIMD
位宽限制:
--force-max-simd-bitwidth=0
--create-uio-dev
/dev/uioX
为绑定到 igb_uio
内核驱动程序的设备创建文件(通常由 igb_uio
驱动程序本身完成)。--vmware-tsc-map
使用 VMware TSC
映射而不是本机 RDTSC
。--vfio-intr
对绑定到 VFIO
内核驱动程序的设备使用指定的中断模式。--vfio-vf-token
对绑定到 VFIO
内核驱动程序的设备使用指定的 VF
令牌。--file-prefix
为 DPDK
进程使用不同的共享数据文件前缀。此选项允许在不同的前缀下运行多个独立的 DPDK
主/次进程。--legacy-mem
使用传统的 DPDK
内存分配模式。--socket-mem
为每个套接字预分配指定数量的内存。该参数是逗号分隔的值列表。例如:--socket-mem 1024,2048
这将在套接字 0 上分配 1 GB 的内存,在套接字 1 上分配2 GB的内存。
--socket-limit
设置每个Socket
的内存使用上限(仅限非传统内存模式)。0 将禁用特定套接字的限制。--single-file-segments
在hugetlbfs
中创建更少的文件(仅限非传统模式)。--huge-dir
使用指定的hugetlbfs
目录,而不是自动检测的。hugetlbfs
是大页使用目录。e.g. --huge-dir /dev/hugepages
。--match-allocations
完全按照最初分配的方式将大页面释放回系统。--syslog
设置系统日志工具。有效的系统日志设施是:
auth
cron
daemon
ftp
kern
lpr
mail
news
syslog
user
uucp
local0
local1
local2
local3
local4
local5
local6
local7
DPDK --lcores参数解释
DPDK 服务核心解释
一台服务器运行多个DPDK程序
dpdk-l2fwd+pdump的例程
未完待续~~