3. VPP源码分析(graph node(1))

2.1. 与结点相关的结构体

2.1.1. 全局结构体

vlib_main_t:每个线程一份,记录着线程使用到的全局数据信息.
比如:

/* Node graph main structure. */
vlib_node_main_t node_main;

/* Command line interface. */
vlib_cli_main_t cli_main;

/* Packet trace buffer. */
vlib_trace_main_t trace_main;

......

2.1.2. Node相关结构体

vlib_node_t:结点的主结构,包括结点的处理功能函数,名称,结点类型等,主要保存一些相对静态信息
vlib_node_main_t:Node graph相关的全局信息,nodes数组、vlib_next_frame_t、vlib_pending_frame_t等数据
vlib_node_registration_t:注册node结点时使用,保存结点业务逻辑的函数地址,结点类型,结点状态,结点名称等
vlib_node_runtime_t:实际在调度node过程中使用的结构,主要记录在处理过程中的信息变动
vlib_frame_t:每个node都有一个对应的vlib_frame_t,用来保存供node使用的数据集合(标量、矢量)
vlib_next_frame_t:主要是node内部逻辑使用,用于定位该node的下一结点所对应的frame地址
vlib_pending_frame_t:当一个node处理完数据包,则填充该待处理帧管理表数据结,调度框架便能在下一次调度时找到需要接收该数据包的下一个node

2.2. vlib_node_type_t

VLIB_NODE_TYPE_INTERNAL
/* An internal node on the call graph (could be output).
Internal nodes (including output nodes) move data from node to node (or out of the graph for output nodes). */

VLIB_NODE_TYPE_INPUT
/* Nodes which input data into the processing graph.
Input nodes are called for each iteration of main loop. */

VLIB_NODE![1](https://i-blog.csdnimg.cn/blog_migrate/27d70d0a59ca8e1e515c72344a47b006.png)
_TYPE_PRE_INPUT
/* Nodes to be called before all input nodes.
Used, for example, to clean out driver TX rings before processing input. */

VLIB_NODE_TYPE_PROCESS
 /* "Process" nodes which can be suspended and later resumed.
     A lightweight cooperative multi-tasking thread model. Context switching costs a setjmp/longjump pair. */

2.2.1. VLIB_NODE_TYPE_INPUT结点

以dpdk-input结点为例:

2.2.1.1. dpdk burst收包

1
2
DPDK收到的数据包保存在rte_mbuf中,通过rx_vectors按queue_id进行索引。
dpdk_rx_burst将返回收到的包个数n_buffers。

2.2.1.2. 得到to_next指针

3
to_next指针指向下一结点frame的起始vector地址,用于存放数据包的索引值。
4
该宏主要调用以下两个函数:
nf = vlib_node_runtime_get_next_frame(vm, node, next_index);
f = vlib_get_frame(vm, nf->frame_index);
首先,在vlib_node_runtime_t node中的next_frames数组中根据next_index找到下一结点相关的vlib_next_frame_t信息。
找到vlib_next_frame_t后,便可从其中保存的frame_index域找到下一结点对应的vlib_frame_t _f结构体。
并通过计算:
u32 _n = _f->n_vectors;
(to_next) = vlib_frame_vector_args(_f) + _n * sizeof ((to_next)[0]);
返回未使用的vector的起始地址

2.2.1.3. 从DPDK rte_mbuf到vlib_buffer_t

为了方便管理,VPP自定义了vlib_buffer_t类型的缓冲区,其与rte_mbuf的关系如下:
#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
5
vlib_buffer_t存放在rte_mbuf的headroom中,通过此方法将DPDK与VPP的内存管理机制管理起来

  1. 从xd->rx_vectors得到rte_mbuf指针后,vlib_buffer_from_rte_mbuf再换算成vlib_buffer指针
    6

7

  1. 使用vlib_get_buffer_index函数得到每个vlib_buffer指针相对于buffer_mem_start的offset值
    即作了归一化后的包索引值,将指针值表示成索引值

8
9
这些包索引值将保存在to_next所指向的next_frame中的vector中

2.2.1.4. 验证处理结果

vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0);
当next0 != next_index时,说明该包被正确处理,该宏将do nothing
否则,说明本来该包应去next_index但是发生错误,使得next0 != next_index。该宏会将该错误包索引pi0发往到next0实际的下一个结点

2.2.1.5. vlib_pending_frame_t的添加

完成包处理后下一结点的frame已填充好包索引信息,说明可以进行调度处理需要添加到vlib_pending_frame_t待处理帧管理表中
vlib_put_next_frame(vm, node, next_index, n_left_to_next);
10
主要登记的信息包括:
下一结点frame索引、下一结点runtime_index、下一结点next_frame_index

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值