Linux的網絡設備驅動架構- 接收封包/傳遞封包

(出處: Linux的網絡設備驅動架構)

從上到下可以劃分為4層,依次為:
—網絡協議接口層:向網絡層提供統一的數據包收發接口。
—設備層:向協議接口層提供統一的用於描述具體網絡設備的屬性和操作的結構體的net_device。
—驅動層:驅動層的各函數是net_device的數據結構的具體成員,使設備硬件完成相應動作的程序。
—物理層,也可以叫媒介層:是完成數據包發送和接收的物理實體。

在設計具體的網絡設備驅動程序時,我們的主要工作是編寫驅動層相關的函數,填充net_device數據結構,並將net_device 註冊進內核。

1. 協議接口層

1.1 dev_queue_xmit()
當上層協議,如ARP或IP協議,需要發送數據包時,將調用dev_queue_xmit()函數發送該數據包,同時傳遞給該函數一個指向struct sk_buff 數據結構的指針,該結構就代表了一個要傳送的數據包dev_queue_xmit()定義如下,注意這是向網絡發送一個數據包。當上層協議,如ARP或IP協議,需要發送數據包時,將調用dev_queue_xmit()函數發送該數據包,同時傳遞給該函數一個指向struct sk_buff 數據結構的指針,該結構就代表了一個要傳送的數據包dev_queue_xmit()定義如下,注意這是向網絡發送一個數據包。

1.2 netif_rx()
同樣,對數據包的接收,是通過向netif_rx() 函數傳遞一個struct sk_buff 數據結構指針來實現:
netif_rx()函數定義如下,注意這是從網絡接收一個數據包到內存。

1.3 sk_buff
這裡sk_buff非常重要
sk_buff — 套接字緩衝區,用來在linux網絡子系統中各層之間數據傳遞,起到了“神經中樞”的作用。
當發送數據包時,linux內核的網絡模塊必須建立一個包含要傳輸的數據包的sk_buff,然後將sk_buff傳遞給下一層,各層在sk_buff 中添加不同的協議頭,直到交給網絡設備發送。同樣,當接收數據包時,網絡設備從物理媒介層接收到數據後,他必須將接收到的數據轉換為sk_buff,並傳遞給上層,各層剝去相應的協議頭後直到交給用戶。
sk_buff結構如下圖所示: (define at include/linux/skbuff.h)

2. 設備層

設備層的主要功能是為各種網絡設備定義一個統一的數據結構net_device,實現多種硬件在軟件層次上的統一。
net_device結構體在內核中代表一個網絡設備。
網絡設備驅動程序只需要填充net_device的具體成員,並註冊net_device 即可實現硬件操作函數與內核的掛接。
net_device 是一個巨型結構體,包含了網絡設備的屬性描述和接口操作:
更多細節: net_device & net_device_ops

3. 驅動層:

net_device中的成員(屬性和函數指針),需要被驅動層的具體數值和函數賦值。
對於具體的網絡設備ethx, 軟件工程師需要編寫設備驅動層的函數,這些函数如下:
ethx_open();
ethx_stop();
ethx_tx();
ethx_hard_header();
ethx_get_stats();
ethx_tx_timeout();
ethx_poll();
等。

網絡數據包的接收可以由中斷引發,所以驅動層的另一個主要部分是中斷處理函數。
它負責讀取硬件設備上的數據包並傳給上層協議。
中斷處理函數一般如下:
ethx_interrupt(); — 完成中斷類型判斷等基本工
ethx_rx(); — 完成數據包的生成和傳遞給上層等複雜工作。

對於特定的設備,我們還可以定義其相關的私有數據(private_data) 和操作,並封裝一個私有信息結構體struct ethx_private,讓其指針被賦值給net_device 的priv 成員。
struct ethx_private 結構體中可以包含設備特殊的屬性,自旋鎖/信號量,定時器,及統計信息等,由工程師自己定義。

4. 物理媒介層

媒介層直接對應實際的硬件設備,為了對設備的物理配置和寄存器操作進行普通操作,我們可以定義一組宏或一組訪問函數,對內部寄存器進行訪問。
具體的定義和函數,對特定的硬件緊密相關。下面是設計範例:

發表迴響