Open vSwitch中的datapath flow匹配过程
- 数据结构看不懂
- 匹配算法经过了多次演进,已经有点复杂了,看代码完全看不懂,我能怎么办,我也很绝望啊!


- 在创建一个vxlan型的vport时,会调用到vxlan_create来创建这个vport,这个函数做了两件事情

- 调用vxlan_tnl_create,alloc要创建的vport,并创建好vxlan设备
- 调用ovs_netdev_link,把上一步创建的vxlan设备与vport绑定起来,并且还注册了一个收包回调函数是为netdev_frame_hook,如下:

- netdev_frame_hook收到包后,把包转交给netdev_vport_receive,但由于不知道这个宏USE_UPSTREAM_TUNNEL功能是什么,所以到底转交的时候带不带第二个参数就搞不清楚了,如下

这里要注意的是,netdev_frame_hook及netdev_port_receive是标准的收包流程,所谓标准指的是,只要是发向OVS中port的包,无论port是什么类型,是VXLAN vport,还是netdev vport,还是gre vport,走的都是这个流程,这些vport类型的收包回调统一都是netdev_frame_hook - 无论什么vport类型,包都会走netdev_frame_hook->netdev_port_receive这个流程,然而在netdev_port_receive中就要分流了,如下:

在这个函数中,根据skb下挂的dev,找出该包所收包时所属于的vport,然后调用ovs_vport_receive - 接下来到了ovs_vport_receive函数中,这个函数主要就做了一件事情:把包中的标识信息(一二三四层外加conntrack信息)扒到一个sw_flow_key结构中,这个结构并不复杂,字段也比较容易理解,这个sw_flow_key结构就是后续datapath转发表匹配时很关键的一个东西。把这件事做完后,就把skb本身与扒出来的这个sw_flow_key一起送给ovs_dp_process_packet函数中进行进一步处理

- ovs_dp_process_packet如下

在这个函数中,将调用ovs_flow_tbl_lookup_stats()进行datapath转发表项的匹配工作
第一个参数是查询的转发表,这个表挂在datapath下,类型为flow_table,看上面的数据结构图
第二个参数是之前扒出来的sw_flow_key类型结构实例
第三个参数是调用Linux kernel函数对skb进行的一个哈希数值
第四个参数是一个出参,如果是megaflow匹配的话,这个出参将携带掩码匹配命中的字段数出来 - 至此,先停一下车,上面说的是包是怎么收进来的,接下来就要看包是怎么匹配的了,先停一下车
- 第一个层次,假设没有megaflow,即按位选择性匹配,datapath转发表项必须全12个字段精确匹配,你会怎么做?这种情况下,匹配就很简单,我们把包中的信息扒到sw_flow_key结构中,然后在OVS中设计一个哈希表,映射的就是[sw_flow_key <==> 如何转发],直接用这个哈希表按key查询,O(1)就能完成匹配。
做个不恰当的比喻,内核datapath中实现了一个类似于std::map的数据结构,当然这是一个哈希表,其中键是sw_flow_key类型的,值就是“要执行的动作”(也就是sw_flow类型)
当packet收上来时,直接把packet解压出来的key当成键,去查询它对应的“要执行的动作”。。查询成功,就走快转直接从内核转走。。查询失败,就是内核datapath转发表项匹配失败,给用户态上送upcall消息。用户态根据OpenFlow流表,走慢转,然后再把慢转的行为总结成datapath转发表里的“要执行的动作”,下发给内核,这样,下一次再来,就直接走快转了。
但是问题出现了,精确匹配的最大缺点就是datapath转发表项数量会爆炸膨胀,你想一下用户态OpenFlow流表中的安全组的实现,conjunctive,你再想一想这些安全组映射成datapath转发表项,表项数量得炸成什么样。
所以为了解决这个问题,就出现了megaflow式匹配,这个洋文名字的意思就是:选择性的匹配某些字段 - megaflow匹配就是第二个层次
- 入的包解压出来的sw_flow_key实例是所有字段都有的
- 匹配时只需要匹配部分的sw_flow_key中的字段,所以OVS设计了一个数据结构叫sw_flow_mask,sw_flow_mask中有两个很重要的字段:sw_flow_key_range与sw_flow_key,其中range就指定了匹配哪些字段。。
比如,比如,举个不严谨的例子,datapath中要支持两种匹配:
第一种:按MAC层src与dst及IP层src与dst的匹配
第二种:IP层src与dst的匹配
那么就需要做两个sw_flow_mask实例,假设macsrc/macdst/ipsrc/ipdst的编号分别是3、4、5、6,那么这两个sw_flow_mask的实例的示意大致如下:
sw_flow_mask first = {
range = [3,4]
key = {
...
macsrc=11:22:33:44:55:66
macdst=66:55:44:33:22:11
...
}
}
sw_flow_mask second = {
range = [3,6]
key = {
...
macsrc=22:22:22:33:33:33
macdst=33:33:33:22:22:22
ipsrc=1.2.3.4
ipdst=4.3.2.1
...
}
}
然后这两个实例放在哪里呢?在(datapath.table)->mask_array中,在旧版本的OVS实现中,这些sw_flow_mask的实例被组织成链表,在2.7版本中,直接组织成顺序表了
那么packet收上来是如何进行匹配的呢?
首先,要对(datapath.table)->mask_array中的所有sw_flow_mask进行遍历
然后,对于每个sw_flow_mask实例,这里称为mask,去比对mask.range范围内,mask.key中的值,
如果这些值与packet解压出来的key一致,那么就表示megaflow匹配成功
这个时候接下来怎么搞呢?和第一步一样,依然是要去查哈希表,查出一个sw_flow出来,但是哈希表是全字段匹配的呀。
比如包原先解压出来的sw_flow_key是为key,这个时候用key作键去查哈希表,结果并不是我们希望得到的megaflow匹配结果,而是全匹配结果(很有可能会miss)
所以不能用key去当键去查哈希表,而应该用匹配的sw_flow_mask实例里的"range + key"这两个信息结合起来,当成键,去查哈希表。
在这一版的匹配流程中,相较于上一版,解决了datapath转发表项数量爆炸的问题。
并且在实际实现中,对于sw_flow结构,还增加了一个用来表示mask的字段,是为sw_flow->mask,类型是为sw_flow_mask
- 上一版的匹配流程虽然改善了datapath转发表项的爆炸问题,但是又引入了一个新的问题(真他妈是聋子治成哑巴了):性能下降了!
第一版虽然很浪费内存空间,但是查找快啊!只查一次哈希表就世界太平了!顶多桶位上链表长度长一点撑死了!
第二版虽然节省了空间,但又浪费时间了啊!你看,先要遍历所有的mask_array中的sw_flow_mask实例,来看哪个实例与包的key能对上!
所以OVS这拨人又处心积虑的搞出了第三版匹配流程。
核心思想还是站在前人的工作上糊一层屎:既然遍历mask_array里的实例太浪费时间,那么就不要以“遍历”的形式去做这件事,来,老子的意大利散列函数呢??想办法干他娘的一炮!
在上一版的策略中,流程大概是:
第一层:遍历mask
第二层:根据masked_key查询flow
所以这一版的策略就改进了这一点,现在流程是这样的:
第一层:根据packet的key,查询masked_key
第二层:根据masked_key,查询flow
注意这两个层次的查询都是哈希表(字典)查询,所以总共实现了两个哈希表(字典):
第一个字典:键为packet的标识信息,值为mask的标识信息
第二个字典:键为masked_key,值为flow
大概逻辑就是这样,下面将讲第三版匹配流程的具体实现


- ufid_ti的用途?
- sw_flow结构中,每个table_instance都对应着两个链表字段,为什么?
- table_instance结构中的node_ver是什么用途?
body,td { font-family: Consolas; font-size: 10pt }
Open vSwitch中的datapath flow匹配过程的更多相关文章
- 绝对路径${pageContext.request.contextPath}用法及其与web.xml中Servlet的url-pattern匹配过程
以系统的一个“添加商品”的功能为例加以说明,系统页面为add.jsp,如图一所示: 图一 添加商品界面 系统的代码目录结构及add.jsp代码如图二所示: 图二 系统的代码目录结构及add.js ...
- (转)绝对路径${pageContext.request.contextPath}用法及其与web.xml中Servlet的url-pattern匹配过程
以系统的一个“添加商品”的功能为例加以说明,系统页面为add.jsp,如图一所示: 图一 添加商品界面 系统的代码目录结构及add.jsp代码如图二所示: 图二 系统的代码目录结构及add.js ...
- web.xml中的url-pattern写法规则及匹配过程
servlet和filter在javaEE开发中很常用,因此有必要知道web.xml文件映射的规则 1. 写法 ①完全匹配:以“/”开头,以字母(非“*”)结束 如:<url-patte ...
- 在Python中使用正则表达式同时匹配邮箱和电话并进行简单的分类
在Python使用正则表达式需要使用re(regular exprssion)模块,使用正则表达式的难点就在于如何写好p=re.compile(r' 正则表达式')的内容. 下面是在Python中使用 ...
- 【java规则引擎】模拟rete算法的网络节点以及匹配过程
转载请注明:http://www.cnblogs.com/shangxiaofei/p/6340655.html 本文只用于理解rete算法,通过一个规则的编译成的网络结构,以及匹配过程去理解rete ...
- Java中对象方法的调用过程&动态绑定(Dynamic Binding)
Java面向对象的最重要的一个特点就是多态, 而多态当中涉及到了一个重要的机制是动态绑定(Dynamic binding). 之前只有一个大概的概念, 没有深入去了解动态绑定的机理, 直到很多公司都问 ...
- Python妙用re.sub分析正则表达式匹配过程
声明:本文所使用方法为老猿自行研究并编码,相关代码版权为老猿所有,禁止转载文章,代码禁止用于商业用途! 在<第11.23节 Python 中re模块的搜索替换功能:sub及subn函数>介 ...
- Python正则表达式书写容易碰到的陷阱:\W*和\W*?匹配过程遇到的问题
老猿在分析<Python正则表达式\W+和\W*匹配过程的深入分析>中的问题时,想到一个问题,如果"re.split('(\W*)','Hello,world')"的处 ...
- Python正则表达式\W+和\W*匹配过程的深入分析
在学习re.split函数的处理过程中,发现执行如下语句及返回与老猿预想的不一致: >>> re.split('\W*','Hello,world') ['', 'H', 'e', ...
随机推荐
- Linux:一位猫奴的意外产物
作者:Vamei,严禁任何形式转载. 1991年年中,林纳斯·托瓦兹(Linus Torvalds)在自己房间里敲着键盘.他全神贯注地盯着14寸的黑色屏幕,都没感觉到自己的小猫Randi在扒自己的裤腿 ...
- Notepad++ 7.3.2 Download 64-bit x64 / 32-bit x86
Notepad++ 7.3.2 Download 32-bit x86 Notepad++ Installer 32-bit x86: Take this one if you have no ide ...
- Unity使用GL画线
脚本需挂在相机上,如果你的脚本,编辑器报错了,Matrix stack full depth reached,加上这个方法试试GL.LoadPixelMatrix(); using System.Co ...
- PHP运算符与表达式
一.概述: 在我们平时的开发中,最离不开的就是运算,在编写比较复杂的后台程序的时候,算法更是必不可少的.涉及到运算就应该了解PHP的运算符,下面我们来一起看一下PHP中常见的运算符,以及和其他语言的区 ...
- Sencha+cordova 构造 华丽手机程序,并讲讲,在商用项目中经常用到的cordova插件(一)
采用 Sencha Architect 3 ,编辑设计,我只想说一个结论,jq能搞的 Sencha touch也能做到(只是 设计思路 更面向对象,学习知识量大点而已 ,不理解 MVC 就不用选了), ...
- AJAX做增删改查详细!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Linux 基础(2)
Linux 基础(二) 用户 组 及权限的相关操作 一.useradd命令选项:–u:指定用户的UID useradd –u 100 mu #指定mu的UID为100–g:指定用户所属的群组 user ...
- 使用虚拟机CentOS7部署CEPH集群
第1章 CEPH部署 1.1 简单介绍 Ceph的部署模式下主要包含以下几个类型的节点 Ø CephOSDs: A Ceph OSD 进程主要用来存储数据,处理数据的replication,恢复 ...
- 【算法系列学习】[kuangbin带你飞]专题二 搜索进阶 D - Escape (BFS)
Escape 参考:http://blog.csdn.net/libin56842/article/details/41909459 [题意]: 一个人从(0,0)跑到(n,m),只有k点能量,一秒消 ...
- PHP学习笔记-2
PHP 是一门弱类型语言: 在上面的实例中,我们注意到,不必向 PHP 声明该变量的数据类型.(跟Javascript很像啊!) PHP 会根据变量的值,自动把变量转换为正确的数据类型. 在强类型的编 ...