資料報接收函式利用pt prev減少一次skb複製

2021-08-16 12:23:13 字數 1586 閱讀 5006

接收函式__netif_receive_skb_core,負責把驅動層收到的資料報傳遞給上層協議處理,其中包括ip層(ip_rcv)、arp層(arp_rcv)、sniffer類程式(tcpdump)等。利用pt_prev延緩執行最後乙個協議處理函式,可減少一次skb複製。

所謂減少一次skb複製,首先來看複製的**位置。在上層協議處理函式中,當需要改變skb結構體的內容時,要拷貝(skb_clone)乙份協議自己的副本。以ip_rcv為例來看拷貝相關**:

376 int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)

377

複製**位於skb_share_check中:

1177 static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri)

1178

1189 return skb;

1190 }

拷貝與否還要看skb_shared的返回結果,這即是關鍵之處,通過控制skb->users的數值來控制是否複製skb:

1159 static inline int skb_shared(const struct sk_buff *skb)

1160

至此,來看__netif_receive_skb_core函式的控制邏輯,首先,呼叫deliver_skb處理所有註冊的協議處理函式,最後乙個除外,不進行處理:

3619 static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)

3620

函式deliver_skb,增加skb->users的計數(等於2),導致skb_shared(skb)為真,上層協議處理函式ip_rcv複製乙份skb,遞減原skb的引用計數,處理完成後釋放複製的skb:

1728 static inline int deliver_skb(struct sk_buff *skb,

1729 struct packet_type *pt_prev,

1730 struct net_device *orig_dev)

1731

函式__netif_receive_skb_core結尾處,不呼叫deliver_skb,不增加skb->users計數,直接呼叫協議處理函式,由於skb->users計數等於1,skb_shared(skb)結果為假,省去了一次skb的複製(同時省去了相應的釋放操作)。因為是最後乙個協議處理函式,無需再複製,最後skb在此函式內完全釋放。

3619 static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)

3620

核心**基於linux-4.0。

接收網路資料報

接收網路資料報一種好的方法就是可以建立套介面 位元組緩衝 來對網路資料先進行緩衝再在以後進行處理 由於接收的資料報是位元組連續的,所以需要設定一塊一塊連續的記憶體塊來儲存網路資料報,因而必須設定記憶體塊的大小 const unsigned int trunksize 64 1024 一般網路資料比較...

廣播資料報的接收

對資料報接收方來說,資料報的過濾有兩層,首先是mac位址的過濾,一般只接收目標mac位址為自身mac位址和全1的廣播位址 支援組播的話,還有組播mac位址 接下來是ip位址過濾,目標ip位址為本機的,或者為廣播ip幀的才會往上面 tcp udp 傳。ip廣播有兩種,一種是有限廣播 目標ip為255....

網絡卡如何接收資料報

ip報文可以看作乙個包。linux網絡卡驅動程式,將ip包新增14位元組的mac包頭,構成mac包。mac包中含有傳送端和接收端的mac位址資訊。既然是驅動程式建立的mac包頭資訊,當然可以隨便輸入位址資訊的,主機偽裝就是這麼實現的。驅動程式將mac包拷貝到網絡卡晶元內部的快取區,就算完事了。有網絡...