目录
文章目录
DPDK 扩展第三方函数库
在开发 DPDK App 的时候难免会需要在 DPDK 中扩展自己的库或者直接引入第三方函数库。
- 本文版本:DPDK 18.08
- 官方参考网页:https://dpdk-docs.readthedocs.io/en/latest/prog_guide/extend_dpdk.html
扩展一个新的 libfoo 库
添加扩展库的启用配置
for f in config/\*; do \
echo CONFIG_RTE_LIBFOO=y >> $f; done
上述脚本的作用是为所有的 目标环境(Target Env) 中添加扩展库的配置项,表示编译该扩展库。
$ ll ${RTE_SDK}/config/
以最常见的 x86_64-native-linuxapp-gcc 为例,文件为 ${RTE_SDK}/config/defconfig_x86_64-native-linuxapp-gcc:
#include "common_linuxapp"
CONFIG_RTE_MACHINE="native"
CONFIG_RTE_ARCH="x86_64"
CONFIG_RTE_ARCH_X86_64=y
CONFIG_RTE_ARCH_X86=y
CONFIG_RTE_ARCH_64=y
CONFIG_RTE_TOOLCHAIN="gcc"
CONFIG_RTE_TOOLCHAIN_GCC=y
# Extended libfoo library.
CONFIG_RTE_LIBFOO=y
实现扩展库
创建源码目录:
$ mkdir ${RTE_SDK}/lib/libfoo
$ touch ${RTE_SDK}/lib/libfoo/foo.c
$ touch ${RTE_SDK}/lib/libfoo/foo.h
我们要扩展的是 DPDK 库,所以库目录自然也创建在 ${RTE_SDK}/lib 路径下。
源文件 foo.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "foo.h"
void foo(void)
{
printf("libfoo test appliation.\n");
fprintf(stdout, "%s %d\n", __func__, __LINE__);
}·
头文件 foo.h:
#ifndef _RTE_FOO_H_
#define _RTE_FOO_H_
extern void foo(void);
#endif
添加扩展库的 Makefile
首先我们需要添加扩展库的 Makefile,可以从 mempool Makefile 获取模板:
$ cp ${RTE_SDK}/lib/librte_mempool/Makefile ${RTE_SDK}/lib/libfoo/
替换 ${RTE_SDK}/lib/libfoo/Makefile 的内容:
- 静态库文件:librte_mempool.a -> libfoo.a
- 原文件名:rte_mempool.c -> foo.c
- 头文件:rte_mempool.h -> foo.h
- 中间编译的符号映射文件:rte_mempool_version.map -> foo_version.map
- 扩展库配置项名称:CONFIG_RTE_LIBRTE_MEMPOOL -> CONFIG_RTE_LIBFOO
include $(RTE_SDK)/mk/rte.vars.mk
# library name
LIB = libfoo.a
CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
CFLAGS += -DALLOW_EXPERIMENTAL_API
LDLIBS += -lrte_eal -lrte_ring
EXPORT_MAP := foo_version.map
LIBABIVER := 5
# memseg walk is not yet part of stable API
CFLAGS += -DALLOW_EXPERIMENTAL_API
# all source are stored in SRCS-y
SRCS-$(CONFIG_RTE_LIBFOO) += foo.c
# install includes
SYMLINK-$(CONFIG_RTE_LIBFOO)-include := foo.h
include $(RTE_SDK)/mk/rte.lib.mk
然后,更新总库的 Makefile:${RTE_SDK}/lib/Makefile
...
DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
DIRS-$(CONFIG_RTE_LIBFOO) += libfoo
最后,还需要更新 ${RTE_SDK}/mk/rte.app.mk 文件,添加 -lfoo 选项到 LDLIBS 变量中:
...
_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool
_LDLIBS-$(CONFIG_RTE_LIBFOO) += -lfoo
如此的,在编译 DPDK 的时候就会连带的编译 libfoo 扩展库了。
重新编译安装 DPDK 的目标环境
rm -rf ${RTE_SDK}/x86_64-native-linuxapp-gcc
cd ${RTE_SDK}
make config T=x86_64-native-linuxapp-gcc
make
make install T=x86_64-native-linuxapp-gcc
如果扩展库 libfoo 安装成功,DPDK 会自动创建 foo.h 的链接文件和创建 libfoo.a 静态链接库文件:
$ ll ${RTE_SDK}/x86_64-native-linuxapp-gcc/include/ | grep foo
lrwxrwxrwx 1 root root 22 6月 19 00:03 foo.h -> ../../lib/libfoo/foo.h
$ ll ${RTE_SDK}/x86_64-native-linuxapp-gcc/lib/ | grep foo
-rw-r--r-- 1 root root 1964 6月 19 00:03 libfoo.a
在自己的 DPDK App 中使用扩展库
创建 DPDK App 项目:
$ ~/workspace/myapp/
源文件 main.c:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>
#include <rte_memory.h>
#include <rte_memzone.h>
#include <rte_launch.h>
#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_debug.h>
#include <foo.h>
int main(void)
{
foo();
return 0;
}
获取 App 的 Makefile 模板:
$ cp ${RTE_SDK}/examples/helloworld/Makefile ~/workspace/myapp/Makefile
替换成:
# binary name
APP = myapp
# all source are stored in SRCS-y
SRCS-y := main.c
# Build using pkg-config variables if possible
$(shell pkg-config --exists libdpdk)
ifeq ($(.SHELLSTATUS),0)
all: shared
.PHONY: shared static
shared: build/$(APP)-shared
ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
ln -sf $(APP)-static build/$(APP)
PC_FILE := $(shell pkg-config --path libdpdk)
CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
build:
@mkdir -p $@
.PHONY: clean
clean:
rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
rmdir --ignore-fail-on-non-empty build
else
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overridden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/rte.extapp.mk
endif
编译 App:
$ make -C ~/workspace/myapp/
make: 进入目录“/root/workspace/myapp”
CC main.o
LD myapp
INSTALL-APP myapp
INSTALL-MAP myapp.map
$ # ll ~/workspace/myapp/
总用量 8
drwxr-xr-x 3 root root 188 6月 19 00:13 build
-rw-r--r-- 1 root root 355 6月 19 00:13 main.c
-rw-r--r-- 1 root root 1381 6月 19 00:11 Makefile
$ ll ~/workspace/myapp/build/
总用量 10680
drwxr-xr-x 2 root root 36 6月 19 00:13 app
-rw-r--r-- 1 root root 0 6月 19 00:13 _install
-rw-r--r-- 1 root root 1448 6月 19 00:13 main.o
-rwxr-xr-x 1 root root 7174064 6月 19 00:13 myapp
-rw-r--r-- 1 root root 3754908 6月 19 00:13 myapp.map
-rw-r--r-- 1 root root 0 6月 19 00:13 _postbuild
-rw-r--r-- 1 root root 0 6月 19 00:13 _postinstall
-rw-r--r-- 1 root root 0 6月 19 00:13 _preinstall
执行:
$ ./myapp/build/myapp
libfoo test appliation.
foo 11