博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
4. VPP源码分析(graph node(2))
阅读量:6148 次
发布时间:2019-06-21

本文共 2562 字,大约阅读时间需要 8 分钟。

2.2.2. VLIB_NODE_TYPE_PROCESS结点

每个process结点是由jump机制构成的一个协程,协程主要用于等待、处理事件。

使用longjmp/setjmp的轻量级多任务协程,由应用进程自行进行调度,不受操作系统调度机制的影响,上下文切换只损耗调用longjmp/setjmp的时间。
协程中运行的函数类似于线程函数,区别在于协程函数Can be suspended, wait for events, be resumed… (based on setjump/longjump).

  • Wait for an event
    always_inline f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
  • Send an event
    always_inline void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)

2.2.2.1. vlib_process_t结构体

1

2
协程间的切换最重要的是要保护CPU寄存器和私有栈。
这里clib_longjmp_t中保存上下文切换时CPU寄存器的信息,而相应的栈信息保存在process结构体中stack后续的内存空间中。

2.2.2.2. process node的初始化

在vlib_main_or_worker_loop开始包处理循环之前,main线程会对所有的process结点都调度一次,执行相应的node函数,类似于初始化操作。

3
在dispatch_process函数中讲调用vlib_process_startup函数,处理所有process结点的初始化工作。
vlib_process_startup先记录每个process结点正常返回时的jmp信息(return_longjmp),之后跳到vlib_process_bootstrap函数中执行process结点函数。
4

2.2.2.3. process node函数

以下为某个典型的process结点函数:

5
该函数为while (1)的形式,说明该node函数将一直执行直到应用进程退出为止。
而在开始的时候这里先调用了vlib_process_wait_for_event函数,检查是否由事件需要处理。

该函数先去检查non_empty_event_type_bitmap是否置位,如有说明有需要处理的事件则立刻返回进行处理,否则说明该process node任然需要等待事件,暂不需要分配CPU时间,可以进入suspend状态。

所以,这里先记录下当前的位置(记为resume_longjmp),然后再跳回return_longjmp所记录的位置,完成一次结点调度过程。
这样,初始化时调用的dispatch_process可以先初始化所有的process node,而各process node暂时处于suspend状态,等待某个条件的到来进入resume状态并执行业务逻辑,执行完后退出释放CPU资源。
6

2.2.3. VLIB_NODE_TYPE_INTERNAL结点

internal结点主要用于处理数据包业务逻辑,结点通过函数流程上与input结点大致相同。

static uword sample_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)

2.2.3.1. 从本node frame中取包

vlib_frame_t *frame    -> 由node函数入口传入 U32 *from              -> 当前frame中vector的起始数据from = vlib_frame_vector_args(frame);

调用vlib_frame_vector_args函数返回本node vlib_frame_t中数据包的起始位置,对包进行处理使用from[0],from[1]…

2.2.3.2. to_next指针的获得

vlib_main_t *vm  = vlib_get_main ();u32 next_index   = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;vlib_node_runtime_t *node;u32 n_left_to_next;u32 *to_next;vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);

调用vlib_get_next_frame函数,找到下一node对应的vlib_frame_t中合适的存放数据包的起始位置并保存到to_next

如果要发送数据包,则可以修改to_next[0],to_next[1]……中的数据包索引值

2.2.3.3. 验证处理结果

vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0);next_index   -> 默认的下一结点的indexnext0        -> 实际的下一个结点的index

当next0 != next_index时,说明该包被正确处理,该宏将do nothing

否则,说明本来该包应去next_index但是经过包处理需要去往其他结点
使得next0 != next_index,该宏会将该包索引pi0发往到next0实际的下一个结点

2.2.3.4. 登记调度

vlib_put_next_frame(vm, node, next_index, n_left_to_next);

所有流程都正确处理完毕后,下一结点的frame上已经有本结点处理过后的数据索引
执行该函数,将相关信息登记到vlib_pending_frame_t中,准备开始调度处理

2.2.3.5. 具体实例

1

转载地址:http://wbqya.baihongyu.com/

你可能感兴趣的文章
解决ros建***能登录不能访问内网远程桌面的问题
查看>>
vsftpd 相关总结
查看>>
售前工程师的成长---一个老员工的经验之谈
查看>>
Get到的优秀博客网址
查看>>
【Git入门之四】操作项目
查看>>
老男孩教育每日一题-第107天-简述你对***的理解,常见的有哪几种?
查看>>
Python学习--time
查看>>
在OSCHINA上的第一篇博文,以后好好学习吧
查看>>
软件概要设计做什么,怎么做
查看>>
dwr
查看>>
java的特殊符号
查看>>
word2010中去掉红色波浪线的方法
查看>>
fabric上下文管理器(context mangers)
查看>>
JQuery-EasyUI Datagrid数据行鼠标悬停/离开事件(onMouseOver/onMouseOut)
查看>>
并发和并行的区别
查看>>
php小知识
查看>>
Windows下安装、运行Lua
查看>>
Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解(二)
查看>>
初识中间件之消息队列
查看>>
MyBatis学习总结(三)——优化MyBatis配置文件中的配置
查看>>