OVS源码--datapath(一)

一、datapath 简介

datapath为 ovs内核模块,负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。

一个datapath可以对应多个vport,一个vport类似物理交换机的端口概念。一个datapth关联一个flow table,一个flow table包含多个条目,每个条目包括两个内容:一个match/key和一个action
在这里插入图片描述

二、数据流向

在这里插入图片描述
一般的数据包在 Linux 网络协议中的流向为上图中的蓝色箭头流向:网卡eth0 收到数据包后判断报文走向,如果是本地报文把数据传送到用户态,如果是转发报文根据选路(二层交换或三层路由)把报文送到另一个网卡如eth1。当有 OVS 时,数据流向如红色所示:从网卡 eth0 收到报文后进入ovs 的端口,根据 key 值进行流表匹配,如果匹配成功执行流表对应的 action;如果失败通过upcall 送入用户态处理。

三、源码分析

1、模块初始化

内核模块采用module_init(dp_init)进行datapath 的初始化,代码如下:
在这里插入图片描述
其中dp 的genl_family 注册了如下四个类型:
在这里插入图片描述

2、收包处理

通过vport注册的回调函数netdev_frame_hook()-> netdev_port_receive()->ovs_vport_receive()处理接收报文,ovs_flow_key_extract()函数生成flow的key内容用以接下来进行流表匹配,最后调用ovs_dp_process_packet()函数进入真正的ovs数据包处理,代码流程如下:
在这里插入图片描述

3、流表哈希桶

流表采用hash的方式排列存放,流表的hash头结点存储数据结构如下:
在这里插入图片描述
该hash 桶的初始化函数alloc_buckets (),生成的数据格式可参考如下:
在这里插入图片描述

4、流表创建

用户态通过netlink 进行datapath 流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new 函数,代码分析如下:
在这里插入图片描述
根据上述流程给出流表的主要数据结构如下:
在这里插入图片描述

5、流表查询

流表查找主要是查表关键字的匹配,关键字数据结构如下,根据skb 中的Ethernet 帧生成key 的函数为ovs_flow_key_extract():
在这里插入图片描述
流表查询的入口函数ovs_flow_tbl_lookup_stats(),flow 的匹配策略是和流表中所有mask 和所有key 进行匹配处理,为了加速查询效率,在调用真正的流表查询函数flow_lookup()之前,对于mask 的查询采用了缓存机制,实现原理是首先查询缓存的mask_cache_entry,这些cache 是查询成功后形成的cache,并针对cache 采用分段查询的方式,代码如下:
在这里插入图片描述
flow_lookup()函数的处理流程如下:
在这里插入图片描述
masked_flow_lookup()函数处理如下:
在这里插入图片描述

6、action处理

ovs的action类型如下,使用nla_type()函数获取nl_type的值,入口处理函数为do_execute_actions()。
在这里插入图片描述

  • OVS_ACTION_ATTR_OUTPUT:获取port号,调用do_output()发送报文到该port;
  • OVS_ACTION_ATTR_USERSPACE:调用output_userspace()发送到用户态;
  • OVS_ACTION_ATTR_HASH:调用execute_hash()获取skb的hash赋值到ovs_flow_hash
  • OVS_ACTION_ATTR_PUSH_VLAN:调用push_vlan()增加vlan头部
    在这里插入图片描述
  • OVS_ACTION_ATTR_POP_VLAN:调用pop_vlan()移除vlan头
    在这里插入图片描述
  • OVS_ACTION_ATTR_RECIRC:在action_fifos全局数组中添加一个deferred_action;
  • OVS_ACTION_ATTR_SET:调用execute_set_action()设置相关参数;
  • OVS_ACTION_ATTR_SAMPLE:概率性的发送报文到用户态(详见sflow 章节)。

7、upcall 处理

当没有找到匹配的流表时,内核通过netlink 发送报文到用户层处理,入口函数ovs_dp_upcall(),该函数调用queue_userspace_packet()构造发往用户层的skb,通过netlink 通信机制发送到用户层,其中形成的主要数据格式如下:
在这里插入图片描述
原文链接:https://www.sdnlab.com/my_sdnlab/wp-content/uploads/2017/02/cntctfrm_1a5b490b5708a374ad0d207df48ec29e_Openvswitch%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0.pdf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章