Author [email protected]
Date Aug. 02, 2023
Description 自定义插件的方法
虽然VPP已经基本满足了路由转发需要,但是用它肯定还有其它原因:自定义扩展功能。
1. 环境及版本
$ sudo vppctl # 或者make run
DBGvpp# show version
vpp v23.06-release built by XXX on XXX at 2023-08-02T07:37:51
$ lsb_release -r
Release: 20.04
2. 创建插件
创建插件使用了一个自带的脚本,在此之前应该先安装emacs:sudo apt install -y emacs
。
进入到${VPP_HOME}/src/plugins
目录下,然后执行下述命令就可以,需要填写插件名称(如myplugin,但有的博客说不建议使用r
开头,没尝试过)以及调度类型。还没搞懂调度类型是啥,说是只有生成的node.c有所不同,且从qs改到dual非常简单。所以我选择了qs,可以查看这里看区别。
这个脚本自动创建了一个插件,而且这个插件是可以直接使用的,只需要编译运行就行了。
$ VPP_HOME="/usr/local/src/vpp"
$ cd ${VPP_HOME}/src/plugins
$ ../../extras/emacs/make-plugin.sh
Loading /etc/emacs/site-start.d/00debian.el (source)...
Loading /etc/emacs/site-start.d/50autoconf.el (source)...
Loading /etc/emacs/site-start.d/50cmake-data.el (source)...
Loading /etc/emacs/site-start.d/50dictionaries-common.el (source)...
Loading debian-ispell...
Loading /var/cache/dictionaries-common/emacsen-ispell-default.el (source)...
Loading /var/cache/dictionaries-common/emacsen-ispell-dicts.el (source)...
Loading /usr/local/src/vpp/extras/emacs/all-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin.el (source)...
Loading /usr/local/src/vpp/extras/emacs/cli-cmd-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/config-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/dual-loop-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/periodic-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/pipe-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-cmake-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-api-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-h-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-main-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-node-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-qsnode-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-test-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-periodic-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/plugin-setup-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/tunnel-c-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/tunnel-decap-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/tunnel-encap-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/tunnel-h-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/elog-4-int-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/elog-4-int-track-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/elog-enum-skel.el (source)...
Loading /usr/local/src/vpp/extras/emacs/elog-one-datum-skel.el (source)...
Plugin name: myplugin
Dispatch type [dual or qs]: qs
(Shell command succeeded with no output)
OK...
这个脚本执行完毕后,可以进入插件目录查看生成文件。不同的版本生成的文件可能有所不同。
$ cd ${VPP_HOME}/src/plugins/myplugin
$ ls
CMakeLists.txt # 插件名称、编译代码、依赖库、api文件配置等
myplugin.api # 主要是同vat客户端程序通信数据格式的接口定义,便于结构同步;可参考文章
myplugin.c # 节点初始化VNET_FEATURE_INIT,注册消息队列到全局;注册CLI命令及其响应函数,同时启动定时扫描进程(见myplugin_periodic.c)
myplugin.h #
myplugin_periodic.c # 定义了扫描进程函数,相关事件触发机制,监听插件是否工作;
myplugin_test.c # 定义API方式定义的客户端vat测试代码
node.c # 完成结点注册VLIB_REGISTER_NODE以及插件功能实现函数VLIB_NODE_FN;
setup.pg # 一些测试命令和配置
3. 编译、安装、查看以及卸载插件
编译,文档中给的make rebuild
,但我的这样用就会失败,生成不了。此时再make build
就会重新编译所有的内容,太费时间了。
所以就直接make build
就可以正常编译了。
$ cd ${VPP_HOME}/src/vpp
$ make build
...
[15/15] Linking C shared library lib/x86_64-linux-gnu/vpp_api_test_plugins/myplugin_test_plugin.so
...
$ make run
DBGvpp# show plugins
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
DBGvpp# show plugins
Plugin path is: /usr/local/src/vpp/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/vpp_plugins
Plugin Version Description
...
57. myplugin_plugin.so 23.06-release myplugin plugin description goes here
...
可以看到已经添加到了VPP的插件中了。我这里并没有在加载的时候就自己蹦出来,这时就可以使用命令这样看。不过它的顺序摸不准,而且由于version一样,很难找到,需要仔细查找下。我们可以通过定义版本号的方式,将VPP的插件和自定义的插件进行区分,这样找起来会更加方便。这个改动位置在myplugin.c
中,在注册插件位置有个.version
。
#define MYPLUGIN_VERSION "0.0.1"
/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () =
{
// .version = VPP_BUILD_VER,
.version = MYPLUGIN_VERSION,
.description = "myplugin plugin description goes here",
};
/* *INDENT-ON* */
然后此时再重新编译(可能需要使用到make rebuild; make build
,费时间也没法子)查看。就会发现版本已经变为了我们自定义的版本了:
$ make rebuild; make install
$ make run
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
DBGvpp# show plugins
Plugin path is: /usr/local/src/vpp/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/vpp_plugins
Plugin Version Description
...
57. myplugin_plugin.so 0.0.1 myplugin plugin description goes here
...
如果需要删除插件,可以直接用rm -r myplugin
,然后再make build
,就已经没了。