如何将 DPDK 应用程序编译为库
How to compile a DPDK application as a library
我有一个使用 DPDK 的程序,我正在使用示例中提供的 Makefile 编译它。
如果我将程序编译为APP(如描述here),一切顺利
出色地。
但是,我的代码是一个更大项目的一部分,为此使用
单独的 makefile 会造成很多麻烦。
所以我将我的代码捆绑在一个库中,如同一页中所述。
调用库中函数的程序(初始化
EAL) 收到此错误:
MBUF: error setting mempool handler
Cannot init mbuf pool
看来,当应用程序被编译为库时,EAL 无法正确初始化。
我在这里报告使用 l2fwd 示例重现问题的步骤。
背景
我按照 here 所述从源代码构建了 DPDK,并且我有一个绑定到 DPDK 驱动程序的以太网接口:
$ $RTE_SDK/usertools/dpdk-devbind.py --status |head -n4
Network devices using DPDK-compatible driver
============================================
0000:01:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection 10fb' drv=igb_uio unused=ixgbe
运行 l2fwd 例子
先复制示例文件夹,然后运行示例:
$ cp -r $RTE_SDK/examples/l2fwd $RTE_SDK/examples/l2fwd-lib/
$ cd $RTE_SDK/examples/l2fwd
$ make
CC main.o
LD l2fwd
INSTALL-APP l2fwd
INSTALL-MAP l2fwd.map
$ sudo ./build/l2fwd -l 0-3 -- -p 0x1
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
====================================================
- 有效!
构建与库相同的示例
cd ../l2fwd-lib/
mv main.c l2fwd.c
修改l2fwd.c,在上面添加#include "l2fwd.h"
并替换
int main(int argc, char **argv)
和
int start(int argc, char **argv)
用库接口创建头文件l2fwd.h:
int start(int argc, char **argv);
按照文档中的说明修改 Makefile:
APP = l2fwd ---> LIB = libl2fwd.a
SRCS-y := main.c ---> SRCS-y := l2fwd.c
include $(RTE_SDK)/mk/rte.extapp.mk ---> include $(RTE_SDK)/mk/rte.extlib.mk
编译库:
$ make
CC l2fwd.o
AR libl2fwd.a
INSTALL-LIB libl2fwd.a
编写一个使用该库的程序。仅使用以下 2 行创建 main.c
文件:
#include "l2fwd.h"
int main (int argc, char **argv) { start(argc, argv); }
编译它(使用所有需要的库):
gcc -L build/lib/ -L $RTE_SDK/build/lib/ main.c -o main.o -l l2fwd -l dpdk -l numa -pthread -l dl
最后,运行 它与前面使用的相同参数:
$ sudo ./main.o -l 0-3 -- -p 0x1
EAL: Detected 40 lcore(s)
EAL: Detected 2 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Probing VFIO support...
MAC updating enabled
EAL: Error - exiting with code: 1
Cause: No Ethernet ports - bye
在这种情况下,EAL无法正确初始化(以太网端口仍然绑定到DPDK驱动程序)。
编辑 1
根据@Andriy Berestovskyy 的说法,链接 DPDK 库时需要链接器 --whole-archive
选项。这解决了示例的问题。
但是,我的程序现在面临着不同的问题。我需要使用自定义构建系统,因此我将 DPDK 应用程序链接为一个库。在执行期间我得到错误:
MBUF: error setting mempool handler
mempool/dpaa2: Not a valid dpaa2 buffer pool
看起来它使用的是 dpaa2 驱动程序,那是错误的驱动程序(我的 NIC 使用的是 igb_uio)。关于为什么会发生这种情况的任何提示?相同的代码在编译为 DPDK 应用程序时有效,因此它可能与链接过程有关。
编辑 2
这个错误是因为我用
CONFIG_RTE_BUILD_SHARED_LIB=y
选项。当 DPDK 构建为共享库时,必须使用 -d
EAL 命令行选项显式设置驱动程序。
我用CONFIG_RTE_BUILD_SHARED_LIB=n
重新编译了DPDK,问题解决了
compile it (with all the needed libraries):
gcc -L build/lib/ -L $RTE_SDK/build/lib/ main.c -o main.o -l l2fwd -l dpdk -l numa -pthread -l dl
我想问题出在这一步。 DPDK 使用 link 级构造函数(即 __attribute__((constructor))
)。例如,参见 RTE_INIT()
的定义。还有回调等等等等
因此,要正确地 link 使用 DPDK,我们必须:
在 Makefile 中使用 rte.app.mk
(参见 Development Kit Build System)
或者如果我们需要使用自定义构建系统,我们需要在 --whole-archive
选项之后 link DPDK 库。
我遇到了类似的问题,如 here 中所述,我对 link 库“-d /usr/lib64/librte_mempool_ring.so
”使用了 -d
选项。成功了。
我有一个使用 DPDK 的程序,我正在使用示例中提供的 Makefile 编译它。
如果我将程序编译为APP(如描述here),一切顺利 出色地。 但是,我的代码是一个更大项目的一部分,为此使用 单独的 makefile 会造成很多麻烦。 所以我将我的代码捆绑在一个库中,如同一页中所述。
调用库中函数的程序(初始化 EAL) 收到此错误:
MBUF: error setting mempool handler
Cannot init mbuf pool
看来,当应用程序被编译为库时,EAL 无法正确初始化。
我在这里报告使用 l2fwd 示例重现问题的步骤。
背景
我按照 here 所述从源代码构建了 DPDK,并且我有一个绑定到 DPDK 驱动程序的以太网接口:
$ $RTE_SDK/usertools/dpdk-devbind.py --status |head -n4
Network devices using DPDK-compatible driver
============================================
0000:01:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection 10fb' drv=igb_uio unused=ixgbe
运行 l2fwd 例子
先复制示例文件夹,然后运行示例:
$ cp -r $RTE_SDK/examples/l2fwd $RTE_SDK/examples/l2fwd-lib/
$ cd $RTE_SDK/examples/l2fwd
$ make
CC main.o
LD l2fwd
INSTALL-APP l2fwd
INSTALL-MAP l2fwd.map
$ sudo ./build/l2fwd -l 0-3 -- -p 0x1
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
====================================================
- 有效!
构建与库相同的示例
cd ../l2fwd-lib/ mv main.c l2fwd.c
修改l2fwd.c,在上面添加
#include "l2fwd.h"
并替换int main(int argc, char **argv)
和
int start(int argc, char **argv)
用库接口创建头文件l2fwd.h:
int start(int argc, char **argv);
按照文档中的说明修改 Makefile:
APP = l2fwd ---> LIB = libl2fwd.a SRCS-y := main.c ---> SRCS-y := l2fwd.c include $(RTE_SDK)/mk/rte.extapp.mk ---> include $(RTE_SDK)/mk/rte.extlib.mk
编译库:
$ make CC l2fwd.o AR libl2fwd.a INSTALL-LIB libl2fwd.a
编写一个使用该库的程序。仅使用以下 2 行创建
main.c
文件:#include "l2fwd.h" int main (int argc, char **argv) { start(argc, argv); }
编译它(使用所有需要的库):
gcc -L build/lib/ -L $RTE_SDK/build/lib/ main.c -o main.o -l l2fwd -l dpdk -l numa -pthread -l dl
最后,运行 它与前面使用的相同参数:
$ sudo ./main.o -l 0-3 -- -p 0x1 EAL: Detected 40 lcore(s) EAL: Detected 2 NUMA nodes EAL: Multi-process socket /var/run/dpdk/rte/mp_socket EAL: Probing VFIO support... MAC updating enabled EAL: Error - exiting with code: 1 Cause: No Ethernet ports - bye
在这种情况下,EAL无法正确初始化(以太网端口仍然绑定到DPDK驱动程序)。
编辑 1
根据@Andriy Berestovskyy 的说法,链接 DPDK 库时需要链接器 --whole-archive
选项。这解决了示例的问题。
但是,我的程序现在面临着不同的问题。我需要使用自定义构建系统,因此我将 DPDK 应用程序链接为一个库。在执行期间我得到错误:
MBUF: error setting mempool handler
mempool/dpaa2: Not a valid dpaa2 buffer pool
看起来它使用的是 dpaa2 驱动程序,那是错误的驱动程序(我的 NIC 使用的是 igb_uio)。关于为什么会发生这种情况的任何提示?相同的代码在编译为 DPDK 应用程序时有效,因此它可能与链接过程有关。
编辑 2
这个错误是因为我用
CONFIG_RTE_BUILD_SHARED_LIB=y
选项。当 DPDK 构建为共享库时,必须使用 -d
EAL 命令行选项显式设置驱动程序。
我用CONFIG_RTE_BUILD_SHARED_LIB=n
重新编译了DPDK,问题解决了
compile it (with all the needed libraries):
gcc -L build/lib/ -L $RTE_SDK/build/lib/ main.c -o main.o -l l2fwd -l dpdk -l numa -pthread -l dl
我想问题出在这一步。 DPDK 使用 link 级构造函数(即 __attribute__((constructor))
)。例如,参见 RTE_INIT()
的定义。还有回调等等等等
因此,要正确地 link 使用 DPDK,我们必须:
在 Makefile 中使用
rte.app.mk
(参见 Development Kit Build System)或者如果我们需要使用自定义构建系统,我们需要在
--whole-archive
选项之后 link DPDK 库。
我遇到了类似的问题,如 here 中所述,我对 link 库“-d /usr/lib64/librte_mempool_ring.so
”使用了 -d
选项。成功了。