轉:http://blog.csdn.net/adamska0104/article/details/45397177
Linux內核網絡報文簡單流程 2014-08-12 10:05:09
分類: Linux
linux下的網卡驅動中通常會提供類似XXX_rx的接收函數
該函數處理與具體硬件相關的寄存器操作
包括中斷檢查,數據狀態檢查,錯誤檢查等
在確認有數據抵達后讀取數據或從DMA的接收環中獲取數據地址
XXX_rx函數以skb為元數據結構組織報文數據
隨后調用內核接口函數netif_rx或netif_receive_skb
這里會涉及到軟中斷的處理,NAPI的接收方式
但是最后都會走netif_receive_skb函數
現在內核中使用了RPS機制
將報文分散到各個cpu的接收隊列中進行負載均衡處理
在netif_receive_skb函數中進行了封裝
真正的數據處理從__netif_receive_skb_core函數開始
現在可以將該函數視為協議棧的入口函數
首先進行skb中報文頭元數據的調整
如果是vlan報文則先從數據中提取至vlan_tci字段
將vlan標簽的4個字節從數據移除
即在調用deliver_skb向上層傳遞報文數據時不含vlan標簽
ptype_all鏈表的處理主要用於抓包
在應用程序中注冊PF_PACKET族ETH_P_ALL的socket便可以得到所有的輸入報文
也可以用於實現自定義的協議類型報文收發
隨后內核會丟棄無法識別的報文
也可以在內核模塊中使用dev_add_pack向ptype_all注冊自定義的處理函數
如果接口上配置了輸入流控
則根據具體的隊列和分類規則決定繼續處理或丟棄報文
對於vlan數據報文
將skb記錄的輸入接口修改為vlan虛接口
比如使用vconfig配置的eth0.100虛接口
再重復上述處理
內核提供了netdev_rx_handler_register接口函數向接口注冊rx_handler
比如為網橋下的接口注冊br_handle_frame函數
為bonding接口注冊bond_handle_frame函數
這相對於老式的網橋處理更靈活
有了這個機制也可以在模塊中自行注冊處理函數
網橋的處理包括向上層提交和轉發
發往本地的報文會修改入接口為網橋虛接口如br0
調用netif_receive_skb重新進入協議棧處理
對於上層協議棧見到的只有橋虛接口
需要轉發的報文根據轉發表進行單播或廣播發送
netfilter在網橋的處理路徑中從br_handle_frame到br_dev_queue_push_xmit設置了5個hook點
根據nf_call_iptables的配置還會經過NFPROTO_IPV4的hook點等
內核注冊的由br_nf_ops數組中定義
可在模塊中自行向NFPROTO_BRIDGE族的幾個hook點注冊函數
ebtables在netfilter框架NFPROTO_BRIDGE中實現了橋二層過濾機制
配合應用程序ebtables可在橋下自定義相關規則
處理完接口上的rx_handler后便根據具體的3層協議類型在ptype_base中尋找處理函數
比如ETH_P_IP則調用ip_rcv,ETH_P_IPV6則調用ipv6_rcv
這些函數都由dev_add_pack注冊
可在模塊中自定義協議類型處理函數
如果重復定義相同協議的處理函數則要注意報文的修改對后續流程的影響
IP報文進入ip_rcv后進行簡單的檢查便進入路由選擇
根據路由查找結果調用ip_local_deliver向上層提交或調用ip_forward進行轉發
向上層提交前會進行IP分片的重組
在ip_local_deliver_finish中會根據報文中4層協議類型調用對應的處理函數
處理函數由接口函數inet_add_protocol注冊
針對TCP或UDP進行不同處理,最后喚醒應用程序接收數據
向外發送和轉發數據經由ip_output函數
包括IP的分片,ARP學習,MAC地址的修改或填充等
netfilter在從ip_rcv到ip_output間設置了5個hook點
向各個點的鏈表中注冊處理函數或使用iptables工具自定義規則
實現報文處理的行為控制
報文的發送最后匯聚到隊列發送函數dev_queue_xmit
在接口up的時候dev_activate會創建默認的隊列規則
這里也涉及到接口驅動初始化的時候軟件多隊列與硬件多隊列
配合tc工具可以在報文發送前進行流量控制等
最終報文發送到dev_hard_start_xmit調用接口注冊的動作函數ndo_start_xmit
發送前會檢查ptype_all鏈表,支持抓包處理等
如果是虛擬接口則通常調用其對應物理接口的發送函數
到這里內核對報文的控制便結束了
根據不同網卡驅動的實現,操作寄存器等由物理層將數據發送出去
整個調用鏈相對較長
每個點都包含大量的細節
主線都是圍繞元數據結構skb的處理
