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

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