Open vSwitch 中的 vswitchd 事件上报

 一、数据包转发流程与 vswitchd 事件上报

        Open vSwitch 的数据包转发流程如下图所示:

        在数据包的转发流程中,提到过慢速路径的概念:即当数据包在内核空间无法完全处理时,会产生 upcall 调用,将数据包从内核空间转发到用户空间进行处理,对应上图中的步骤(1→2→3→4→5→6→7)。

        这里图中的步骤(3)对应的是 vswitchd 守护进程与控制器的通信过程,可以细分为两个部分:vswitchd 事件上报和 OpenFlow 流表下发。所谓的 vswitchd 事件上报指的是 vswitchd 守护进程也无法完全处理数据包,需要将信息上报给控制器进行决策;所谓的 OpenFlow 流表下发指的是控制器在收到  vswitchd 上报的信息之后,将相应流表传输到 vswitchd 守护进程的过程。

Tips:对于 OpenFlow 流表下发这个过程而言,Open vSwitch 或者说是整个领域有一套广泛约定的流程,即 OpenFlow 协议,这里不做展开。本文重点关注 vswitchd 事件上报的过程。

二、vswitchd 事件上报的应用场景

        按照数据包的处理流程,当 Datapath 模块无法完全处理数据包时,会产生 upcall 调用,将数据包交给 vswitchd 守护进程。于是这里就存在一个问题:

vswitchd 守护进程在收到数据包后一定会上报给控制器吗?

答:不一定。原因如下:

        在 Open vSwitch 守护进程的 upcall 处理 和 Open vSwitch 中 upcall 消息的类型 这两篇文章中详细讨论过:

  • 对于 upcall 消息而言,只有 MISS 和 ACTION 这两种主要类型,而其他类型都是这两种基本类型的细化。
  • 对于不同的 upcall 类型,vswitchd 守护进程中的 upcall 消息处理函数 process_upcall() 会执行不同的处理逻辑。

        其中,当内核空间的 Datapath 模块匹配不到流表项时,将会产生 MISS 类型的 upcall 消息,在处理过程中相应地调用 upcall_xlate(),并不涉及和控制器通信的部分。

        当消息类型为 CONTROLLER_UPCALL 类型时(注意这是 ACTION 类型的细化),则 vswitchd 守护进程会与控制器进行通信。

        

Tips:细心的你可能早就注意到了,在数据包转发的流程图中,所有步骤的数字,只有第三步是带括号的,而其他步骤是不带括号的。这就是因为并不是所有的 upcall 调用都会产生 vswitchd 守护进程与控制器的通信,而是根据需要或者说是设定的规则来进行的。

三、vswitchd 事件上报机制实现

        在 Open vSwitch 守护进程的 upcall 处理 中讨论过 process_upcall() 对于 CONTROLLER_UPCALL 类型 upcall 消息的处理:

    case CONTROLLER_UPCALL:{struct user_action_cookie *cookie = &upcall->cookie;......const struct frozen_state *state = &recirc_node->state;struct ofproto_async_msg *am = xmalloc(sizeof *am);*am = (struct ofproto_async_msg) {.controller_id = cookie->controller.controller_id,.oam = OAM_PACKET_IN,.pin = {.up = {.base = {.packet = xmemdup(dp_packet_data(packet), dp_packet_size(packet)),.packet_len = dp_packet_size(packet),.reason = cookie->controller.reason,.table_id = state->table_id,.cookie = get_32aligned_be64(&cookie->controller.rule_cookie),.userdata = (recirc_node->state.userdata_len ? xmemdup(recirc_node->state.userdata, recirc_node->state.userdata_len) : NULL),.userdata_len = recirc_node->state.userdata_len,},},.max_len = cookie->controller.max_len,},};if (cookie->controller.continuation) {am->pin.up.stack = (state->stack_size ? xmemdup(state->stack, state->stack_size) : NULL),am->pin.up.stack_size = state->stack_size,am->pin.up.mirrors = state->mirrors,am->pin.up.conntracked = state->conntracked,am->pin.up.actions = (state->ofpacts_len ? xmemdup(state->ofpacts, state->ofpacts_len) : NULL),am->pin.up.actions_len = state->ofpacts_len,am->pin.up.action_set = (state->action_set_len ? xmemdup(state->action_set, state->action_set_len) : NULL),am->pin.up.action_set_len = state->action_set_len,am->pin.up.bridge = upcall->ofproto->uuid;am->pin.up.odp_port = upcall->packet->md.in_port.odp_port;}......ofproto_dpif_send_async_msg(upcall->ofproto, am);}break;

        这段代码主要用于构造 ofproto_async_msg 信息,并通过 ofproto_dpif_send_async_msg(upcall->ofproto, am) 函数将构造好的 ofproto_async_msg 消息发送给控制器。其中 ofproto_dpif_send_async_msg() 函数存储在 ovs-main/ofproto/ofproto-dpif.c 文件中:

/* Appends 'am' to the queue of asynchronous messages to be sent to the controller. * Takes ownership of 'am' and any data it points to. */
void ofproto_dpif_send_async_msg(struct ofproto_dpif *ofproto, struct ofproto_async_msg *am) {if (!guarded_list_push_back(&ofproto->ams, &am->list_node, 1024)) {COVERAGE_INC(packet_in_overflow);ofproto_async_msg_free(am);}/* Wakes up main thread for packet-in I/O. */seq_change(ofproto->ams_seq);
}

        通过观察可以发现,这个函数主要用于向异步消息队列中添加消息,并唤醒主线程进行处理。函数首先使用 guarded_list_push_back() 函数将 am->list_node 添加到 ofproto->ams 中,相应的 guarded_list_push_back() 函数存储在 ovs-main/lib/guarded-list.c 文件中:

/* If 'list' has fewer than 'max' elements, adds 'node' at the end of the list and returns the number of elements now on the list.* If 'list' already has at least 'max' elements, returns 0 without modifying the list. */
size_t guarded_list_push_back(struct guarded_list *list, struct ovs_list *node, size_t max) {size_t retval = 0;ovs_mutex_lock(&list->mutex);if (list->n < max) {ovs_list_push_back(&list->list, node);retval = ++list->n;}ovs_mutex_unlock(&list->mutex);return retval;
}

        如果队列已满,则使用 COVERAGE_INC(packet_in_overflow) 维护溢出统计信息,并通过 ofproto_async_msg_free(am) 释放相应资源,相应的 ofproto_async_msg_free() 函数存储在 ovs-main/ofproto/connmgr.c 文件中:

void ofproto_async_msg_free(struct ofproto_async_msg *am) {free(am->pin.up.base.packet);free(am->pin.up.base.userdata);free(am->pin.up.stack);free(am->pin.up.actions);free(am->pin.up.action_set);free(am);
}

        在进行接收后(无论成功与否),都会通过 seq_change(ofproto->ams_seq) 唤醒主线程进行数据包处理,相应的 seq_change() 函数存储在 ovs-main/lib/seq.c 文件中:

/* Increments 'seq''s sequence number, waking up any threads that are waiting on 'seq'. */
void seq_change(struct seq *seq)OVS_EXCLUDED(seq_mutex) {ovs_mutex_lock(&seq_mutex);seq_change_protected(seq);ovs_mutex_unlock(&seq_mutex);
}

Tips:通过上面的讨论,可以发现交换机和控制器的通信过程其实是在 ofproto 层实现的。

总结:

        最后列举一些交换机不需要走控制器的场景:

  • DHCP、DNS 等
  • upcall 调用类型为 sflow 时走 sflow 相应的流程
  • upcall 调用类型为 ipfix 时走 ipfix 相应的流程

总之就是说 vswitchd 事件上报不是数据包转发流程(或者慢速路径)中的必要过程

        由于本人水平有限,以上内容如有不足之处欢迎大家指正(评论区/私信均可)。

参考资料:

Open vSwitch 官网

Open vSwitch 源代码 GitHub

2015 FOSDEM - OVS Stateful Services

Open vSwitch 守护进程的 upcall 处理-CSDN博客

Open vSwitch 中 upcall 消息的类型-CSDN博客

Open vSwitch v2.17.10 LTS 源代码

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

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

相关文章

大众点评_token,mtgsig

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未经许可禁止转载&#xff0…

⌈ 传知代码 ⌋【算法】实体关系抽取

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

【漏洞复现】六零导航页 _include_file.php 任意文件上传漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

鸿蒙 游戏来了 鸿蒙版 五子棋来了 我不允许你不会

团队介绍 作者:徐庆 团队:坚果派 公众号:“大前端之旅” 润开鸿生态技术专家,华为HDE,CSDN博客专家,CSDN超级个体,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发。欢迎合…

.NET MAUI Sqlite数据库操作(一)

一、安装 NuGet 包 安装 sqlite-net-pcl 安装 SQLitePCLRawEx.bundle_green 二、配置数据库&#xff08;数据库文件名和路径&#xff09; namespace TodoSQLite; public static class Constants {public const string DatabaseFilename "TodoSQLite.db3";//数据库…

this指针如何使C++成员指针可调用

在C中&#xff0c;this指针是一个隐藏的指针&#xff0c;指向当前对象实例。它在成员函数中自动可用&#xff0c;用于访问该对象的成员变量和成员函数。理解this指针的工作原理有助于理解为什么指向成员的指针是可调用的。在本文中&#xff0c;我们将详细探讨this指针的概念&am…

云计算在保险行业的应用:太平财险团财险理赔新核心业务系统案例

随着科技的快速发展&#xff0c;云计算技术已经成为推动保险行业数字化转型的重要力量。云计算为保险公司提供了弹性、可扩展的计算资源&#xff0c;使其能够灵活应对业务高峰和低谷&#xff0c;提高业务运营效率和风控水平。太平财险与太平金科联合开发的“团财险理赔新核心业…

PCA与LDA

共同点 降维方法&#xff1a; PCA和LDA都是数据降维的方式&#xff0c;它们都能通过某种变换将原始高维数据投影到低维空间。 数学原理&#xff1a; 两者在降维过程中都使用了矩阵特征分解的思想&#xff0c;通过对数据的协方差矩阵或类间、类内散度矩阵进行特征分解&#xff…

JAVA开发 选择指定的文件生成ZIP压缩包

JAVA开发 选择指定的文件生成ZIP压缩包 1、ZipOutputStream1.1 主要方法1.2 使用步骤 2、案例实现2.1 代码块2.2 运行界面 1、ZipOutputStream ZipOutputStream 是 Java 中的一个类&#xff0c;它属于 java.util.zip 包&#xff0c;用于将多个文件或数据流写入到一个 ZIP 输出…

【mysql为什么采用b+树作为索引】

## 1、Hash: 它查询任何一行数据都只需一次IO,但是只能查一行&#xff0c;不能查询范围 。 ## 2、二叉树&#xff1a; 1、 可能会单边增长&#xff0c;退化成链表&#xff0c;查询效率和没建立索引差不多。2、才二叉而已&#xff0c;树的层数太多&#xff0c;IO次数多&#x…

贪心算法学习五

例题一 解法&#xff08;贪⼼&#xff09;&#xff1a; 贪⼼策略&#xff1a; 我们的任何选择&#xff0c;应该让这个数尽可能快的变成 1 。 对于偶数&#xff1a;只能执⾏除 2 操作&#xff0c;没有什么分析的&#xff1b; 对于奇数&#xff1a; i. 当 n 1 的时候…

Docker 安装 MySQL5.7 和 MySQL8

文章目录 安装 MySQL5.7拉取镜像前期准备启动容器 安装MySQL8.0拉取镜像查看镜像前期准备启动容器 安装 MySQL5.7 拉取镜像 docker pull mysql:5.7拉下来镜像后 执行 docker images 此时我们已经有这个镜像了。 前期准备 在根目录下创建 app &#xff0c; 在 app 目录下创建…

小工具开发

因不太喜欢重复性工作&#xff0c;为了提高日常工作效率&#xff0c;在业余时间开发一些小工具用于帮助自己“偷懒”。 小工具功能&#xff1a; 1、Hightec编译的hex文件&#xff0c;与多模式标定hex文件合成 2、Bootloader文件&#xff0c;Hightec编译的hex文件&#xff0c;与…

Oracle 系列数据库使用 listagg去重,删除重复数据的几种方法

listagg聚合之后很多重复数据&#xff0c;下面是解决重复数据问题 案例表 create table "dept_tag_info" ( "tag_id" bigint not null, "tag_code" varchar(200), "tag_name" varchar(500), "tag_level" varchar(200), &…

Android Studio新增功能:Device Streaming

今天将Android Studio升级到2023.3.1 Patch2。发现新增了Device Streaming功能。支持远程使用Google的物理设备调试程序。这样可以方便地在真实设备上测试自己的APP。这对于手头没有Google设备的开发者而言&#xff0c;确实方便很多。该功能目前处于测试阶段&#xff0c;在2025…

交易中的群体行为特征和决策模型

本文基于人的行为和心理特征&#xff0c;归纳出交易中群体的行为决策模型&#xff0c;并基于这个模型&#xff0c;分析股价波浪运行背后的逻辑&#xff0c;以及投机情绪的周期变化规律&#xff0c;以此指导交易&#xff0c;分析潜在的风险和机会&#xff0c;寻找并等待高性价比…

system与excel族函数区别

1.system #include<stdlib.h> int system(const char *command); comand是命令的路径&#xff0c;一般我们用绝对路径 system函数会创建新的进程&#xff0c;新的进程执行完返回原来的进程&#xff0c;原来的进程则继续执行后面的代码段。 如我们创建一个sys.cpp文件…

使用pip2pi和nginx搭建私有pip镜像源方法

在内网环境下部署python开发环境&#xff0c;安装python第三方库比较麻烦&#xff0c;特别是安装需要多个依赖的库。一种比较好的解决方案是搭建一个本地的私有pip镜像源&#xff0c;有多个方案可以选择&#xff0c;比如pypiserver、pip2pi等&#xff0c;本文介绍使用python的p…

Python求子数组和的所有元素(附Demo)

目录 前言1. 暴力求解2. 前缀和哈希表3. 滑动窗口 前言 工作需要&#xff0c;对应需要优化查找子数组和等于特定值的算法 对应的算法推荐&#xff1a;子数组相关题目 以下算法主要针对Python 1. 暴力求解 双重循环时间复杂度为 O(n2) def subarrays_with_sum_equal_k(num…

HTML的常用标签

HTML&#xff08;补&#xff09; CSS选择器 元素选择器&#xff1a;指定一个标签给这个标签设置一个默认的样式。设置的样式对所有相同的标签都有用。 id选择器&#xff1a;我们可以给标签指定一个唯一的id&#xff0c;然后根据id可以在style标签中设置对应标签的样式元素。设…