Open vSwitch 中 upcall 消息的类型

一、upcall 调用的流程

        在 Open vSwitch 的数据包转发流程中,如果数据包在内核空间无法完全处理(比如匹配不到流表项),就会发生 upcall 调用,将数据包从内核空间的 Datapath 模块传输至用户空间的 ovs-vswitchd 守护进程进行处理。由于 upcall 调用经过了内核态到用户态的转发和 Open vSwitch 在用户空间的分层设计,所以 upcall 消息需要经过层层封装、解析和处理才能最终到达 vswitchd 守护进程。这里将详细讨论在 upcall 调用过程的不同阶段中,消息类型的变化。

二、内核空间中的 upcall 消息类型

        内核空间对应的 upcall 结构体主要用于 Netlink 消息的封装,定义在 ovs-main/datapath/linux/compat/include/linux/openvswitch.h 头文件中:

enum ovs_packet_cmd {OVS_PACKET_CMD_UNSPEC,/* Kernel-to-user notifications. */OVS_PACKET_CMD_MISS,    /* Flow table miss. */OVS_PACKET_CMD_ACTION,  /* OVS_ACTION_ATTR_USERSPACE action. *//* Userspace commands. */OVS_PACKET_CMD_EXECUTE  /* Apply actions to a packet. */
};

        这时的 ovs_packet_cmd 对于 upcall 调用而言,只有 OVS_PACKET_CMD_MISS 和 OVS_PACKET_CMD_ACTION 这两种主要类型,分别对应内核模块 Datapath 匹配不到流表项和需要执行一些特定动作的情况。

        也就是说,当内核模块 Datapath 匹配不到流表项时,会产生 MISS 类型的 upcall 消息,相应代码存储在 ovs-main/datapath/datapath.c 文件中:

void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) {......if (unlikely(!flow)) {......upcall.cmd = OVS_PACKET_CMD_MISS;......error = ovs_dp_upcall(dp, skb, key, &upcall, 0);......}......
}

        而相应的,ACTION 类型的处理函数存储在 ovs-main/datapath/actions.c 文件中:

static int output_userspace(struct datapath *dp, struct sk_buff *skb, struct sw_flow_key *key, const struct nlattr *attr, const struct nlattr *actions, int actions_len, uint32_t cutlen) {......upcall.cmd = OVS_PACKET_CMD_ACTION;......err = ovs_dp_upcall(dp, skb, key, &upcall, cutlen);......
}

二、用户空间中的 upcall 消息类型

        由于 Open vSwitch 在用户空间的分层设计,用户空间需要对 upcall 消息结构进行重新整合。

(1)dpif 中的 upcall 消息类型

        这里 dpif 对应的 upcall 结构体主要用于接收来自内核的消息,定义在 ovs-main/lib/dpif.h 头文件中:

enum dpif_upcall_type {DPIF_UC_MISS,               /* Miss in flow table. */DPIF_UC_ACTION,             /* OVS_ACTION_ATTR_USERSPACE action. */DPIF_N_UC_TYPES
};

        可以看到这里的 DPIF_UC_MISS 和 DPIF_UC_ACTION 和内核空间中 upcall 消息类型是一一对应的关系。由此可见,此时是接收后直接存储,不需要进行额外关于类型的处理。

(2)ofproto 中的 upcall 消息类型

        这里 ofproto 对应的 upcall 结构体主要为了便于 upcall 消息处理函数 process_upcall() 对不同类型 upcall 消息的处理,存储在 ovs-main/ofproto/ofproto-dpif-upcall.c 文件中:

enum upcall_type {BAD_UPCALL,                 /* Some kind of bug somewhere. */MISS_UPCALL,                /* A flow miss.  */SLOW_PATH_UPCALL,           /* Slow path upcall.  */SFLOW_UPCALL,               /* sFlow sample. */FLOW_SAMPLE_UPCALL,         /* Per-flow sampling. */IPFIX_UPCALL,               /* Per-bridge sampling. */CONTROLLER_UPCALL           /* Destined for the controller. */
};

此时相应的 process_upcall() 处理流程如下图所示:

(3)用户空间的 upcall 消息类型转换

        用户空间的 upcall 消息类型转换主要发生在 dpif 和 ofproto 之间,将 dpif 中简单粗略的 upcall 消息类型进行细化,存储在 ovs-main/ofproto/ofproto-dpif-upcall.c 文件中:

static enum upcall_type classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata, struct user_action_cookie *cookie) {/* First look at the upcall type. */switch (type) {case DPIF_UC_ACTION:break;case DPIF_UC_MISS:return MISS_UPCALL;case DPIF_N_UC_TYPES:default:VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32, type);return BAD_UPCALL;}/* "action" upcalls need a closer look. */if (!userdata) {VLOG_WARN_RL(&rl, "action upcall missing cookie");return BAD_UPCALL;}size_t userdata_len = nl_attr_get_size(userdata);if (userdata_len != sizeof *cookie) {VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %"PRIuSIZE,userdata_len);return BAD_UPCALL;}memcpy(cookie, nl_attr_get(userdata), sizeof *cookie);if (cookie->type == USER_ACTION_COOKIE_SFLOW) {return SFLOW_UPCALL;} else if (cookie->type == USER_ACTION_COOKIE_SLOW_PATH) {return SLOW_PATH_UPCALL;} else if (cookie->type == USER_ACTION_COOKIE_FLOW_SAMPLE) {return FLOW_SAMPLE_UPCALL;} else if (cookie->type == USER_ACTION_COOKIE_IPFIX) {return IPFIX_UPCALL;} else if (cookie->type == USER_ACTION_COOKIE_CONTROLLER) {return CONTROLLER_UPCALL;} else {VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16" and size %"PRIuSIZE, cookie->type, userdata_len);return BAD_UPCALL;}
}

        函数通过 case 检查 dpif_upcall_type 类型:如果是 DPIF_UC_MISS,则返回 MISS_UPCALL;如果是 DPIF_N_UC_TYPES 或其他未知类型,则返回 BAD_UPCALL;如果是 DPIF_UC_ACTION 则根据 userdata 和 user_action_cookie 进行更详细的和分类。

        这里的 user_action_cookie 定义在 ovs-main/lib/odp-util.h 头文件中:

/* user_action_cookie is passed as argument to OVS_ACTION_ATTR_USERSPACE. */
struct user_action_cookie {uint16_t type;              /* enum user_action_cookie_type. */ofp_port_t ofp_in_port;     /* OpenFlow in port, or OFPP_NONE. */struct uuid ofproto_uuid;   /* UUID of ofproto-dpif. */union {struct {/* USER_ACTION_COOKIE_SFLOW. */ovs_be16 vlan_tci;      /* Destination VLAN TCI. */uint32_t output;        /* SFL_FLOW_SAMPLE_TYPE 'output' value. */} sflow;struct {/* USER_ACTION_COOKIE_SLOW_PATH. */uint16_t unused;uint32_t reason;        /* enum slow_path_reason. */} slow_path;struct {/* USER_ACTION_COOKIE_FLOW_SAMPLE. */uint16_t probability;   /* Sampling probability. */uint32_t collector_set_id; /* ID of IPFIX collector set. */uint32_t obs_domain_id; /* Observation Domain ID. */uint32_t obs_point_id;  /* Observation Point ID. */odp_port_t output_odp_port; /* The output odp port. */enum nx_action_sample_direction direction;} flow_sample;struct {/* USER_ACTION_COOKIE_IPFIX. */odp_port_t output_odp_port; /* The output odp port. */} ipfix;struct {/* USER_ACTION_COOKIE_CONTROLLER. */uint8_t dont_send;      /* Don't send the packet to controller. */uint8_t continuation;   /* Send packet-in as a continuation. */uint16_t reason;uint32_t recirc_id;ovs_32aligned_be64 rule_cookie;uint16_t controller_id;uint16_t max_len;} controller;};
};
BUILD_ASSERT_DECL(sizeof(struct user_action_cookie) == 48);

总结:

        通过上面的分析可以得到以下结论:

(1)对于 upcall 调用中的消息类型而言,只有 MISS 和 ACTION 这两种主要类型。

(2)当内核空间的 Datapath 模块匹配不到流表项时,产生的一定是 MISS 类型的 upcall 消息,并且在后续的过程中如果没有出现错误,则一直将会是 MISS 类型的消息,只是名称不同。

(3)当内核空间的 Datapath 模块判断出数据包需要传输至 vswitchd 守护进程进行进一步处理时,会产生 ACTION 类型的 upcall 消息,并将配套信息通过 OVS_ACTION_ATTR_USERSPACE 也传输到用户空间。用户空间会根据这些信息将 ACTION 类型的 upcall 消息进行更细致的划分后,再进行处理。

        此外,还有一点需要注意:我们在数据包的处理流程中提到过快速路径慢速路径的概念,但是这和 upcall 调用过程在名称上并不是完全匹配。

        这里的慢速路径对应的 upcall 类型其实是 MISS 类型,而 upcall 消息在用户空间也存在 SLOW_PATH 的 upcall 类型。虽然在进行最终处理的时候二者被归为一类,并且处理的流程区别不大,但认真分辨下来还是有细微差别的,在特定场景下需要注意区分。

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

参考资料:

Open vSwitch 官网

Open vSwitch 源代码 GitHub

Open vSwitch 数据包处理流程-CSDN博客

Open vSwitch 的 upcall 调用(内核空间部分)-CSDN博客

Open vSwitch 的 upcall 调用(用户空间部分)-CSDN博客

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

Open vSwitch v2.17.10 LTS 源代码

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

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

相关文章

UML类图之间的关系与对应的代码关系

UML类图之间的关系与对应的代码关系 1. 依赖关系1.1 图解1.2代码实现 2. 关联关系2.1图解2.2代码实现 3. 聚合关系3.1图解3.2代码实现 4. 组合关系4.1图解4.2代码实现 5. 泛化关系5.1图解5.2代码实现 6. 实现关系6.1图解6.2代码实现 在UML中,共有四种关系&#xff1…

Docker与Docker-Compose详解

1、Docker是什么? 在计算机中,虚拟化(英语: Virtualization) 是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍&…

学习笔记——路由网络基础——缺省(默认)路由

3、缺省(默认)路由 1、定义 缺省路由(默认路由):是目的地址和掩码都为全0的特殊路由。全0代表任意网络。缺省路由在路由表中的形式为:0.0.0.0/0缺省路由也被叫默认路由。缺省路由优先级比直连路由低 缺省路由是一种特殊的路由,当报文没有在…

API工具--Apifox和Postman对比(区别)

🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 &#x1…

【SkiaSharp绘图03】SKPaint详解(一)BlendMode混合模式、ColorFilter颜色滤镜

文章目录 SKPaintSKPaint属性BlendMode获取或设置混合模式SKBlendMode 枚举成员效果预览 Color/ColorF获取或设置前景色ColorFilter 颜色滤镜CreateBlendMode 混合模式CreateColorMatrix 颜色转换CreateCompose 组合滤镜CreateHighContrast 高对比度滤镜CreateLighting 照明滤镜…

eNSP学习——配置高级的访问控制列表

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、搭建OSPF网络 3、配置Telnet 4、配置高级ACL控制访问 需要eNSP各种配置命令的点击链接自取:华为eNSP各种设备配置命令大全PDF版_ensp配置命令大全资源-…

AcWing 477:神经网络 ← 拓扑排序+链式前向星

【题目来源】https://www.acwing.com/problem/content/479/【题目描述】 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。 对神经网络的研究…

致 粉丝de信

致 粉丝 -本文呢看不下去别看,但是学业是真的重要(平常有信奥😫),电脑没收……更新可能得到暑假, 同学:小没苯agoe (aaa,学霸!!!&…

排序-快排算法对数组进行排序

目录 一、问题描述 二、解题思路 1.初始化 2.将右侧小于基准元素移到左边 3.将左侧大于基准元素移到右边 4.重复执行上面的操作 5.对分好的左、右分区再次执行分区操作 6.最终排序结果 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 快排算法实现数组排序&am…

【Spring EL<二>✈️✈️ 】SL 表达式结合 AOP 注解实现鉴权

目录 🍻前言 🍸一、鉴权(Authorization) 🍺二、功能实现 2.1 环境准备 2.2 代码实现 2.3 测试接口 🍹三、测试功能 3.1 传递 admin 请求 ​ 3.2 传递普通 user 请求 🍻四、章末 &a…

【智能算法应用】基于混合粒子群-蚁群算法的多机器人多点送餐路径规划问题

目录 1.算法原理2.数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】粒子群算法(PSO)原理及实现 配餐顺序: 采用混合粒子群算法 || 路径规划: 采用蚁群算法 2.数学模型 餐厅送餐多机器人多点配送路径规划&…

美创科技入选“2024网络安全提供商创新排行榜”

近日,DBC德本咨询公布了“2024网络安全提供商创新排行榜”,美创科技凭借近20年的数据安全创新耕耘,荣誉上榜。 此次,与360、华为、腾讯等互联网、网络安全头部厂商并肩上榜,是行业对美创的再次认可。 数据安全的发展离…

景芯SoC A72的时钟树分析

innovus的ctslog中的Clock DAG信息可以报出来CTS主要运行步骤的关键信息,比如clustering,balancing做完后的clock tree的长度,clock tree上所用的buffer、inverter,icg cell数量,clock skew等信息。我们以景芯SoC A72 …

搜维尔科技:Movella旗下的Xsens在人形机器人开发中得到广泛应用

人形机器人的发展正在全球范围内受到广泛关注。作为机器人领域的重要分支,人形机器人因其具备高度仿真的外观和动作,以及更贴近人类的行为模式,有望逐渐成为人们日常生活和工业生产中的得力助手。在中国,这一领域的发展尤为引人注…

解密Spring Boot:深入理解条件装配与条件注解

文章目录 一、条件装配概述1.1 条件装配的基本原理1.2 条件装配的作用 二、常用注解2.1 ConditionalOnClass2.2 ConditionalOnBean2.3 ConditionalOnProperty2.4 ConditionalOnExpression2.5 ConditionalOnMissingBean 三、条件装配的实现原理四、实际案例 一、条件装配概述 1…

C++进阶:继承

文章目录 继承的概念继承的定义方式继承关系和访问限定符基类和派生类对象的赋值转换继承中的作用域派生类中的默认成员函数构造函数拷贝构造函数赋值拷贝函数析构函数 总结 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允…

【全开源】Java无人共享棋牌室茶室台球室系统JAVA版本支持微信小程序+微信公众号

无人共享棋牌室系统——棋牌娱乐新体验 🎲引言 随着科技的不断发展,传统棋牌室正逐渐迈向智能化、无人化。今天,我要为大家介绍的就是这款引领潮流的“无人共享棋牌室系统”。它不仅为棋牌爱好者提供了全新的娱乐体验,更在便捷性…

【Python】数据处理:SQLite操作

使用 Python 与 SQLite 进行交互非常方便。SQLite 是一个轻量级的关系数据库,Python 标准库中包含一个名为 sqlite3 的模块,可以直接使用。 import sqlite3数据库连接和管理 连接到 SQLite 数据库。如果数据库文件不存在,则创建一个新数据库…

Conda安装

conda可以做到不同项目就用不同虚拟环境,这样就能做到每个项目的依赖包都是相互独立 一、windows Download Success | Anaconda 环境变量 二、nano 本次安装Archiconda的外部python版本为python3.7.1

Vue基础知识:异步DOM更新是什么?$nextTick是什么?到底应该如何使用。什么是同步?什么是异步?

要先了解异步dom更新是什么就必须先了解,什么是同步?什么是异步? 1.什么是同步?什么是异步? 同步(Synchronous): 同步操作是按照代码的顺序执行的,每个操作都必须等待上…