1.sk_buff是linux 網絡內核裏面最終要的數據結構了.存放要發送和接收的數據.頭文件 linux/skbuff.h
2.主要成員以及相關結構函數分爲以下幾類
a.layout
struct sk_buff *next;
struct sk_buff *prev;
struct sk_buff_head* list; 方便找到表頭
__u32 qlen; 雙鏈表裏sk_buff結構的數量
spinlock_t lock; 保證操作鏈表安全
struct sock *sock; 指向tcp udp socket結構,如果數據被轉發的話,該指針爲NULL
unsigned int len; 整個sk_buff鏈data_len的總和
unsigned int data_len; 當前sk_buff的數據長度.包含協議頭部內容.各層傳輸時大小會變化
unsigned int mac_len; mac頭部大小
atomic_t users; 引用計數.(skb_get kfree_skb改變)
unsigned int truesize; data大小 + sizeof(sk_buff)
unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end; 以上都是數據段的指針
void (*destructor)(...) 當sk_buff某個socket的時候被初始化,通常執行sock_rfree或者sock_wfree
b.general
struct tim stamp; 接收到數據時時間
struct net_device *dev; 網絡設備,也很重要
struct net_device *input_dev; 輸入設備
struct net_device *real_dev; 可用於虛擬設備
union
{
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct spxhdr *spxh;
unsigned char *raw;
} h;
union
{
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
struct ipxhdr *ipxh;
unsigned char *raw;
} nh;
union
{
struct ethhdr *ethernet;
unsigned char *raw;
} mac;
struct dst_entry dst; 路由子系統使用,複雜
char cb[40]; 控制緩衝區或者存放隱私信息,例如tcp用它來存放一個struct_skb_cb的結構體
struct tcp_skb_cb {
... ... ...
_ _u32 seq;
_ _u32 end_seq;
_ _u32 when;
_ _u8 flags;
... ... ...
};
unsigned int csum;
unsigned char ip_summed;
unsigned char cloned; 該sk_buff是否克隆的
unsigned char pkt_type; 根據L2層的目的地址判斷,該數據包的類型,本機的,多播,廣播,其他主機
__u32 priority; 發送和轉發的QoS
unsigned short protocol; L2層的協議類型.通常是ip ip6 arp rarp
unsigned short security; IPSec,未使用
c.feature-specific
unsigned long nfmark;
__u32 nfcache;
__u32 nfctinfo;
struct nf_conntrack *nfct;
unsigned int nfdebug;
struct nf_bridge_info *nf_bridge;
以上字段netfilter模塊使用.
union {...} private HIPPI使用
__u32 tc_index;
__u32 tc_verd;
__u32 tc_classid;
以上字段用於traffic control
struct sec_path *sp; 用於IPSec跟蹤傳輸
d.manegement functions
sk_put L2層接收數據時,將除了數據幀頭部(已經拷貝)的內容包考到sk_buff數據緩衝區
sk_push 發送數據時,高層->低層添加頭部(data指針改變)
sk_pull 接收數據時,低層->高層去掉頭部(data指針改變)
sk_reserve L2層開始接收數據前,保持4字節對齊,data += 2
alloc_skb dev_alloc_skb 分配空間函數,默認用dev_alloc_skb.分配的空間包括兩次,第一個是struct sk_buff,第二個是data_size + sizeof(struct skb_shared_info)
kfree_skb dev_kfree_skb 釋放sk_buff內存
struct skb_shared_info { 緊跟着data緩衝區後面,保存data緩衝區的相關信息的結構體
atomic_t dataref;
unsigned int nr_frags;
unsigned short tso_size;
unsigned short tso_seqs;
unsigned sk_buff *frag_list;
skb_frag_t frags[MAX_SKB_FRAGS];
};
clone和copy
clone:數據需要給其他的使用者時候(不會改變數據內容),會採用clone.分配一個新的sk_buff,並且 cloned屬性爲1,users屬性爲1,保證不要的時候釋放內存.head data等仍然指向以前的data緩衝區.但是 保存data緩衝區的
struct skb_shared_info的dataref需要加一.
copy:其他使用者需要改變data緩衝區的數據的時候使用.分配兩塊新的內存.不會設置clone位
相關函數:skb_clone pskb_copy(拷貝當前data緩衝區) skb_copy(拷貝所有data緩衝區)
skb_queue_head_init 初始化一個空鏈表
skb_queue_head skb_queue_tail 添加sk_buff到鏈表
skb_dequeue skb_dequeue_tail 刪除sk_buff從鏈表
skb_queue_purge 清空sk_buff鏈表
skb_queue_walk 循環鏈表
進行這些函數的時候需要使用 :
unsigned long flags;
spin_lock_irqsave(...);
function();
spin_unlock_irqrestore(...);
spin的作用在單處理器上,關中斷.多處理器上, 通過一個原子變量,保證函數的執行安全.
struct sk_buff 學習
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.