1. 程式人生 > >linux網路協議棧(四)鏈路層 (1)鏈路層原理

linux網路協議棧(四)鏈路層 (1)鏈路層原理

四:鏈路層:

4.1、鏈路層原理:

4.1.1、鏈路層在幹什麼:

在報文接收方向上,網絡卡驅動把接收到的資料按照其對應的鏈路層協議(如乙太網)組裝成報文,然後把它上交給鏈路層,介面是netif_receive_skb,至此網絡卡驅動的任務就結束了,報文交給鏈路層處理;

在報文傳送方向上,網絡卡驅動受鏈路層驅使,鏈路層告知其有報文要傳送時,網絡卡驅動才開始工作,介面是dev_queue_xmit。

上面是鏈路層和網絡卡驅動層的介面,然而在鏈路層不一定是報文最終的歸宿,從報文接收角度看,絕大多數報文都要最終給目的主機的應用層,協議報文會在不同協議所屬層次終結,所以大多數報文都還要由鏈路層處理後(或不處理)再向上層轉發,比如IP報文,在鏈路層由ip_rcv函式進入網路層處理,比如由應用程式通過原始套接字獲取的報文將在鏈路層被直接送往socket層,比如arp協議報文會被送往arp模組去處理……

再從報文傳送角度看,不同的處理模組,會通過其專有介面通知鏈路層要傳送報文,比如對於網路層,通過ip_finish_output(最終是ip_finish_output2)告訴鏈路層要傳送報文(事實上是經由鄰居子系統模組實際傳送,鄰居子系統實現鏈路層和網路層的對映,可以認為屬於鏈路層和網路層的中間層),當然原始套接字的情況則比較簡單,直接呼叫dev_queue_xmit通知網絡卡驅動,然而對於網橋、vlan子介面的收發,鏈路層的處理就顯得極為必要,而從網路分層理論看,網橋、vlan,正是邏輯鏈路層的內容,這些都屬於linux鏈路層的核心工作,典型的對於乙太網的鏈路層,乙太網型別、vlan、源目MAC地址是鏈路層的協議欄位

此外,在鏈路層的無需三層協議轉發的二層隧道轉發方式,典型如按網路層IP地址轉發的eoip(Ethernet over ip),也是鏈路層的任務。

從功能上看,鏈路層完成以下任務:

1、  實現與網絡卡驅動和協議棧上層的介面;

2、  實現網橋,即實現按MAC地址轉發的二層交換機功能;

3、  實現vlan處理,實現帶vlan報文的傳輸;

4、  實現鄰居子系統,即實現鏈路層和網路層的對映;

5、  根據乙太網型別,實現根據鏈路層協議型別收發報文;

6、實現二層隧道功能(典型如依託於網路層IP地址轉發的eoip隧道);


如上圖,鏈路層由netif_receive_skb收到報文後,依次進行網橋處理、L2隧道處理、按乙太網型別處理(事實上在按乙太網型別處理前,還可能有其他處理),網橋處理中會根據報文是否發給本機還是轉發做不同的處理,發給本機將修改報文輸入介面為橋埠並返回netif_receive_skb重新進協議棧處理,轉發則直接呼叫dev_queue_xmit從對應介面傳送;L2隧道處理則根據所屬隧道的目的IP尋找路由,並根據路由結果指示的出介面轉發報文;按乙太網型別處理,就根據乙太網型別呼叫在之前註冊過的協議處理函式,如vlan報文呼叫vlan_skb_recv,IP報文呼叫ip_rcv,arp報文呼叫arp_rcv等等;

需要注意對於網橋和vlan的上本機的報文,會更新報文的輸入介面,由從網絡卡驅動接收介面改為對應的橋埠或vlan子介面(vlan報文還會去除vlan頭),這是因為事實上上層協議棧關心報文的“邏輯”輸入介面,而不是“物理”輸入介面,這些報文的反向報文也是由上層協議棧傳送到橋埠或vlan子介面,再繼而轉換為其原始的報文輸入介面通往網絡卡驅動,簡單的說就是網橋、vlan報文對於上層協議棧可見的是橋埠、vlan子介面。

綜上所述,鏈路層的功能是提供協議棧與網絡卡驅動的介面、協議棧上層的介面(按乙太網型別)、直接轉發(網橋或L2隧道),另外鄰居子系統實現了鏈路層和網路層的對映(對於IPV4為arp),另外需要注意,netif_receive_skb是在軟中斷處理函式呼叫的,也就是說整個協議棧報文處理是處於軟中斷中。

4.1.1、介面的概念:

介面可以理解為鏈路層的每一個收發單元,每一個介面可以對應實際的一個網絡卡,也可以是一個沒有實際物理裝置驅動對應的“虛”介面,比如網橋介面、vlan子介面,不論是“虛”介面還是“實”介面,在核心中都是以net_device結構體描述;

對於網路層,最重要的工作是選路,即確定路由,而確定路由就是確定報文是轉發還是上送本機,如果是轉發的話從哪個介面傳送(skb->_skb_dst),並且路由判決所需條件也包括報文的輸入介面即報文是從哪個介面上到網路層的(skb->dev),除路由之外,上層協議棧其他部分也經常關注報文的輸入介面和路由轉發介面;

所以介面是報文實際輸入輸出的邏輯路徑,但不一定是物理路徑,如某報文的路由結果是從eth0.5介面轉發出去,那麼這個eth0.5就是轉發的邏輯路徑,但它並沒有實際的物理驅動,而是再通過vlan子介面處理最終仍由eth0實際轉發報文,再如某報文由網橋br0上送到網路層,那麼br0是該報文的邏輯路徑,上層協議棧認為該報文就是從br0接收的,而實際該報文可能是由eth1實際接收的,經過網橋處理後輸入介面變為br0的。

之所以會有“虛”介面,都是因為一些特殊的目的,linux需要實現網橋,需要實現vlan,而這些都是邏輯上的概念,並不真的存在某種物理裝置叫網橋或者叫vlan,所以需要人為的製造出這些“虛”介面,以滿足上層協議棧向下處理的統一性,而這些“虛”介面和“實介面的“虛實轉換”,就是需要鏈路層實現的內容。

“實”介面一般由網絡卡驅動生成,因為網絡卡驅動管理實際的物理裝置,所以一般諸如eth0、wlan1、usb2之類“實”介面由網絡卡驅動生成,網絡卡驅動負責這些“實”介面的ops實現;而“虛”介面一般由應用程式生成,如網橋、vlan子介面,核心原始碼負責這些型別的“虛”介面的ops。

可以把linux機器想象成一臺能夠實現交換機、路由器、主機的L2/3/4/5功能的結合體機器,“實”介面就是這個結合體機器的每個物理埠,“虛”介面表面上實現一些二層網路功能,如vlan子介面實現物理埠的vlan功能,網橋介面實現二層交換功能,而實際上這些“虛”介面同樣被這個結合體機器的L3/4/5所識別