vpp中node节点是数据包的处理流程,数据包在不同节点之间流动进行处理
vpp所有的node节点无论里面的逻辑如何处理,转发流程都分为两种,主要是为了性能优化,本篇文章介绍第一种dual类型
首先创建一个dual类型的插件,名字为testdual,查看node.c文件
注:一般来说处理数据包的代码文件名都是node.c,但是如果一个模块功能过于复杂就会根据相应类型取名,例如ip4的处理
1.第一个知识点,当前node是如何确定数据包的下一个node节点的
这两个要放在一起看
VLIB_REGISTER_NODE这个宏表示注册 testdual这个节点
name表示该节点的名字,其中vpp会给该node分配一个node index作为标识,和名称一一对应
type表示节点的类型,这个会在别的文章中分享,处理数据包的节点都是该类型
重点来了
n_next_nodes表示当前node节点的下一个节点有多少个,这个值就是上面枚举类型的最后一个
next_nodx表示当前node节点下一个节点有哪些,在代码中会变成char *next_nodes[] 数组,记录下每一个节点的名字,其中数组下标对应上面的枚举类型,具体代码中使用的下面讲解
2.第二个知识点,当前节点是如何处理数据包并控制转发的
我把相关说明以注释的形式放在代码中
注: 该代码是vpp处理数据的基础,务必全部理解,基本上分析源码障碍就少了很多
3.dual类型与qs类型的区别
dual类型适合当前node节点的转发节点有很多个,同时在处理的过程中数据包会根据条件发送到不同的节点去
dual类型转发数据包的流程
(1)调用vlib_get_next_frame获取下一个节点的frame
(2)通过vlib_validate_buffer_enqueue_x系列函数(宏)转发到指定node
(3)通过vlib_put_next_frame函数设置frame状态等待vpp调度
如果想搞懂区别,必须理解vlib_validate_buffer_enqueue_x在做什么
为了方便理解,这里以vlib_validate_buffer_enqueue_x1为例
问题就在于为什么要先调用一次vlib_put_next_frame
需要分析一下vlib_put_next_frame函数
原因就是前面已经通过to_next把数据包存放到next_index指向的node,但是实际上数据包需要转发到next0指向的node,所以通过 vlib_put_next_frame重置一下next_index指向node的数据,证据就是调用vlib_put_next_frame函数时传入数据包个数是 n_left_to_next + 1,由于程序是在最后调用vlib_put_next_frame把当前节点收到的所有数据把统一发走,所以n_left_to_next + 1一定等于VLIB_FRAME_SIZE
接着循环结束,把这一个数据包转发到next_index,但是此时的next_index已经变成了next0
继续分析,x2和x4又在做什么呢
2个包和4个包情况就复杂了,其中如果有一个包不跟next_index表示的node一致,就需要把数据包发走
这里以x4为例
通过vlib_set_next_frame_buffer函数
继续通过vlib_set_next_frame函数
这里可以看出把数据包发送到next0指向的node
关于qs的处理放在下篇文章讲解