sk buff結構分析

2021-06-20 03:26:37 字數 3404 閱讀 2629

原文出處:

前言:以下是根據《深入理解linux網路技術內幕》對sk_buff的相關總結,由於是剛剛看這本書(太厚了),不免在前期出現錯誤,隨著對此書的深入我會在修改前面的錯誤,也希望各位牛人給予指點。幫助我成長。

sk_buff分析:

sk_buff是linux網路**中最重要的結構體之一。它是linux在其協議棧裡傳送的結構體,也就是所謂的「包」,在他裡面包含了各層協議的頭部,比如ethernet, ip ,tcp ,udp等等。也有相關的操作等。熟悉他是進一步了解linux網路協議棧的基礎。

此結構定義在標頭檔案中,結構體布局大致可分為以下四部分:

l       布局(layout)

l       通用(general)

l       功能專用(feature-specific)

l       管理函式(management functions)

網路選項以及核心結構

我們可以看到在此結構體裡有很多預處理,他是在需要指定相應功能時才起作用,我們在這裡先對通用的作出分析。

布局字段:

sk_buff是乙個複雜的雙向鍊錶,在他結構中有next和prev指標,分別指向鍊錶的下乙個節點和前乙個節點。並且為了某些需求(不知道是哪些目前)需要很快定位到鍊錶頭部,所以還有乙個指向鍊錶頭部的指標list(我在2.6.25核心沒有發現這個指標)。

sk_buff_head結構是:

struct sk_buff_head {

/* these twomembers must be first. */

structsk_buff *next;

structsk_buff *prev;

__u32       qlen; //代表元素節點數目

spinlock_t      lock; //加鎖,防止對錶的併發訪問

struct sock *sk

這個指標指向乙個套接字sock資料結構。當資料在本地產生或者本地程序接受時,需要這個指標;裡面的資料會有tcp/udp和使用者態程式使用。如果是**此指標為null

unsigned int len

緩衝區中資料塊大小。長度包括:主要緩衝區(head所指)的資料以及一些片斷(fragment)的資料。當包在協議棧向上或向下走時,其大小會變,因為有頭部的丟棄和新增。

unsigned int data_len

片段中資料大小

unsigned int mac_len

mac包頭大小

atomic_t users

引用計數,使用這個sk_buff的使用者的數目,可能有多個函式要使用同乙個sk_buff所以防止提前釋放掉,設定此計數

unsigned int truesize

此緩衝區總大小,包括sk_buff。sk_buff只不過是個指標的集合,他所指的才是真正的資料區,所以是兩部分。(見下圖)

sk_buff_data_t         tail;

sk_buff_data_t         end;

unsigned char     *head, *data;

這些指標很重要,他們指向的是真正的資料區,他們的邊界。head和end指向的是資料區的開端和尾端(注意和data,tail區別)如下圖,data和tail指向的是實際資料的開頭和結尾。

因為資料區在協議棧走的時候要一層層新增或去掉一些資料(比如報頭)所以申請一塊大的足夠的記憶體,然後在往裡放東西。真實的實際資料可能用不了這麼多,所以用data,tail指向真實的,head,tail指向邊界。剛開始沒填充資料時前三個指標指向的是乙個地方。

void (*destructor) (…….)

此函式指標被初始化乙個函式,當此緩衝區刪除時,完成某些工作。

通用字段

struct timeval stamp(2.6.25沒有,估計是ktime_t tstamp)

時間戳,表示何時被接受或有時表示包預定的傳輸時間

struct net_device *dev

描述乙個網路裝置,我會以後分析他。

sk_buff_data_t         transport_header; //l4

sk_buff_data_t         network_header; //l3

sk_buff_data_t         mac_header; //l2

這些指標分別指向報文頭部,和2.4版本比較有了變化,不再是聯合體,使用更加方便了,linux給出了很方便的函式直接定位到各層的頭部。下圖是2.4版本的,只是說明一下。

struct dst_entry dst

路由子系統使用。目前不知道怎麼回事呢。據說比較複雜。

char cb[40]

緩衝控制區,用來儲存私有資訊的空間。比如tcp用這個空間儲存乙個結構體tcp_skb_cb ,可以用巨集tcp_skb_cb(__skb)定位到他,然後使用裡面的變數。

ip_summed:2

__wsum   csum;

校驗和unsigned char pkt_type

根據l2層幀的目的位址進行型別劃分。

unsigned char cloned

表示該結構是另乙個sk_buff轉殖的。

__u32           priority;

qos等級

__be16               protocol;

從l2層裝置驅動看使用在下乙個較高層的協議。

功能專用字段

linux是模組化的,你編譯時可以帶上特定功能,比如netfilter等,相應的字段才會生效。應該是那些預定義控制的。

管理函式

下面這個圖是:(a*)skb_put; (b*) skb_push; (c*) skb_pull (d*)skb_reserve的使用,主要是對skb_buf所指向的資料區的指標移動。(資料預留以及對齊)

下圖是用skb_reserve函式,把乙個14位元組的ethernet幀拷貝到緩衝區。skb_reserve(skb, 2), 2表示16位元組對齊。14+2=16

下圖是穿過協議棧從tcp層向下到鏈路層的過程

分配記憶體:

alloc_skb 分配緩衝區和乙個sk_buff結構

dev_alloc_skb 裝置驅動程式使用的緩衝區分配函式

釋放記憶體:

kfree_skb 只有skb->users計數器為1時才釋放

dev_kfree_skb

緩衝區轉殖函式 skb_clone

列表管理函式:

skb_queue_head_init

佇列初始化

skb_queue_head , skb_queue_tail

把乙個緩衝區新增到佇列頭或尾

skb_dequeue, skb_dequeue_tail

從頭或尾去掉

skb_queue_purge

把佇列變空

skb_queue_walk

迴圈佇列每個元素

sk buff詳細介紹

struct sk buff可能是linux網路 中最重要的資料結構,它表示接收或傳送資料報的包頭資訊,幷包含很多成員變數供網路 中的各子系統使用。這個結構被網路的不同層 mac或者其他二層鏈路協議,三層的ip,四層的tcp或udp等 使用,並且其中的成員變數在結構從一層向另一層傳遞時改變。l4向l...

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...