sk buff詳細介紹

2021-07-25 21:06:03 字數 4038 閱讀 1724

struct sk_buff可能是linux網路**中最重要的資料結構,它表示接收或傳送資料報的包頭資訊,幷包含很多成員變數供網路**中的各子系統使用。 

// 這個結構被網路的不同層(mac或者其他二層鏈路協議,三層的ip,四層的tcp或udp等)使用,並且其中的成員變數在結構從一層向另一層傳遞時改變。

// l4向l3傳遞前會新增乙個l4的頭部,同樣,l3向l2傳遞前,會新增乙個l3的頭部。

新增頭部比在不同層之間拷貝資料的效率更高。

//由於在緩衝區的頭部 新增資料意味著要修改指向緩衝區的指標,這是個複雜的操作,所以核心提供了乙個函式skb_reserve來完成這個功能。

//協議棧中的每一層在往下一層傳 遞緩衝區前,第一件事就是呼叫skb_reserve在緩衝區的頭部給協議頭預留一定的空間

skb_reserve同樣被裝置驅動使用來對齊接收到包的包頭。如果緩衝區向上層協議傳遞,舊的協議層的頭部資訊就沒什麼用了。

例如,l2的頭部只有在 網路驅動處理l2的協議時有用,l3是不會關心它的資訊的。

但是,核心並沒有把l2的頭部從緩衝區中刪除,而是把有效荷載的指標指向l3的頭部,這樣做, 可以節省cpu時間。

有些sk_buff成員變數的作用是方便查詢或者是連線資料結構本身。核心可以把sk_buff組織成乙個雙向鍊錶。

當然,這個鍊錶的結構要比常見的雙向 鍊錶的結構複雜一點。

就像任何乙個雙向鍊錶一樣,sk_buff中有兩個指標next和prev,其中,next指向下乙個節點,而prev指向上乙個節 點。

在第乙個節點前面會插入另乙個結構sk_buff_head,這是乙個輔助節點(作為sk_buff雙向鍊錶的頭),它的定義如下:

struct sk_buff_head ;

struct sk_buff ;

};///優先順序,主要用於qos。

__u32 priority; //packet queueing priority 報文排隊優先順序,取決於ip中的tos域

kmemcheck_bitfield_begin(flags1);

///接下來是一些標誌位。

__u8 local_df:1, //是否可以本地切片的標誌。

cloned:1, ///為1說明頭可能被clone。

ip_summed:2, ///這個表示校驗相關的乙個標記,表示硬體驅動是否為我們已經進行了校驗(前面的blog有介紹)

nohdr:1, ///這個域如果為1,則說明這個skb的頭域指標已經分配完畢,因此這個時候計算頭的長度只需要head和data的差就可以了。

nfctinfo:3;

__u8 pkt_type:3, ///pkt_type主要是表示資料報的型別,比如多播,單播,回環等等。

fclone:2, ///這個域是乙個clone標記。主要是在fast clone中被設定,我們後面講到fast clone時會詳細介紹這個域。

ipvs_property:1, ///ipvs擁有的域。

peeked:1, ///這個域應該是udp使用的乙個域。表示只是檢視資料。

nf_trace:1; ///netfilter使用的域。是乙個trace 標記

kmemcheck_bitfield_end(flags1);

__be16 protocol; ///這個表示l3層的協議。比如ip,ipv6等等。

void (*destructor)(struct sk_buff *skb); //skb的析構函式,一般都是設定為sock_rfree或者sock_wfree.

///netfilter相關的域。

#if defined(config_nf_conntrack) || defined(config_nf_conntrack_module)

struct nf_conntrack *nfct;

#endif

#ifdef net_skbuff_nf_defrag_needed

struct sk_buff *nfct_reasm;

#endif

#ifdef config_bridge_netfilter

struct nf_bridge_info *nf_bridge;

#endif

int skb_iif; //接收裝置的index。

///流量控制的相關域。

#ifdef config_net_sched

__u16 tc_index; /* traffic control index */

#ifdef config_net_cls_act

__u16 tc_verd; /* traffic control verdict */

#endif

#endif

__u32 rxhash;

kmemcheck_bitfield_begin(flags2);

///多佇列裝置的對映,也就是說對映到那個佇列。

#ifdef config_ipv6_ndisc_nodetype

__u8 ndisc_nodetype:2;

#endif

__u8 ooo_okay:1;

kmemcheck_bitfield_end(flags2);

/* 0/13 bit hole */

#ifdef config_net_dma

dma_cookie_t dma_cookie;

#endif

#ifdef config_network_secmark

__u32 secmark;

#endif

union ;

__u16 vlan_tci; //vlan標籤控制資訊;

sk_buff_data_t transport_header; //傳輸層頭

sk_buff_data_t network_header; // 網路層頭指標

sk_buff_data_t mac_header; //鏈路層頭

/* these elements must be at the end, see alloc_skb() for details. */

sk_buff_data_t tail; //儲存資料被容的結尾;

sk_buff_data_t end; //分配的記憶體塊的結尾;

unsigned char *head, // 分配的記憶體塊的起始位置;指向資料區中開始的位置(非實際資料區域開始位置)

*data; //儲存資料內容的首位址;(實際資料區域開始位置)

/*sk_buff->head sk_buff->data sk_buff->tail sk_buff->end 它們表示緩衝區和資料部分的邊界。

在每一層申請緩衝區時,它會分配比協議頭或協議資料大的空間。head和end指向緩衝區的頭部和尾部,而data和 tail指向實際資料的頭部和尾部。

每一層會在head和data之間填充協議頭,或者在tail和end之間新增新的協議資料。資料部分會在尾部包含一 個附加的頭部。

*/unsigned int truesize; //該緩衝區分配的所有總的記憶體,包括:skb_buff + 所有資料大小;//這個表示整個skb的大小,包括skb本身,以及資料。

/*這是緩衝區的總長度,包括sk_buff結構和資料部分。如果申請乙個len位元組的緩衝區,alloc_skb函式會把它初始化成len+sizeof(sk_buff)。當skb->len變化時,這個變數也會變化

*/atomic_t users; //儲存引用skb_buff的數量

/*這是乙個引用計數,用於計算有多少實體引用了這個sk_buff緩衝區。

它的主要用途是防止釋放sk_buff後,還有其他實體引用這個sk_buff。

因此,每個引用這個緩衝區的實體都必須在適當的時候增加或減小這個變數。

這個計數器只保護sk_buff結構本身,而緩衝區的資料部分由類似的計數器 (dataref)來保護.有時可以用atomic_inc和atomic_dec函式來直接增加或減小users,

但是,通常還是使用函式 skb_get和kfree_skb來操作這個變數。

*/};

1:  

//imporent 

//important

sk buff結構分析

原文出處 前言 以下是根據 深入理解linux網路技術內幕 對sk buff的相關總結,由於是剛剛看這本書 太厚了 不免在前期出現錯誤,隨著對此書的深入我會在修改前面的錯誤,也希望各位牛人給予指點。幫助我成長。sk buff分析 sk buff是linux網路 中最重要的結構體之一。它是linux在...

sk buff 函式操作 一)

1 alloc 分配完 之後的結構 僅僅是分配了線束資料區域,但是現在還沒有資料 2 skb reserve函式 static inline void skb reserve struct sk buff skb,int len 這個函式很重要,是為 協議頭 預留空間!而且是盡最大的空間預留,因為很...

SK BUFF 核心列印除錯

為了更方便的除錯報文,需要對sk buff的真正資料載荷進行除錯輸出,只需要在驅動中加入如下 就可以除錯了 static void qdmalib dump skb struct sk buff skb,struct net device dev netdev printk kern info,de...