一個在線看Linux源碼的網站http://lxr.free-electrons.com,需要翻牆
第二章 關鍵數據結構
本章講述以下兩個重要數據結構:
struct sk_buff:存儲所有網絡分層的包頭、有效載荷,其他內部信息
struct net_device:網絡設備的通用數據結構
-
sk_buff
佈局:
書上sk_buff 寫到的對分層頭的設計是以union形式來表示,這是Linux 2.6.24之前的方式
/* Transport layer header */
union
{
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct spxhdr *spxh;
unsigned char *raw;
} h;
/* Network layer header */
union
{
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
struct ipxhdr *ipxh;
unsigned char *raw;
} nh;
/* Link layer header */
union
{
struct ethhdr *ethernet;
unsigned char *raw;
} mac;
Linux 2.6.24後,這個分層的指針精簡爲了
#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif
......
sk_buff_data_t transport_header;
sk_buff_data_t network_header;
sk_buff_data_t mac_header;
L2到L3時報頭指針變化:
管理函數:有很多名稱類似do_something和__do_somthing,第一個是包裹函數,增加額外檢查或者上鎖,內部的__do_something通常不會直接調用。
報文經過每一層緩衝區處理的關鍵函數:
skb_reserve, skb_put, skb_push, skb_pull
主要是更新:skb->data, skb->len
skb_clone只是克隆了skb_buff的結構,指向相同的緩存,緩存保存了引用計數。
skb_copy是完全拷貝緩存。
sk_buff的隊列管理要注意上spin_lock鎖以保證原子操作。
net_device
包括真實設備和虛擬設備(VLAN或聚合口)
全局變量dev_base列表存儲了所有設備的net_device,
每個net_device有唯一的ID。
混雜模式promiscuous mode:設備接收所有封包。
設備的統計數據存在於設備的驅動內,net_device結構只保存一個priv指針指向該數據結構,有線和無線設備關鍵字段有區別。