1. 程式人生 > >Open vSwitch(OvS)原始碼分析之工作流程(flow流表查詢)

Open vSwitch(OvS)原始碼分析之工作流程(flow流表查詢)

前面分析了Open vSwitch幾部分原始碼,對於Open vSwitch也有了個大概的理解,今天要分析的程式碼將是整個Open vSwitch的重中之重。整個Open vSwitch的核心程式碼在datapath檔案中;而datapath檔案中的核心程式碼又在ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb);函式中;而在ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb);函式中的核心程式碼又是流表查詢(流表匹配的);有關於ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb);核心程式碼的分析在前面的《Open vSwitch(OvS)原始碼分析之工作流程(資料包處理)》中。今天要分析的就是其核心中的核心:流表的查詢(匹配流表項)原始碼。我分析原始碼一般是採用跟蹤的方法,一步步的往下面去分析,只會跟著主線走(主要函式呼叫),對其他的分支函式呼叫只作大概的說明,不會進入其實現函式去分析。由於流表的查詢設計到比較多的資料結構,所以建議對照著《Open vSwitch(OvS)原始碼分析之資料結構》去分析,我自己對資料結構已經大概的分析了遍,可是分析流表查詢程式碼時還是要時不時的倒回去看看以前的資料結構分析筆記。

注:這是我寫完全篇後補充的,我寫完後自己閱讀了下,發現如果就單純的看原始碼心裡沒有個大概的輪廓,不是很好理解,再個最後面的那個圖,畫的不是很好(我也不知道怎麼畫才能更好的表達整個意思,抱歉),所以覺得還是在這個位置(原始碼分析前)先來捋下框架(也可以先看完原始碼分析再來看著框架總結,根據自己情況去學習吧)。上面已經說過了《Open vSwitch(OvS)原始碼分析之資料結構》的重要性,現在把裡面最後那幅圖拿來順著圖示來分析,會更好理解。(最後再來說下那幅圖是真的非常有用,那相當於Open vSwitch的整個框架圖了,如果你要分析原始碼,有了那圖絕對是事半功倍,希望閱讀原始碼的朋友重視起來,哈哈,絕不是黃婆賣瓜)

Open vSwitch的整個框架圖

流表查詢框架(或者說理論):從ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)函式中開始呼叫函式查流表,怎麼查呢?

第一步,它會根據網橋上的流表結構體(table)中的mask_list成員來遍歷,這個mask_list成員是一條連結串列的頭結點,這條連結串列是由mask元素連結組成(裡面的list是沒有資料的連結串列結構,作用就是負責連結多個mask結構,是mask的成員);流表查詢函式開始就是迴圈遍歷這條連結串列,每遍歷到得到一個mask結構體,就呼叫函式進入第二步。

第二步,是操作key值,呼叫函式讓從資料包提取到的key值和第一步得到的mask中的key值,進行與操作,然後把結構存放到另外一個key值中(masked_key)。順序執行第三步。

第三步,把第二步中得到的那個與操作後的key值(masked_key),傳入 jhash2()演算法函式中,該演算法是經典的雜湊演算法,想深入瞭解可以自己查資料(不過都是些數學推理,感覺挺難的),linux核心中也多處使用到了這個演算法函式。通過這個函式把key值(masked_key)轉換成hash關鍵字。

第四步,把第三步得到的hash值,傳入 find_bucket()函式中,在該函式中再通過jhash_1word()演算法函式,把hash關鍵字再次雜湊得到一個全新的hash關鍵字。這個函式和第三步的雜湊演算法函式類似,只是引數不同,多了一個word。經過兩個雜湊演算法函式的計算得到一個新的hash值。

第五步,把第四步得到的hash關鍵字,傳入到flex_array_get()函式中,這個函式的作用就是找到對應的雜湊頭位置。具體的請看上面的圖,流表結構(table)中有個buckets成員,該成員稱作為雜湊桶,雜湊桶裡面存放的是成員欄位和彈性陣列parts[n],而這個parts[n]數組裡面存放的就是所要找的雜湊頭指標,這個雜湊頭指標指向了一個流表項鍊表(在圖中的最下面struct sw_flow),所以這個才是我們等下要匹配的流表項。(這個雜湊桶到彈性陣列這一段,我有點疑問,不是很清楚,在下一篇blog中會分析下這個疑問,大家看到如果和原始碼有出入,請按原始碼來分析),這一步就是根據hash關鍵字查詢到流表項的連結串列頭指標。

第六步,由第五步得到的流表項鍊表頭指標,根據這個指標遍歷整個流表項節點元素(就是struct sw_flow結構體元素),每遍歷得到一個流表項sw_flow結構體元素,就把流表項中的mask成員和第一步遍歷得到的mask變數(忘記了可以重新回到第一步去看下)進行比較;比較完後還要讓流表項sw_flow結構體元素中的key值成員和第二步中得到的key值(masked_key)進行比較;只有當上面兩個比較都相等時,這個流表項才是我們要匹配查詢的流表項了。然後直接返回該流表項的地址。查詢完畢!!接下來分析原始碼了。

在ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb);函式中流表查詢呼叫程式碼:

C
1 2 3 // ovs_flow_lookup()是流表查詢實現函式;引數rcu_dereference(dp->table):網橋流表(不是流表項);   // 引數&key:資料包各層協議資訊提取封裝的key地址;返回值flow:查詢到的或者說匹配到的流表項   flow = ovs_flow_lookup ( rcu_dereference ( dp -> table ) , & key ) ;

這裡要特別說明下:dp->table是流表,是結構體struct flow_table的變數;而flow是流表項,是結構體struct sw_flow的變數;我們平常習慣性說的查詢流表或者匹配流表,其實並不是說查詢或者匹配flow_table結構體的變數(在openVswitch中flow_table沒有連結串列,只有一個變數),而是struct sw_flow的結構體連結串列。所以確切的說應該是查詢和匹配流表項。這兩個結構是完全不同的,至於具體的是什麼關係,有什麼結構成員,可以檢視下openVswitch(OVS)原始碼分析之資料結構。如果不想看那麼繁瑣的分析,也可以看下最後面的那張圖,可以大概的瞭解下他們的關係和區別。

下面來著重的分析下ovs_flow_lookup()函式,主要是迴圈遍歷mask連結串列節點,和呼叫ovs_masked_flow_lookup()函式。

C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // tbl是網橋結構中的table,key是包中提取的key的地址指標   struct sw_flow * ovs_flow_lookup ( struct flow_table * tbl ,                     const struct sw_flow_key * key )    {         struct sw_flow * flow = NULL ; // 準備流表項,匹配如果匹配到流表項則返回這個變數        struct sw_flow_mask * mask ; // 瞭解mask結構就非常好理解mask的作用          // 下面是從網橋上的table結構中頭mask_list指標開始遍歷mask連結串列,          // 依次呼叫函式去查詢流表,如果得到流表項則退出迴圈        list_for_each_entry_rcu ( mask , tbl -> mask_list , list ) {           // 流表查詢函式(其實是key的匹配),引數分別是:網橋的table,和資料包的key,以及網橋上的mask節點            flow = ovs_masked_flow_lookup ( tbl , key , mask ) ;             if ( flow )    /* Found */                 break ;   

相關推薦

Open vSwitchOvS原始碼分析工作流程flow查詢

前面分析了Open vSwitch幾部分原始碼,對於Open vSwitch也有了個大概的理解,今天要分析的程式碼將是整個Open vSwitch的重中之重。整個Open vSwitch的核心程式碼在datapath檔案中;而datapath檔案中的核心程式碼又在ovs_dp_process_re

Spark原始碼分析Spark Shell

https://www.cnblogs.com/xing901022/p/6412619.html 文中分析的spark版本為apache的spark-2.1.0-bin-hadoop2.7。 bin目錄結構: -rwxr-xr-x. 1 bigdata bigdata 1089 Dec

Uboot啟動過程原始碼分析第一階段硬體相關

從上一個部落格知道uboot的入口點在 cpu/arm920t/start.s 開啟cpu/arm920t/start.s 跳轉到reset reset: /* * set the cpu to SVC32 mode// CUP設定為管理模式 */ mrs r0,cps

【NLP】【三】jieba原始碼分析關鍵字提取TF-IDF/TextRank

【一】綜述 利用jieba進行關鍵字提取時,有兩種介面。一個基於TF-IDF演算法,一個基於TextRank演算法。TF-IDF演算法,完全基於詞頻統計來計算詞的權重,然後排序,在返回TopK個詞作為關鍵字。TextRank相對於TF-IDF,基本思路一致,也是基於統計的思想,只不過其計算詞的權

雲客Drupal8原始碼分析外掛系統

以下內容僅是一個預覽,完整內容請見文尾: 至此本系列對外掛的介紹全部完成,涵蓋了系統外掛的所有知識 全文目錄(全文10476字): 例項化外掛 外掛對映Plugin mapping 外掛上下文  

以太坊原始碼分析 P2P網路三、UDP底層通訊

區塊鏈特輯 :https://blog.csdn.net/fusan2004/article/details/80879343,歡迎查閱,原創作品,轉載請標明!這周工作有點小忙,部門區塊鏈基礎平臺的開發開始進入節奏了,和上一篇間隔間隔有點久了,以後還是要堅持,不能剛開始就犯毛

以太坊原始碼分析 P2P網路二、節點發現流程

區塊鏈特輯 :https://blog.csdn.net/fusan2004/article/details/80879343,歡迎查閱,原創作品,轉載請標明!上一篇文章簡單介紹了下一些基礎的型別定義,從這一篇開始我們將描述p2p網路的更多細節。從關於節點的定義來看,其實不同

elasticsearch原始碼分析分片分配

分片 什麼是分片 分片是把索引資料切分成多個小的索引塊,這些小的索引塊能夠分發到同一個叢集中的不同節點。在檢索時,檢索結果是該索引每個分片上檢索結果的合併。類似於資料庫的分庫分表。 為什麼分片 1、這樣可以提高讀寫效能,實現負載均衡。 2、副本容易

elasticsearch原始碼分析索引操作

上節介紹了es的node啟動如何建立叢集服務的過程,這節在其基礎之上介紹es索引的基本操作功能(create、exist、delete),用來進一步細化es叢集是如果工作的。 客戶端部分的操作就不予介紹了,詳細可以參照elasticsearch原始碼分析之客戶

elasticsearch原始碼分析服務端

上篇部落格說明了客戶端的情況,現在繼續分析服務端都幹了些啥,es是怎麼把資料插進去的,此處以transport的bulk為入口來探究,對於單個document的傳送就忽略了。 一、服務端接收 1.1接收訊息 在客戶端分析中已經提到,netty中通訊的處理類是Mes

elasticsearch原始碼分析啟動過程

最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,

Android4.4.2原始碼分析WiFi模組

已經寫了幾篇關於Android原始碼的,原始碼程式碼量太大,所以如果想分析某個模組可能不知如何下手,說一下思路 1,分析原始碼英文閱讀能力要夠,想要分析某個模組一般找模組對應的英文,就是模組 2,找到之後首先檢視清單配置檔案Androidmani.fest,找到程式主介面activity 3,通過檢視配置檔

netty十七原始碼分析客戶端建立

相對於服務端,Netty客戶端的建立更加複雜,除了要考慮執行緒模型、非同步連線、客戶端連線超時等因素外,還需要對連線過程中的各種異常進行考慮。 下面我們直接分析客戶端連線操作: 首先要建立和初始化NioSocketChannel,程式碼如下: private Cha

Vue原始碼分析依賴收集

依賴收集就是訂閱資料變化watcher的收集,依賴收集的目的是當響應式資料發生變化時,能夠通知相應的訂閱者去處理相關的邏輯。在上一章,介紹了Vue將普通物件變成響應式物件是利用defineReactive()(定義在'core/observer/index.js'中)函式,d

spark mllib原始碼分析L-BFGS

1. 使用 spark給出的example中涉及到LBFGS有兩個,分別是LBFGSExample.scala和LogisticRegressionWithLBFGSExample.scala,第一個是直接使用LBFGS直接訓練,需要指定一系列優化引數,優

雲客Drupal8原始碼分析實體Entity配置實體基類

配置實體基類是系統定義的一個用於配置實體的抽象基類,繼承自實體基類,完成了配置實體的大部分通用功能,具體的配置實體往往會繼承它,比如使用者角色實體,這樣寫少量程式碼即可,類定義如下: Drupal\Core\Config\Entity\ConfigEntityBase 實

雲客Drupal8原始碼分析實體Entity內容實體基類

原始碼分析重點在於在自己的大腦中重現開發者的思維過程,內容實體基類是drupal中很大的一個類,她要處理眾多的問題,內容實體的大多數功能都集中在這裡,開發者有許多的考慮,要弄清楚她的所有細節,學習者可能會覺得有些困難,這時需要明白任何複雜龐大的事物都是一步步累積發展起來的,

雲客Drupal8原始碼分析外掛系統

各位《雲客drupal8原始碼分析》系列的讀者: 本系列一直以每週一篇的速度進行部落格原創更新,希望幫助大家理解drupal8底層原理,並縮短學習時間,但自《外掛系統(上)》主題開始部落格僅釋出前言和目錄,這是因為雲客在思考一個問題:drupal在國外如此流行但在國內卻很小

netty原始碼分析ByteBuf

通過對netty的API的學習,可以更加遊刃有餘的使用netty的相關類庫 對原始碼的學習不僅能夠從原始碼層面掌握netty框架,方便日後的維護,拓展和定製而且可以起到觸類旁通的作用,拓展讀者的知識面,提升程式設計技能。當我們進行資料傳輸的時候,往往需要使用到緩衝區,常用的

Android4.4.2原始碼分析WiFi模組

接著上一篇繼續對WiFi原始碼的分析 onResume方法中 6>,首先是呼叫WiFiEnabler的resume方法對switch進行管理 接下來註冊廣播 getActivity().registerReceiver(mReceiver, mFilter);