目錄
文章目錄
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