DPDK源碼庫(kù)中提供了一些示例程序來(lái)測(cè)試DPDK,這些示例程序可以看作是一個(gè)個(gè)小的DPDK的app。那我們先來(lái)分析第一個(gè)最簡(jiǎn)單的app——helloworld。
編譯執(zhí)行示例程序
運(yùn)行app之前需要完成app的編譯,這個(gè)前提是已經(jīng)完成了DPDK庫(kù)的編譯和安裝,編譯方法很簡(jiǎn)單,首先需要導(dǎo)入兩個(gè)環(huán)境變量,RTE_SDK指向DPDK的安裝目錄,RTE_TARGET指向DPDK的目標(biāo)環(huán)境目錄:
export RTE_SDK=/home/user/DPDK
export RTE_TARGET=x86_64-native-linuxapp-gcc
再進(jìn)入示例程序的源碼目錄,如helloworld的app的代碼就在$RET_SDK/examples/helloworld目錄下,執(zhí)行命令make即可完成編譯,編譯的可執(zhí)行文件存放在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
執(zhí)行該示例程序,該程序完成的功能是,從lcore上分別打印一條語(yǔ)句hello from core #,等所有的lcore都執(zhí)行完之后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參數(shù)說(shuō)明
從上面可以看到在執(zhí)行helloworld程序時(shí),后面指定了幾個(gè)參數(shù)-l 0-4 -n 4,那這幾個(gè)參數(shù)的含義是什么呢。打開源碼可以看到這些參數(shù)最終都是傳給EAL做初始化使用的,下面列出部分EAL參數(shù)說(shuō)明其含義:
lcore相關(guān)參數(shù)
- -c COREMASK | -l CORELIST | --lcores COREMAPS:DPDK程序使用的核,可以使用核號(hào)的掩碼或者列表的形式給出,例如 -c 0x1f 和 -l 0-4 效果是一樣的,都表示使用的核是0,1,2,3,4。
- --master-lcore COREID:指定master core的核號(hào),默認(rèn)為核號(hào)最小的那個(gè)核。
- -s SERVICE_CORE_MASK:執(zhí)行service cores的核的掩碼,默認(rèn)不分配。
內(nèi)存相關(guān)參數(shù)
- -n CHANNELS:設(shè)置使用的內(nèi)存通道。
- -r RANKS:設(shè)置使用的內(nèi)存ranks,默認(rèn)自動(dòng)檢測(cè)。
- -m MEGABYTES:?jiǎn)?dòng)時(shí)預(yù)分配的內(nèi)存大小。
- --in-memory:
- --iova-mode <pa|va>
設(shè)備相關(guān)參數(shù)
- -b, --pci-blacklist PCI:禁止EAL使用的PCI設(shè)備列表。
- -w, --pci-whitelist PCI:將PCI設(shè)備加入到白名單。
- --vdev <device arguments>:添加一個(gè)虛擬設(shè)備,格式為
<driver><id>,[key=val,...],例如:--vdev net_pcap0,rx_pcap=input.pcap,tx_pcap=output.pcap - -d <path_to_shared_object>:
- --no-pci:
調(diào)試相關(guān)參數(shù)
- --log-level <type:val>:設(shè)置不同組件的日志級(jí)別,例如
--log-level eal:8。
helloworld代碼分析
了解上面一些基本的EAL參數(shù)之后,回頭來(lái)分析一下hellworld的源碼,從這個(gè)簡(jiǎn)單的app上看看DPDK的程序編碼風(fēng)格等。
/* 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;
}