struct sk_buff 學習

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的作用在單處理器上,關中斷.多處理器上, 通過一個原子變量,保證函數的執行安全.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章