OpenVSwitch数据面流表cache机制浅谈

2023-11-11

稍许笔墨写了一篇关于OpenVSwitch(以下简称OVS)的文章:
https://blog.csdn.net/dog250/article/details/103492099
但有些事情并没有说清楚。

关于OVS的流表是如何映射成数据平面的Flow cache的,有必要单独写一篇文章来说一下。

下面的Paper描述了整个过程的来龙去脉,不可不读:
http://www.openvswitch.org//support/papers/nsdi2015.pdf

假设你已经读过了此Paper,至少已经大致扫过了一眼,下面谈谈我的看法。


OVS的流表可以抽象成下面的结构:
在这里插入图片描述
当然,为了解决match间的笛卡尔积问题,可以将上述的结构进行分解,最终形成一个多table级联的pipeline流表机构。

OVS的流表无论从结构上讲还是从匹配方式上看,都非常类似于iptables:

  • 单条iptables rule按照“match与”的方式匹配。一个 O ( n ) O(n) O(n)时间复杂度的过程。
  • 多条iptables rule按照“顺序或”的方式匹配。一个 O ( n ) O(n) O(n)时间复杂度的过程。
  • 匹配结果可以jump到其它chain以解决match之间笛卡尔积问题。

我们类比来看,OVS流表项就是iptables规则:

  • OVS的table就是iptables的chain。
  • OVS的match就是iptables的match。
  • OVS的Action就是iptables的target。

简直就是一回事。

那么,iptables的问题就是OVS流表的问题咯,是吗?是的, 但是OVS已经解决了 O ( n ) O(n) O(n)时间复杂度的匹配部分:

  • 数据包被上传到ovs-vswitchd进程匹配OVS流表时并非顺序匹配的,而是采用了hashmap的方式。

理想的完美哈希的 O ( 1 ) O(1) O(1)过程如下:
在这里插入图片描述
但现实中,往往采用冲突链表来解决哈希冲突的问题:
在这里插入图片描述

那么,OVS流表既然采用了这种方式,还有什么问题呢?我之前不是很推崇用这种方式预处理iptables规则吗?我之前不是很推崇nf-HiPAC,ipset这种方案吗?

OVS的新问题到底在哪里?

先说结论, OVS的目标在于在保持高效的查找过程的前提下,尽可能少的将数据包交给慢速路径处理。

这意味着既需要减少算法的时间复杂度,又要尽可能最大化快速路径的匹配率。


NSDI2015里说了,OVS的流表匹配不仅仅是一个规则匹配问题,而是一个Flow cache生成的问题,这里就涉及到了流表和Flow cache的区别:

  • 流表是复杂的,强调灵活和可编程。
  • Flow cache是简单的,强调快速转发。

可以说,Flow cache是根据流表查找结果生成的cache,它是要被注入到内核或者硬件的数据平面转发路径的cache项。

那么,这里就涉及到了cache的形式,它有两种选择:

  1. 精确的Flow cache。(OVS称为Microflow cache)
  2. 模糊的Flow cache。(OVS称为Megaflow cache)

我们分别看一下。

假设流表中有下面的一条规则:

src IP=200.100.0.0/16 Action=DROP

此时到达一个数据包:

src IP=200.100.10.1 dst IP=100.100.100.100 proto=TCP sport=123 dport=80

其源地址是 200.100.10.1 ,快速路径中未命中任何Flow cache,此时它被交给慢速路径ovs-vswitchd处理查询流表,恰好匹配上述规则,根据精确Flow cache的生成规则,它将生成一条下面的Flow cache并注入内核:

src IP=200.100.10.1 Action=DROP

如果是模糊Flow cache,将会是下面的:

src IP=200.100.0.0/16 Action=DROP

我们来比较一下它们。

如果来自 200.100.0.0/16 网段的不同主机的数据包持续到达,由于源地址不同,精确Flow cache将会持续向慢速路径转交数据包,如果是短连接,那么情况会更加严重,看起来这是多么不明智,严重影响转发效率。

如果采用模糊Flow cache,那么即便在快速路径,也要为数据包执行一次最长前缀匹配算法,如果是Trie数据结构,那么时间复杂度将会是 O ( n l o g n ) O(nlog n) O(nlogn),比精确Flow cache的 O ( 1 ) O(1) O(1)(理想情况的完美哈希假设下)要差一些。看样子模糊Flow cache的查询性能不如精确Flow cache。

很显然,长连接适用于精确Flow cache,而短连接则适用于模糊Flow cache。

OVS的做法是级联精确Flow cache和模糊Flow cache,也就是说,两类Flow cache全部内置,以多一次哈希查找的代价来平衡长连接和短连接最坏情况的性能损失,可谓精妙!

这里的关键在于, 查询性能相比向慢速路径上报数据包是无关紧要的。

现在的问题是, 模糊Flow cache要模糊到什么程度!


如果我们把一个match作为一个维度,那么一条具有N个match的Rule便拥有N个维度,所有的Rule作为一个集合,每条Rule必须全部去映射所有这N个维度各个match的数值,即便某一条Rule没有显示匹配某个match。

比方说,下面两条Rule:

src IP=1.2.3.4 Action=DROP
src IP=5.6.7.8 DPORT=8080 ACTION=NAT

显然,第一条Rule并没有DPORT这个match,然而它作为一个集合整体中的一员,还是隐含了这个match,只是没有显式表达而已,它隐含的DPORT match就是除了8080之外的所有值,于是上面的两条Rule等效于如下的Rule集合:

src IP=1.2.3.4 DPORT=1 Action=DROP
src IP=1.2.3.4 DPORT=2 Action=DROP
src IP=1.2.3.4 DPORT=3 Action=DROP
...
src IP=1.2.3.4 DPORT=8079 Action=DROP
src IP=5.6.7.8 DPORT=8080 ACTION=NAT
src IP=1.2.3.4 DPORT=8081 Action=DROP
src IP=1.2.3.4 DPORT=8082 Action=DROP
...
src IP=1.2.3.4 DPORT=65535 Action=DROP

盗用自己文章的两张图来说明这个多维匹配的原理:
在这里插入图片描述
在这里插入图片描述
这两个图来自下面的文章:
https://blog.csdn.net/dog250/article/details/77618319

也就是说,整个Rule集必须按照match最多的那条规则确定集合的维度个数,然后所有的Rule都需要基于这些维度进行match数值映射。考虑下面的两条Rule:

src IP=200.100.0.0/16 Action=DROP
src IP=5.6.7.8 DPORT=8080 ACTION=NAT

对于来自200.100.2.1,访问1234端口的数据包,按照上述的最大match维度匹配原则,即便是模糊Flow cache,也会生成下面的cache:

src IP=200.100.0.0/16 DPORT=1234 Action=DROP

此时如果是同样来自200.100.0.0/16网段的数据包访问不同于1234的其它端口,依然会发生cache miss,进而将数据包转交给慢速路径ovs-vswitchd处理。

模糊Flow cache的作用失效了!

解决方案之一就是,采用二次通配机制, 对于命中本来就没有某个match的Rule生成Flow cache时,其没有的那个match采用通配符替代具体值。 比如,数据包命中了Rule:

src IP=200.100.0.0/16 Action=DROP

这条Rule并没有DPORT这个match,所以生成cache时,会生成下面的cache:

src IP=200.100.0.0/16 DPORT=wildcast[1~8079/8081~65535] Action=DROP

代价只是在快速路径匹配模糊Flow cache时,多一次通配符运算。

然而,OVS没有采用这种方案(我自己的iptables规则预处理采用的就是这种方案),而是发明了另一种令人哇塞的方案,即 Staged Lookup

Staged lookup生成的Flow cache恰到好处,最后连通配符都不需要。它的精髓在于:

  1. 将所有match的一次hash计算过程分为逐渐加入新的match的N次hash计算过程。
  2. 只要在第N次hash匹配时发生了不匹配,那么第N-1次(初始化为默认策略)的hash匹配结果就是最终结果。

比方说下面的Rule集合:

M1=m11 M2=m12 M3=m13 M4=m14 M5=m15 Action=A1
M1=m21 M2=m22 M3=m23 M4=m24 Action=A2
M1=m31 M3=m33 M4=m34 M5=m35 Action=A3
M1=m41 M2=m42 Action=A4

一个携带对应5个match的filed分别为f1,f2,f3,f4,f5的数据包在进行匹配查找的时候,不再进行如下hash计算:

H = hash(pkt.f1, pkt.f2, pkt.f3, pkt.f4, pkt.f5);
result = lookup(H, pkt);
return result;

而改成下面的过程:

H1 = hash(pkt.f1, pkt.f2);
result1 = lookup(H1, pkt);
if (!result1)
	return default;
	
H2 = hash(pkt.f1, pkt.f2, pkt.f3, pkt.f4);
result2 = lookup(H2, pkt);
if (!result2)
	return result1;
	
H3 = hash(pkt.f1, pkt.f2, pkt.f3, pkt.f4, pkt.f5);
result3 = lookup(H3, pkt);
if (!result3)
	return result2;

return result3;

这个新的过程将原来的5个match拆分成了3组:

match_group1 = {M1, M2}
match_group2 = {M1, M2, M3, M4}
match_group3 = {M1, M2, M3, M4, M5}

可以保证的是,match_groupN 如果匹配失败,那么 match_groupN 以上新加入的match一定会匹配失败,而 match_groupN-1 一定是一个答案,这意味着生成的Flow cache里可以不包括 result_N 以及以后加入的那些match:
在这里插入图片描述
Staged Lookup的本质其实是 “巧妙利用了hash计算的过程”, 考虑到hash计算是可增量进行的,这相当于在hash计算的过程中挂了HOOK。

为了理解这个过程,我们先来看一个标准的可增量hash的过程:
在这里插入图片描述

Staged Lookup的过程就是针对上述的标准流程进行了拆解:
在这里插入图片描述
非常之精妙!

上述对Staged Lookup的解释有个假设,即hash是可以 增量计算 的,如果是增量计算的hash,Staged Lookup并不会因为hash查找从一次增加到多次而变慢,相反,还会提高效率,因为:

  1. hash计算的时间并没有变长,和拆解Stage之前是一样的。
  2. hashmap查找次数确实变多了,但被因不匹配而提前退出的hash计算所抵消。

当然,如果每个hash计算的步骤都引入一个种子,那么整个计算过程将不再是增量的,这样确实会增加计算量,然而在OVS中,Stage被典型拆解为4个步骤,hash计算量是微不足道的。

Staged Lookup的原理就说到这里,现在,让我们看最后一个问题,即如何拆解Stage。这个还是看原文更加直观:
在这里插入图片描述
应该先匹配那些多样性小(即容易匹配成功的)的match,然后再匹配那些多样性大的match,这样可以 尽可能保证不匹配现象最容易在早期的Stage中被发现。 背后的假设是, 根据TCP/IP分层原则,被封装在越里面的数据,其多样性越广泛。【引用1】

引用1: 不可以独立看待这个结论,因为TCP/IP模型是沙漏型的,而不是倒金字塔,也就是说,独立地看,IP层是多样性最广的,它是腰部。而TCP/UDP层和链路层相对而言多样性并不广泛,TCP/UDP层仅仅有65535个端口,链路层仅仅能看到与当前设备直连的设备。

所以说,要结合业务模型来看待这个结论,我们说TCP的多样性广泛,是结合IP层一起说的,也就是说,我们说的是一个socket。


我对OVS的这个Staged Lookup机制是拍案叫绝的,因为它的思路和我之前优化iptables时颠倒Rule,match,Prio维度的思路是一致的。我没有想到的是,竟然还可以对增量计算的过程进行HOOK。

当然了,我说的这些,对于经理而言,应该都是没有意义的。

先就这么多吧。


浙江温州皮鞋湿,下雨进水不会胖。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenVSwitch数据面流表cache机制浅谈 的相关文章

  • Proxmox VE 超融合集群OVS(Open vSwitch)虚拟机网络隔离

    作者 xff1a 田逸 需求的产生 在一个高配置的Proxmox VE 超融合集群中 xff0c 为充分利用资源 xff0c 需要按某种需求将虚拟机之间进行网络隔离 xff0c 以支持更大规模的场景 网络虚拟化基本条件 支持VLAN的网络交
  • openstack ovs-vswitch收包流程

    数据包从物理网卡进入虚拟机的流程 物理网卡处理 NIC 收到数据包 xff0c 会先将高低电信号转换到网卡 FIFO 存储器 NIC 首先申请 Ring buffer 的描述 xff0c 根据描述找到具体的物理地址 xff0c NIC 会使
  • Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(8)

    问题导读 xff1a 1 怎样使用arp responder xff1f 2 怎样搭建l2pop环境 xff1f 3 ARP Responder arp responder 的原理不复杂 Neutorn DB 中保存了所有的端口的 MAC
  • 开源SDN控制器和商用SDN控制器一览

    以下是来自IT168收集的2014年可追寻到的开源SDN控制器和商用SDN控制器 xff0c 此处转载以供大家知悉 xff0c 更多控制器信息需要大家自己动手去查询和理解 开源SDN控制器组织 随机排序 xff0c 仅为了查看便利 1 组织
  • openflow交换机流表删除_sdn交换机与普通交换机区别—Vecloud

    SDN xff0c 即Software Defined Network 软件定义网络 xff0c 传统的网络设备 交换机 路由器 的固由设备制造商锁定和控制 xff0c 所以SDN希望将网络控制与物理网络拓扑分离 xff0c 从而摆脱硬件对
  • 基于SDN的访问控制模块实现

    一 背景 1 访问控制 访问控制技术 xff0c 指防止对任何资源进行未授权的访问 xff0c 从而使计算机系统在合法的范围内使用 意指用户身份及其所归属的某项定义组来限制用户对某些信息项的访问 xff0c 或限制对某些控制功能的使用的一种
  • SDN控制平台开源代码

    开源代码是指源代码在开放的许可下公开发布 xff0c 任何人都可以从源代码免费获得 复制 修改和分发 在SDN控制平台领域 xff0c 有许多开源代码可供选择 xff0c 如 xff1a OpenDaylight ONOS Ryu等 这些项
  • SDN的HUB实验

    SDN的hub实验 首先需要搭建ryu控制器环境和mininet环境 使用winscp将hub的py代码上传到服务器啊贝云 使用命令搭建拓扑环境 mn topo 61 single xff0c 3 controller 61 remote
  • OVS 使用总结

    1 简介 Open vSwitch 是一个用C语言开发的多层虚拟交换机 1 1 工作原理 内核模块实现了多个 数据路径 xff08 类似网桥 xff09 每个都可以有多个 vports xff08 类似网桥的端口 xff09 每个数据路径也
  • 关于ovs中ovs-ofctl add-flow的“in_port”问题

    问题提出 在之前做的docker容器互联的实验中有这样一句命令 xff1a ovs ofctl add flow s1 span class token string 34 in port 61 1 actions 61 drop 34 s
  • SDN 中 DDoS 攻击问题(论文方法总结)

    SDN 中 DDoS 攻击类型 1 数据平面DDoS攻击 数据平面由多个启用OpenFlow的转发设备组成 这些设备被称为OpenFlow交换机 每个交换机都有一个有限的流表大小来存储规则和有限的处理能力来处理不匹配的数据包 xff0c 因
  • OpenvSwitch 的 Open Virtual Network(OVN)项目

    几天前 xff08 1 月 13 日 xff09 xff0c OpenvSwitch 团队正式宣布了 OVN xff08 Open Virtual Network xff09 项目 xff0c 参考 Open Virtual Network
  • OpenStack 之 OVS介绍

    一 概述 Open vSwitch的官方定义 xff1a Open vSwitch是一个具有工业级质量的多层虚拟交换机 通过可编程扩展 xff0c 可以实现大规模网络的自动化 xff08 配置 管理 维护 xff09 它支持现有标准管理接口
  • Centos搭建配置SDN

    文章目录 赛题 1 关闭Selinux和防火墙 2 安装相关服务并上传解压安装包 安装服务 安装ODL 启动OVS 启动karaf程序 3 安装组件 测试 4 创建拓扑 5 下发流表 6 启动HTTP Server功能 7 更多内容 赛题
  • Ubuntu下如何关闭指定端口的进程

    1 查看该端口的占用情况 lsof i 端口号 2 关闭进程 kill PID 可能不止一个进程
  • ovs+dpdk 三级流表(microflow/megaflow/openflow)

    本文介绍在ovs dpdk下 三级流表的原理及其源码实现 普通模式ovs的第一和二级流表原理和ovs dpdk下的大同小异 三级流表完全一样 基本概念 microflow 最开始openflow流表是在kernel中实现的 但是因为在ker
  • 基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API

    为了更好的分享体验 博客搬迁至极客驿站 欢迎查阅 基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API 介绍 准备工作 开发步骤 问题排查 介绍 目前protocol 中ovsdb协议层面已经实现 但是基于ovsdb prot
  • 使用 OpenDaylight 入门原型不起作用

    尝试跟随开放日光开发者教程获得在控制器上运行的初始 hello world 应用程序 但是运行命令 mvn archetype generate DarchetypeGroupId org opendaylight controller D
  • OpenDaylight 控制器应用程序 (Sodium SR1) 缺少依赖项

    我按照此处的说明编写一个简单的 hello world RPC https docs opendaylight org en stable sodium developer guide developing apps on the open
  • 如何向 OpenDayLight Karaf 添加新功能?

    如何将新功能添加到 ODL Oxygen SR3 0 8 3 作为 Karaf 模块 例如 我从以下位置下载了预构建的 ODL 官方网站 https nexus opendaylight org content repositories p

随机推荐

  • python学习7.1文件

    一 open 函数 1 第一个参数 文件名 2 打开方式 1 r 以只读模式打开文件 readlines 以列表形式输出 输入 file open a txt r print file readlines file close 输出 汪湾
  • vue使用threeJs导入obj模型,并添加标注

    效果图 1 安装threeJs npm install three 2 安装轨道控件插件 npm install three orbit controls 3 安装加载 obj和 mtl文件的插件 npm i save three obj
  • Java流程控制(分支结构,迭代结构,转移语句)

    1 分支结构 if else switch 2 迭代结构 while do while for 3 转移语句 break countinue return 4 while 循环 5 do while循环 6 while do while的区
  • ubuntu12.04下Qt5.6设置命令行启动方式

    本菜鸟由于不精通ubuntu 但是需要做项目使用qt 而将qt安装好后想再次打开时候却找不到qt的图标 经过半天的摸索 终于搞清楚怎么打开qt了 特此作出分享 1 方式一 找到安装目录 寻找qtcreator的文件 相当于在windows下
  • SAP ABAP 中的异步调用

    举例场景 创建采购申请的接口中 在执行完BAPI之后返回了一个PR 接着就会执行到commit提交的接口 然如果还需要在创建的时候直接审批 那么就需要再调用PR审批的BAPI 但是你会发现有的PR 在ME23N查看的时候是审批状态 而有的并
  • Android studio连接真机以及找不到设备问题解决

    一 电脑设置 1 检查必要工具是否下载 Android studio gt 右上角的立方体标志 SDK Manager gt 点击 SDK Tools 检查是否下载 Goolge USB Driver 2 驱动安装 点击下一步 gt 完成
  • OpenBlas 安装

    OpenBLAS是BLAS Basic Linear Algebra Subprograms 的优化版 OpenBLAS官网 http www openblas net OpenBLAS公开课 https www leiphone com
  • hadoop学习——flume的简单介绍

    flume介绍 概述 Flume最早是Cloudera提供的日志收集系统 后贡献给Apache 所以目前是Apache下的项目 Flume支持在日志系统中定制各类数据发送方 用于收集数据 Flume是一个高可用的 高可靠的 鲁棒性 robu
  • 记一次malloc失败的经历

    背景 在类OsBufferEntry的成员函数中 为其成员变量m SimplePingResult分配空间 结果报错了 百思不得其解 class OsBufferEntry public QObject Q OBJECT public ex
  • 用git搭建个人博客

    1 安装 Node js 2 安装 Git 3 全局安装Hexo 在命令框中输入 npm install g hexo cli 4 hexo init
  • 分布式事务在Java中的实现与优化

    分布式事务在Java中的实现与优化 分布式系统中的事务处理是一个复杂而关键的问题 随着互联网规模的不断扩大和应用场景的增多 分布式事务的需求也越来越迫切 本文将探讨在Java中实现和优化分布式事务的方法 并提供相应的源代码示例 一 分布式事
  • Error attempting to get column ‘name‘ from result set. Cannot determine value type from string

    Error attempting to get column name from result set Cause java sql SQLDataException Cannot determine value type from str
  • select()函数的作用

    select 在SOCKET编程中还是比较重要的 可是对于初学SOCKET的人来说都不太爱用select 写程序 他们只是习惯写诸如 conncet accept recv 或recvfrom 这样的阻塞程序 所谓阻塞方式block 顾名思
  • 解决windows无法启动sybase服务

    我这里是由于IP原因导致sybase服务启动不了 将sybase 服务的IP修改为本机正确的IP地址后 重启服务成功 1 启动服务报如下错误 2 启动sybase的 Dsedit Utility 3 步骤2执行后打开如下界面 可以看到4个服
  • Windows命名管道&getsystem原理学习记录

    前言 出品 博客 ID moon flower 以下内容 来自博客的moon flower作者原创 由于传播 利用此文所提供的信息而造成的任何直接或间接的后果和损失 均由使用者本人负责 长白山攻防实验室以及文章作者不承担任何责任 命名管道基
  • 学习笔记:WSL Ubuntu 20.04 LTS 安装中文语言

    环境 系统 Windows 10 Pro 64 WSL子系统 Ubuntu 20 04 LTS 1 安装中文语言包 sudo apt install language pack zh hans 2 设置中文为默认语言 方法一 sudo dp
  • 简单教你美化iPhone电量指示图标

    一样的画面用久了终究会腻的 所以我今天教大家怎样美化自己的iPhone 先从充电图标开始 实际上很简单 iPhone的电量指示就是由17张图片组成的 也就是说我们只要替换这些图片就能改变电量指示图标了 你可以自己做一些图片来替换也可以下载我
  • mysql存储过程批量生成脚本

    删除之前的存储过程 DROP PROCEDURE idata 创建 delimiter create procedure idata begin declare i int set i 1 START TRANSACTION while i
  • logback使用

    1 需要引入maven配置 ch qos logback logback classic 1 0 0 这个会依赖slf4j api和logback core ch qos logback logback access 1 1 5 所有的ja
  • OpenVSwitch数据面流表cache机制浅谈

    稍许笔墨写了一篇关于OpenVSwitch 以下简称OVS 的文章 https blog csdn net dog250 article details 103492099 但有些事情并没有说清楚 关于OVS的流表是如何映射成数据平面的Fl