DPDK源码库中提供了一些示例程序来测试DPDK,这些示例程序可以看作是一个个小的DPDK的app。那我们先来分析第一个最简单的app——helloworld。
编译执行示例程序
运行app之前需要完成app的编译,这个前提是已经完成了DPDK库的编译和安装,编译方法很简单,首先需要导入两个环境变量,RTE_SDK
指向DPDK的安装目录,RTE_TARGET
指向DPDK的目标环境目录:
export RTE_SDK=/home/user/DPDK
export RTE_TARGET=x86_64-native-linuxapp-gcc
再进入示例程序的源码目录,如helloworld的app的代码就在$RET_SDK/examples/helloworld
目录下,执行命令make
即可完成编译,编译的可执行文件存放在build/app
目录下:
# cd $RTE_SDK/examples/helloworld
# ls
Makefile main.c meson.build
# make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
# ls build/app/
helloworld helloworld.map
执行该示例程序,该程序完成的功能是,从lcore上分别打印一条语句hello from core #
,等所有的lcore都执行完之后master core也打印一条后退出。
# cd build/app/
# ./helloworld -l 0-4 -n 4
EAL: Detected 16 lcore(s)
EAL: Detected 2 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: No free hugepages reported in hugepages-1048576kB
EAL: No free hugepages reported in hugepages-2048kB
EAL: Probing VFIO support...
EAL: PCI device 0000:00:03.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 1af4:1000 net_virtio
EAL: PCI device 0000:00:07.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 1af4:1000 net_virtio
hello from core 1
hello from core 2
hello from core 3
hello from core 4
hello from core 0
EAL参数说明
从上面可以看到在执行helloworld程序时,后面指定了几个参数-l 0-4 -n 4
,那这几个参数的含义是什么呢。打开源码可以看到这些参数最终都是传给EAL做初始化使用的,下面列出部分EAL参数说明其含义:
lcore相关参数
- -c COREMASK | -l CORELIST | --lcores COREMAPS:DPDK程序使用的核,可以使用核号的掩码或者列表的形式给出,例如 -c 0x1f 和 -l 0-4 效果是一样的,都表示使用的核是0,1,2,3,4。
- --master-lcore COREID:指定master core的核号,默认为核号最小的那个核。
- -s SERVICE_CORE_MASK:执行service cores的核的掩码,默认不分配。
内存相关参数
- -n CHANNELS:设置使用的内存通道。
- -r RANKS:设置使用的内存ranks,默认自动检测。
- -m MEGABYTES:启动时预分配的内存大小。
- --in-memory:
- --iova-mode <pa|va>
设备相关参数
- -b, --pci-blacklist PCI:禁止EAL使用的PCI设备列表。
- -w, --pci-whitelist PCI:将PCI设备加入到白名单。
- --vdev <device arguments>:添加一个虚拟设备,格式为
<driver><id>,[key=val,...]
,例如:--vdev net_pcap0,rx_pcap=input.pcap,tx_pcap=output.pcap
- -d <path_to_shared_object>:
- --no-pci:
调试相关参数
- --log-level <type:val>:设置不同组件的日志级别,例如
--log-level eal:8
。
helloworld代码分析
了解上面一些基本的EAL参数之后,回头来分析一下hellworld的源码,从这个简单的app上看看DPDK的程序编码风格等。
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>
#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_debug.h>
static int
lcore_hello(__attribute__((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 slave lcore */
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
}
/* call it on master lcore too */
lcore_hello(NULL);
rte_eal_mp_wait_lcore();
return 0;
}