vpp node 及 vpp 多线程

node 注册

node注册,即宏VLIB_REGISTER_NODE(x, ...)流程:

  1. 创建vlib_node_registration_t x;vlib_node_registration_t结构只是存放了用户提供的node相关信息。
  2. 把x添加到全局变量vlib_global_main中的node_registrations链表中(从头加)。
  3. 使用__attribute__ ((__constructor__))修饰,表示为构造函数,会在main函数之前被执行。
  4. 在main函数中会根据vlib_node_registration_t结构分配vlib_node_t结构,vlib_node_t结构是真正node对应的结构,数据处理流程中访问的也是vlib_node_t结构。
  • 函数调用:vlib_main --> vlib_register_all_static_nodes --> vlib_register_node --> vec_add1,函数vlib_register_node中会申请空间并调用函数vec_add1将新分配的节点加入vm->node_main.nodes 数组中,其中node->index 就是该 node 在 vm->node_main.nodes 数组中的索引;
  • hash_set (nm->node_by_name, n->name, n->index);以 node 的名称作为 key, index 作为 value 加入 hash 表 node_by_name 中
  • 复制 vlib_node_registration_t 结构的各个字段到 vlib_node_t 结构里
  •  error 和 elog 的初始化
  • 私有数据runtime_data指针的拷贝,该部分数据由用户提供

node 图的初始化

node图的初始化,即函数vlib_node_main_init处理,在函数vlib_main中被调用。

  1. VLIB_NODE_MAIN_RUNTIME_STARTED表示node图已经初始化过了。
  2. 遍历nm->nodes,nm->nodes在节点注册时会有元素加入,判断是否又兄弟节点。
  3. 如果有兄弟节点,就将该节点index加入到所有的兄弟节点的位图中,同时把所有的兄弟节点的index加入到该节点的位图中。

指定下一个节点的一般步骤

  1. 根据业务确定下一个节点
  2. 调用vlib_get_next_frame函数确定下一个节点保存数据包的位置to_next
  3. 根据业务将数据包给到to_next中
  4. 执行vlib_put_next_frame函数将下一个node要处理的数据加入到nm->pending_frames
  5. vlib_main_loop中会在dispatch_pending_node函数中处理pending_node
  6. 创建 vlib_pending_frame_t 结构,并把它加入数组 vm->node_main. pending_frames 等待调度vlib_pending_frame_t 结构记录报文所在的结构 vlib_next_frame_t 的 index,以及处理这些报文的node 的 vlib_node_runtime_t 结构的索引,这样通过 vlib_pending_frame_t 结构里面的信息就可以把报文分发给指定的 node 处理了

node节点调度

调度类型

老版本中只有主线程中才运行pre_input类型节点,新版本中主线程和worker线程都可以运行pre_input节点

调度方式总结

个人理解:从代码上来看只有Input类型的node节点注册的时候state设置成中断方式,才会出现中断和轮训的切换,默认全是轮询方式。PRE_INPUT类型node只能按照轮询当时来调度。设置成state为中断也是一样的。

中断方式和轮询方式之间切换。

    模式切换依据累计报文数量,在vlib_main_or_worker_loop启动中设置。

开启多线程

修改配置文件startup.conf,添加下面的内容,表示主线程运行在0核,3个worker线程运行在1-3核。

cpu {
   main-core 0
   corelist-workers 1-3
}

执行make run不会使用配置文件,是在Makefile文件中指定启动参数,所以需要修改Makefile文件,将开启多线程的配置添加上,如下图

创建接口后就会绑定worker,通过命令show interface rx-placement查看接口收包被分配到那个线程中。

设置对称哈希算法,保证同一个流总是由相同的worker处理,参考https://blog.csdn.net/sina t_20184565/article/details/126923384

set interface handoff host-vpp workers 0-1 symmetrical
set interface handoff vpp1/0 workers 1-1 symmetrical

注册线程

使用宏VLIB_REGISTER_THREAD注册。

  • 定义vlib_thread_registration_t x,添加到vlib_thread_main的next链表(vlib_thread_registration_t类型指针)
  • 函数cpu_config中,解析配置文件确定线程名字和数量,然后对vlib_thread_main.next链表中的元素的coremask和count进行设置。
  • 在函数start_workers中根据vlib_thread_main.next链表的元素进行线程的创建。

线程初始化(创建线程)

  • 创建线程的函数为start_workers,在文件thread.c中会使用宏VLIB_MAIN_LOOP_ENTER_FUNCTION注册start_workers函数。宏VLIB_MAIN_LOOP_ENTER_FUNCTION会将函数注册到链表vgm->main_loop_enter_function_registrations中,主函数vlib_main中会调用vlib_call_all_main_loop_enter_functions函数统一对注册的函数进行处理,该函数中会遍历vgm->main_loop_enter_function_registrations链表并执行链表中已经注册的函数(start_workers)。
  • start_workers函数中会调用vlib_launch_thread_int函数创建线程,即调用函数pthread_createpthread_setaffinity_np等函数创建线程并设置线程亲核性,线程处理函数为vlib_worker_thread_bootstrap_fn该函数中会调用vlib_worker_thread_fn函数,该函数中会调到vlib_worker_loop。创建线程个数和线程亲核性由tr->coremasktr->count决定,tr->coremask为线程和cpu的位图映射,tr->count表示线程数。
  • tr->coremasktr->count的设置:在函数cpu_config中通过解析配置文件内容设置,coremask位表示那个核绑定线程,count为线程总数。

vlib_main_or_worker_loop函数流程

  • 初始化nm->pending_frames,记录开始运行时间,初始化运行环境。
  • 遍历nm->processes,调用dispatch_process函数处理process类型节点。
  • 进入死循环
    • m->pending_rpc_requests
    • vlib_worker_thread_barrier_check,worker线程和主线程同步操作,会有锁操作
    • tm->frame_queue_mains
    • 处理pre-input类型节点
    • 处理input类型节点
    • 处理中断方式触发的input节点,例如xdp的收包节点就是在这里完成调度。
    • 遍历pending_frames数组,处理所有internal节点,从input节点或internal节点调度到internal节点一般都是这样调度的。
    • 更新循环计数和时间等操作。

接收包队列分配线程

上面提到使用命令show interface rx-placement可以查看接口和线程绑定信息,这条命令的处理函数show_interface_rx_placement_fn中会遍历所有的接口收包队列从而获取每个队列绑定的线程ID,即qptr[0]->thread_index。然后将线程ID对应的线程信息和绑定接口的收包节点信息显示出来。收包队列和线程的绑定在xdp接口创建时完成。

  • 函数af_xdp_create_if中会调用af_xdp_finalize_queues函数完成创建收包队列等一系列工作,这里会完成接口收包队列和线程的绑定。
  • 函数af_xdp_finalize_queues中会调用函数vnet_hw_if_register_rx_queue分配一个收包队列并分配一个线程完成绑定。
  • 函数vnet_hw_if_register_rx_queue中会调用next_thread_index函数分配一个 线程,并将分配的线程id记录到rxq->thread_index
  • 函数next_thread_index中返回vdm->next_worker_thread_index++vdm->next_worker_thread_index值在vdm->first_worker_thread_indexvdm->last_worker_thread_index区间中。
  • vdm->first_worker_thread_indexlast_worker_thread_indexnext_worker_thread_index的初始化在函数vnet_device_init中完成。
    • vdm->first_worker_thread_index = tr->first_index;
    • vdm->next_worker_thread_index = tr->first_index;
    • vdm->last_worker_thread_index = tr->first_index + tr->count - 1;
  • tr->first_index在函数vlib_thread_init中完成初始化,默认值为1
  • tr->count在函数cpu_config中解析配置文件被赋值

多线程是怎样收包和处理包的

每个线程都有独立的处理占和数据包缓存空间,同一个数据包不会在多个线程中被处理。

  • 创建worker线程时会指定线程处理函数vlib_worker_thread_bootstrap_fn,该函数中会记录当前线程的索引__os_thread_index中,即__os_thread_index = w - vlib_worker_threads,__os_thread_index在后面的流程中会被使用,然后执行每个worker线程的处理函数w->thread_function,worker线程的处理函数为vlib_worker_thread_fn函数,这个函数在注册线程时指定。
  • 函数vlib_worker_thread_fn中,首先会根据__os_thread_index值获取每个线程的一个全局结构vmvlib_main_t ),即vm = vlib_get_main (),后续的所有数据都是从该vm中获取。紧接着会执行vlib_worker_loop函数。
  • vlib_worker_loop函数中会执行vlib_main_or_worker_loop函数,该函数中完成了所有节点的调度。其中的node信息和数据包信息都是从全局变量vm中获取的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/311230.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

本地开发环境请求服务器接口跨域的问题(vue的问题)

上面的这个报错大家都不会陌生,报错是说没有访问权限(跨域问题)。本地开发项目请求服务器接口的时候,因为客户端的同源策略,导致了跨域的问题。下面先演示一个没有配置允许本地跨域的的情况: 可以看到&…

如何在数学建模竞赛中稳定拿奖

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。 🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心&…

[三星电子]算法题--两种颜色涂无向图(bfs)

题目 题目描述: 给一无向图中各个节点绘色,一共只有两种颜色,使其满足相邻节点颜色不同,并输出其中一种颜色的节点个数及序号;如果不满足,则输出-1。 示例: 第一行输入节点个数V和边数E&…

数字信号处理实验---Z变换及系统的零极点分析 Matlab代码

一.各种函数的用法 1.tf2zp函数:通常用于将传递函数(Transfer Function)转换为零极增益形式(ZPK form),转换前G(s) num(s) / den(s),转换后G(s) K * (s - z1) * (s - z2) * ... *…

freeRTOS总结(四)中断管理

1、什么是中断 打断CPU正常运行程序,转而处理紧急的事件(中断服务函数)。 中断执行机制3步 1、中断请求 2、响应中断 3、退出中断 2 中断优先级 cortex-M使用8位寄存器配置中断优先级 stm32只用到高4位 stm32优先级分为抢占优先级和子优先…

如何测量电源芯片的电压调整率?电源芯片检测系统助力测试

电源芯片电压调整率的测试方法 测试环境: 温度:252℃ 湿度:60%~70% 大气压强:86kPa~106kPa 测试工具:可调电源、可调电子负载、万用表 测试步骤: 1. 设置电子负载,使电源满载输出; 2. 调节电源芯…

LORA的基本原理

本文将介绍如下内容: 什么是Lora高效微调的基本原理LORA的实现方式LORA为何有效? 一、什么是LoRA LoRA 通常是指低秩分解(Low-Rank Decomposition)算法,是一种低资源微调大模型方法,论文如下: LoRA: Low…

深入理解计算机系统(1):开始

计算机系统是由硬件和系统软件组成的,它们共同工作来运行应用程序。虽然系统的具体实现方式随着时间不断变化,但是系统内在的概念却没有改变。所有计算机系统都有相似的硬件和软件组件,它们又执行着相似的功能。 计算机系统 信息就是位上下…

C++I/O流——(1)I/O流的概念

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 勤奋,机会,乐观…

Nginx配置反向代理实例二

Mac 安装Nginx教程 Nginx配置反向代理实例一 提醒一下:下面实例讲解是在Mac系统演示的; 反向代理实例二实现的效果 使用nginx 反向代理,根据访问的地址跳转到不同端口的服务中 nginx 监听端口为81; 访问地址1:http:/…

QTday4作业

思维导图: widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime> #include <QTimerEvent> #include <QPushButton> #include <QTextToSpeech> #include <QDebug>namespace Ui { class Widget; }class Widget…

实现稳定的联合显著性检测和联合目标分割

1 Title Toward Stable Co-Saliency Detection and Object Co-Segmentation(Bo Li; Lv Tang; Senyun Kuang; Mofei Song; Shouhong Ding)【IEEE Transactions on Image Processing 2022】 2 Conclusion This paper present a novel model for simultaneous stable co-saliency…

数据分析讲课笔记01:数据分析概述

文章目录 零、学习目标一、本次课程概述二、数据分析的背景&#xff08;一&#xff09;进入大数据时代&#xff08;二&#xff09;数据分析的作用 三、什么是数据分析&#xff08;一&#xff09;数据分析的概念&#xff08;二&#xff09;数据分析的分类1、描述性数据分析2、探…

公网环境使用移动端设备+cpolar远程访问本地群晖nas上的影视资源

文章目录 1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑浏览器访问本地群晖video station5.公网条件下使用移动端&#xff08;搭载安卓&#xff0c;ios&#xff0c;ipados等系统的设备…

WiFi7无线路由器TL-7DR6560简单开箱测评

TPLINK/普联 TL-7DR6560易展Turbo版 BE6500 双频WiFi7无线路由器简单开箱测评&#xff0c;4个2.5G网口&#xff0c;6颗独立FEM&#xff0c;双频6流。 TP-LINK XDR6088 WiFi6路由器 简单开箱评测&#xff1a;https://blog.zeruns.tech/archives/731.html 分享一下我家网络机柜…

Macos下修改Python版本

MacOS下修改Python版本 安装 查看本机已安装的Python版本&#xff1a;where python3 ~ where python3 /usr/bin/python3 /usr/local/bin/python3 /Library/Frameworks/Python.framework/Versions/3.12/bin/python3如果没有你想要的版本&#xff0c;去python官网下载安装包。…

Day4Qt

1.头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime>//时间类 #include <QTimer>//时间事件类 #include <QTimerEvent>//定时器类 #include <QTextToSpeech> namespace Ui { class Widget; }class Widget : publi…

esp32-cam使用SD卡/web端保存拍摄图片到本地

目录 一、esp32-cam运行esp-who的人脸识别报错 二、挂载sd卡到esp32-cam&#xff0c;并将拍摄的图片保存到sd卡三、通过web示例对拍摄的图片进行保存 保存拍摄图片主要是想加在人脸识别这个项目中&#xff0c;所以先把人脸识别示例跑通&#xff0c;然后在把挂在sd卡的部分放进来…

7.云原生之jenkins集成SonarQube

1. 私有云实战之基础环境搭建 2. 云原生实战之kubesphere搭建 3.云原生之kubesphere运维 4. 云原生之kubesphere基础服务搭建 5.云原生安全之kubesphere应用网关配置域名TLS证书 6.云原生之DevOps和CICD 7.云原生之jenkins集成SonarQube 8.云原生存储之Ceph集群 文章目录 搭建 …

美国证券交易委员会 X 账户被黑,引发比特币市场震荡

Bleeping Computer 网站消息&#xff0c;威胁攻击者成功“占领”了美国证券交易委员会的 X 账户&#xff0c;并发布一条关于批准比特币 ETF 在证券交易所上市的虚假公告。 帖子原文&#xff1a;今天&#xff0c;美国证券交易委员会批准比特币 ETF 在注册的国家证券交易所上市&a…