根據上篇博文的介紹,gro需要支援gro的每種協議都要實現自己的報文匹配合併函式和合併完成函式。這裡我們先來看看鏈路層上
實現的自己的gro函式。
鏈路層的接收匹配函式__napi_gro_receive(napi, skb):
該函式對報文進行匹配,並不合併報文。
匹配規則(必須同時滿足以下兩個條件):
1、兩個報文的接收dev必須相同。
2、兩個報文的以太頭必須相同。
static int__napi_gro_receive(struct napi_struct *napi,struct sk_buff *skb)
return dev_gro_receive(napi, skb);
}intdev_gro_receive(struct napi_struct *napi,struct sk_buff *skb)
/*如果是ip 分片報文,不進行gro處理,因為如果報文是經過三層**的報文,不需要重組後再**。
是否需要重組交由ip層進行處理,這裡就不進行gro的處理了。
*/if (skb_is_gso(skb) || skb_has_frags(skb))
/*加rcu讀鎖對 ptype_base hahs 鍊錶進行保護*/
rcu_read_lock();
/*遍歷鍊錶,找到處理該型別報文的ptype,
*並且該型別的ptype 實現了處理gro 的函式
*/list_for_each_entry_rcu(ptype, head, list)
rcu_read_unlock();
/*如果沒找到對該協議型別報文進行處理的gro,不進行gro操作*/
if (&ptype->list == head)
same_flow = napi_gro_cb(skb)->same_flow;
ret = napi_gro_cb(skb)->free ? gro_merged_free :
gro_merged;
/*如果協議的gro處理函式返回了合併後的報文,
*就呼叫napi_gro_complete把報文送進協議棧進行處理
*/if (pp)
/*如果same 被設定了,說明在鍊錶上找到了相匹配的報文了,
*已經合併過了,不再需要快取了
*/if (same_flow)
/*如果沒找到相匹配的報文,需要快取。
*快取前需要判斷佇列是否已滿或該報文是否應該快取
*/if (napi_gro_cb(skb)->flush ||
napi->gro_count >= max_gro_skbs)
/*快取沒有匹配的報文到gro_list,返回值為gro_held*/
napi->gro_count++;
napi_gro_cb(skb)->count = 1;
skb_shinfo(skb)->gso_size = skb_gro_len(skb);
skb->next = napi->gro_list;
napi->gro_list = skb;
ret = gro_held;
pull:
/*經過這個協議棧的gro receive的處理,
*這時napi_gro_cb(skb)->data_offset欄位已經設定好了。
*如果gro需要處理的資料不在skb的線性區,
*把需要的資料copy到線性區,方便以後操作
*/if (skb_headlen(skb) < skb_gro_offset(skb))
}ok:
return ret;
normal:
ret = gro_normal;
goto pull;
}鏈路層的gro完成函式:
合併完成後的報文呼叫該函式來把報文送入協議棧。
static intnapi_gro_complete(struct sk_buff *skb)
/*找到相關協議把報文送給協議的grp_complete函式處理*/
rcu_read_lock();
list_for_each_entry_rcu(ptype, head, list)
rcu_read_unlock();
if (err)
/*各層協議處理完成後,送給協議棧進行處理*/
out:
return netif_receive_skb(skb);
}我們從上面分析看到,鏈路層處理完鏈路層上gro的處理後,會再呼叫網路層上對應得gro處理。每一層協議自己負責自己的gro處理。上次處理完後把處理結果返給下一層。最終由鏈路層來根據處理結果來把報文送給協議棧 。
下文我們分析一下ip層對gro的處理實現。
Linux網路子系統中協議棧的入口處理
網路驅動接收到報文後,會初始化skb protocol 字段。鏈路層的接收函式netif receive skb會根據該字段來確定把報文送給那個協議模組進一步處理。乙太網的裝置呼叫eth type trans 來給skb protocol賦值。be16eth type trans struct sk...
網路子系統在鏈路層的收發過程剖析(四)
5 資料報的傳送 資料報的傳送為接收的反過程,傳送過程較之接收過程的複雜性在於它有乙個流量控制層 trafficing control layer 用於實現 os,但不是本文關注的目標。1 netif schedule 當核心有資料報等待傳送時,它會間接呼叫 netif schedule 去處理這些...
Linux 網路子系統底層機制分析 1
linux 網路子系統底層機制分析 1 網路子系統在linux中的地位非常重要。在如今這個嚴重依賴網際網路,強調協同工作的時代,乙個高效,穩定的網路處理系統是留住使用者群的基本手段。前段時間花了一部分時間學習了一下linux的網路子系統的源 以及一些處理機制。這部分是由於工作的原因,另一部分原因是想...