六、vpp 流表+负载均衡

草稿!!!

vpp node其实就是三个部分
1、plugin init
2、set command
3、function 实现功能,比如这里的流表

今天我们再用VPP实现一个流表的功能

一、流表

1.1流表----plugin init

VLIB_REGISTER_NODE 注册流表节点

// 注册流表节点
VLIB_REGISTER_NODE(flowtable_node) = {.function = flowtable_getinfo, // 节点处理函数.name = "flow-table", // 节点名称.vector_size = sizeof(u32), // 向量大小.format_trace = format_flowtable_getinfo, // 跟踪格式函数.type = VLIB_NODE_TYPE_INTERNAL, // 节点类型为内部节点.n_errors = FLOWTABLE_N_ERROR, // 错误数目.error_strings = flowtable_error_strings, // 错误字符串数组.n_next_nodes = FT_NEXT_N_NEXT, // 下一个节点数目.next_nodes = {[FT_NEXT_IP4] = "ip4-lookup",[FT_NEXT_DROP] = "error-drop",[FT_NEXT_ETHERNET_INPUT] = "ethernet-input",[FT_NEXT_LOAD_BALANCER] = "load-balance",[FT_NEXT_INTERFACE_OUTPUT] = "interface-output",} // 下一个节点的映射
};// 注册插件
VLIB_PLUGIN_REGISTER() = {.version = "1.0", // 插件版本.description = "sample of flowtable", // 插件描述
};

1.2 流表-----command 解析

接收到命令后,调用注册好的回调函数flowtable_command_enable_fn,最后会通过VPP自带的vnet_hw_interface_rx_redirect_to_node函数将硬件接口的接收流量重定向到指定节点,这里就是我们的流表节点

// 启用或禁用流表功能,将硬件接口的接收流量重定向到指定节点
int flowtable_enable(flowtable_main_t *fm,u32 sw_if_index,int enable){// 如果启用,获取流表节点的索引;如果禁用,则设置索引为无效值u32 node_index = enable ? flowtable_node.index : ~0;printf("debug:[%s:%s:%d] node_index:%d\n", __FILE__, __func__, __LINE__, flowtable_node.index);// 调用 VPP 的函数,将硬件接口的接收流量重定向到指定节点return vnet_hw_interface_rx_redirect_to_node(fm->vnet_main,sw_if_index,node_index);
}static clib_error_t * flowtable_command_enable_fn(struct vlib_main_t *vm,unformat_input_t *input,struct vlib_cli_command_t *cmd){// 获取与流表相关的主数据结构flowtable_main_t * fm = &flowtable_main;u32 sw_if_index = ~0;// 初始化接口索引为无效值int enable_disable = 1;// 初始化启用/禁用标志为启用// 解析命令行输入,直到输入结束while(unformat_check_input(input) != UNFORMAT_END_OF_INPUT){// 如果输入中包含 "disable" 参数,则禁用流表功能if(unformat(input,"disable")){enable_disable = 0;}// 如果输入中包含接口索引,则解析并存储在 sw_if_index 中else if (unformat(input,"%U",unformat_vnet_sw_interface,fm->vnet_main,&sw_if_index)){}elsebreak;}// 如果没有指定接口索引,则返回错误if(sw_if_index == ~0){return clib_error_return(0,"No Interface specified");}// 调用流表启用/禁用函数int rv = flowtable_enable(fm,sw_if_index,enable_disable);if(rv){if(rv == VNET_API_ERROR_INVALID_SW_IF_INDEX){return clib_error_return(0,"Invalid interface");}else if(rv == VNET_API_ERROR_UNIMPLEMENTED){return clib_error_return(0,"Device driver doesn't support redirection");}else{return clib_error_return(0,"flowtable_enable_disable returned %d\n",rv);}}return 0;
}//命令行启动、关闭流表功能
VLIB_CLI_COMMAND(flowtable_interface_enable_disable_command) = {.path = "flowtable",.short_help = "flowtable <interface> [disable]",.function = flowtable_command_enable_fn, //对应的flowtable命令行回调函数
};

1.3 流表------function

经过上面,这是当网卡接收到数据,就会传到我们指定的流表功能函数进行处理

static uword flowtable_getinfo(struct vlib_main_t *vm,struct vlib_node_runtime_t *node,struct vlib_frame_t *frame){u32 n_left_from, *from,*to_next;u32 next_index = node->cached_next_index;printf("flowtable_getinfo cached_next_index: %u\n", next_index);from = vlib_frame_vector_args(frame);//获取指向帧向量数据的指针,即第一个数据包的地址n_left_from = frame->n_vectors;	// 获取向量数量,即有多少个数据包while(n_left_from > 0){u32 n_left_to_next;/*获取下一个节点的帧和向量,然后vlib_put_next_frame将当前节点处理的数据包添加到这个帧中,以便后续的节点可以处理这些数据包,最开始这里是获取的第一帧,一帧里面有多个vlib_buffer可以看做为二维数组*/vlib_get_next_frame(vm,node,next_index,to_next,n_left_to_next);/*n_left_to_next 是当前帧中剩余的空闲槽位数量,当值为0后,需要vlib_put_next_frame获取一个新的帧来继续传递数据包*/while(n_left_from > 0 && n_left_to_next > 0){vlib_buffer_t *b0;u32 bi0,next0 = 0;bi0 = to_next[0] = from[0];from += 1;to_next += 1;n_left_to_next -= 1;n_left_from -= 1;//它将 DPDK 的 rte_mbuf 转换为 VPP 的 vlib_buffer_t,vlib_buffer_t里面有多个rte_mbuf(数据包)b0 = vlib_get_buffer(vm,bi0);//取出当前需要处理的数据包ip4_header_t *ip0 = vlib_buffer_get_current(b0);ip4_address_t ip_src = ip0->src_address;ip4_address_t ip_dst = ip0->dst_address;//获取处理的数据包所到达的接口的软件索引,并将其存储在变量 sw_if_index0 中u32 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];//对每个数据包打印其源ip及目的ipstruct in_addr addr;addr.s_addr = ip_src.as_u32;printf("sw_if_index0: %d, ip_src: %s ", sw_if_index0, inet_ntoa(addr));addr.s_addr = ip_dst.as_u32;printf(" ip_dst: %s \n", inet_ntoa(addr));/*将当前处理的缓冲区 bi0 传递到下一个节点,同时更新 to_next 数组、n_left_to_next 计数和下一个节点的下一个节点索引 next0。这样,数据包将会在当前节点处理后传递到下一个节点进行进一步处理*/vlib_validate_buffer_enqueue_x1(vm,node,next_index,to_next,n_left_to_next,bi0,next0);}/*vlib_get_next_frame获取下一个节点的帧和向量,然后vlib_put_next_frame将当前节点处理的数据包添加到这个帧中,		以便后续的节点可以处理这些数据包*/vlib_put_next_frame(vm,node,next_index,n_left_to_next);}return frame->n_vectors; //这里决定接下来继续走哪一个node
}

这里的function函数有个返回值,根据返回值决定下一个节点走哪里
flowtable_getinfo这里处理函数返回2 ,则下一步走这个节点[FT_NEXT_ETHERNET_INPUT] = “ethernet-input”,
在这里插入图片描述

浅谈node

在一些系统中,节点的执行顺序可能是在程序初始化的时候静态确定的,特别是在构建数据处理流水线时。这种情况下,节点的顺序是在配置或初始化阶段定义的,然后在整个程序运行期间保持不变。

然而,在某些系统中,特别是对于一些灵活的数据流框架,节点的执行顺序可能是在程序运行时动态决定的。这可以通过某种策略或运行时的条件来调整节点的执行顺序,以适应实时需求或系统的动态变化。

总的来说,节点的执行顺序是取决于应用程序设计和需求的。一些系统更倾向于静态的、在初始化时确定的执行顺序,而其他系统则更注重在运行时根据动态需求来调整节点的执行顺序

在许多系统中,插件和节点的初始化顺序通常是通过配置文件、命令行参数或其他配置机制来确定的。这些配置通常在应用程序启动时被解析,并在初始化过程中用于指导插件和节点的加载和初始化。

以下是一些可能的方式来决定插件和节点的顺序:

配置文件: 应用程序可能会有一个配置文件,其中包含有关插件和节点的信息,包括它们的加载顺序。在应用程序启动时,解析配置文件并按照其中定义的顺序加载插件和节点。

命令行参数: 应用程序可能允许通过命令行参数来指定插件和节点的加载顺序。例如,通过在启动命令中指定参数来控制加载的插件和它们的顺序。

硬编码: 在某些情况下,加载顺序可能是硬编码在应用程序的源代码中的,即在代码中明确指定加载和初始化的顺序。

依赖关系: 插件和节点之间可能存在依赖关系,系统可以根据这些依赖关系来确定加载和初始化的顺序。例如,某个插件可能依赖于另一个插件的某些功能,因此必须在其之前加载。

具体的实现方式取决于系统的设计和开发者的选择。在某些情况下,可能会结合使用上述多种机制来达到更大的灵活性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在CSV文件读取时id读取之后成了‘锘縤d‘,该怎么修改

问题描述 准备用python实现一个小想法&#xff0c;里边数据可能会有点多&#xff0c;也为了代码能成块展示&#xff0c;所以打算写一个读取文件的函数。此时考虑到python中可以直接将CSV格式文件读取成字典的形式&#xff0c;所以尝试了一下。但是中间出现了错误&#xff0c;第…

软件测试|Python自动化测试实现的思路

Python自动化测试常用于Web应用、移动应用、桌面应用等的测试 Python自动化实现思路通常分为以下几步&#xff1a; 1. 确定自动化测试的范围和目标&#xff1a; 首先需要明确需要进行自动化测试的范围和目标&#xff0c;包括测试场景、测试用例、测试数据等。 2. 选择自动化…

Golang接口实现OCP原则

文章目录 Golang接口实现OCP原则实例 Golang接口实现OCP原则 OCP&#xff1a; Open-Closed Principle 开闭原则&#xff0c;对扩展是开发的&#xff0c;对修改是关闭的。 实例 package mainimport "fmt"type Pet interface {eat()sleep() } type Dog struct { } t…

详解IDEA git 版本回滚

作者简介 目录 1.git分区 2.未commit&#xff0c;进行回滚 3.commit未push&#xff0c;进行回滚 3.1.undo commit 3.2.reset 4.已commit&push&#xff0c;进行回滚 1.git分区 git的版本回滚其实就是回滚不同的分区&#xff0c;所以在聊git回滚之前我们有必要简单了解…

开源即时通讯IM框架 MobileIMSDK v6.4 发布

一、更新内容简介 本次更新为次要版本更新&#xff0c;进行了若干优化&#xff08;更新历史详见&#xff1a;码云 Release Notes、Github Release Notes&#xff09;。MobileIMSDK 可能是市面上唯一同时支持 UDPTCPWebSocket 三种协议的同类开源IM框架。 二、MobileIMSDK简介…

css选择器及其权重

在CSS中&#xff0c;选择器是用来选择HTML元素并应用样式规则的一种方式。每个选择器都有一个与之相关联的权重&#xff0c;用来确定当多个规则应用到同一个元素时&#xff0c;哪个规则会优先生效。权重是由选择器的类型和组合方式来决定的。下面是一些常见的CSS选择器及其权重…

基于风驱动优化的BP神经网络(分类应用) - 附代码

基于风驱动优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于风驱动优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.风驱动优化BP神经网络3.1 BP神经网络参数设置3.2 风驱动算法应用 4.测试结果&#x…

递归

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;汉诺塔 &#x1f449;&…

redis 雪崩,穿透,击穿及解决方案

一、缓存雪崩&#xff1a; 1. 原因: 缓存雪崩是指在我们设置缓存时大量采用了相同的过期时间&#xff0c;导致缓存在某一时刻同时失效&#xff0c;请求全部转发到DB&#xff0c;DB瞬时压力过重雪崩。 2. 解决方案: 将失效时间分散&#xff0c;通过生成随机数使得key的过期时间…

Redis 分布式锁

Redis分布式锁 - 胤凯 (oyto.github.io) 分布式锁 1、什么是分布式锁&#xff1f; 在分布式场景下的锁&#xff0c;比如在多台不同机器上的进程&#xff0c;去竞争同一项资源&#xff0c;就是分布式锁。 2、分布式锁有哪些特性&#xff1f; 互斥性&#xff1a;只能让一个竞…

java 将字符串转为Base64格式与将Base64内容解析出来

首先要引入依赖包 import java.nio.charset.StandardCharsets; import java.util.Base64;然后对应一下两个代码 将字符串转为Base64 Base64.getEncoder().encodeToString(需要转换的字符串.getBytes(StandardCharsets.UTF_8));将 Base64 字符串解析成原来的内容 byte[] deco…

每日一题 901. 股票价格跨度(中等,单调栈)

理解题目&#xff0c;对于第 i 天&#xff0c;要求的是前 i - 1 天所满足条件的跨度 思路&#xff1a; 暴力搜索的方式是&#xff0c;对于每一个第 i 天都遍历搜索 i - 1&#xff0c; i - 2&#xff0c;…&#xff0c;直到第 j 天大于当前价格优化&#xff0c;考虑哪里进行了…

SQL的CASE WHEN函数、CAST函数、CONVERT() 函数、COALESCE()函数、DATEDIFF()函数

一、CASE WHEN简单使用 SELECT CASE WHEN age > 18 AND age < 25 THEN 18-25WHEN age > 25 AND age < 35 THEN 25-35WHEN age > 35 AND age < 45 THEN 36-45ELSE 45END AS age_groupFROM peopleGROUP BY age_group;二、CASE WHEN语句与聚合函数一起使用 SE…

论文总结:3D Talking Face With Personalized Pose Dynamics

论文解决的问题:大多数现有的3D人脸生成方法只能生成静态头部姿势的3D面部,只有少数几篇文章关注头部姿势的生成,但这些文章也忽略了个体属性。 解决方法:框架由两个独立模块组成:PoseGAN和PGFace。给定输入音频,PoseGAN首先为3D头部生成一个头部姿势序列,然后PGFace利用…

blender光照系统设置

0&#xff09;Viewport Shading设置里面的Lighting下面的参数&#xff1a; Scene Lights,Scene World - Scene Lights是指在渲染模式下是否使用场景中的灯光对象来照亮物体。 - Scene World是指在渲染模式下是否使用场景中的世界设置来作为背景和环境光。如果关闭该选项&#…

数据库基础知识

数据库 什么是数据库, 数据库管理系统, 数据库系统, 数据库管理员? 数据库 : 数据库(DataBase 简称 DB)就是信息的集合或者说数据库是由数据库管理系统管理的数据的集合。数据库管理系统 : 数据库管理系统(Database Management System 简称 DBMS)是一种操纵和管理数据库的大…

Redis Cluster Gossip Protocol: FAIL, UPDATE

返回目录 FAIL的发送 过程 构建消息头把处于FAIL状态的node的ID填入消息的数据部分广播消息 遍历cluster节点字典:跳过还没有创建连接的node跳过myself和处于handshake的node给node发送FAIL消息FAIL的接收处理 过程 第1 ~ 3步是涵盖所有类型的消息&#xff0c;详细请参考…

RPA自动化全平台文章同步助手

在当今文案自媒体时代&#xff0c;我们通常在各大平台都拥有账号&#xff0c;需要同步发布文章。然而&#xff0c;这个过程常常让人感到非常繁琐&#xff0c;因为我们需要将文章复制粘贴到不同平台上。但是&#xff0c;现在我们可以借助RPA&#xff08;Robotic Process Automat…

TL-ER3220G端口映射设置

1、打开IE浏览器或其它浏览器&#xff0c;在地址栏输入192.168.1.1登录路由器的Web管理界面&#xff1b; 2、打开后弹出密码输入框&#xff0c;输入路由器的用户名和密码&#xff0c;出厂默认值为admin/admin&#xff0c;成功登录后将看到路由器的系统状态信息&#xff1b; 3、…

java技术文档--多线程(1)--核心学习大纲--首页

阿丹&#xff1a; 对于java来说最核心也是一个java程序员最大竞争力的就是多线程的开发。希望我的这一套多线程学习的体系可以帮助大家整理以及清楚明白的使用多线程&#xff0c;并了解多线程的底层。其实不少同学在提到多线程的时候一下就头大了。没关系阿丹将多线程这里用深…