天天看點

struct s_mbuf與struct sk_buff

struct s_mbuf與struct sk_buff本文的copyleft歸[email protected]所有,使用GPL釋出,可以自由拷貝,轉載。但轉載請保持文檔的完整性,注明原作者及原連結,嚴禁用于任何商業用途。

作者:[email protected]

部落格:linuxfocus.blog.chinaunix.net    

為了有一個入口來研究TCP/IP源碼,那麼就按照《TCP/IP詳解——卷2》來開始吧。

TCP/IP詳解的内容是Linux2.4的,在Linux2.6中mbuf有了很大的變化。

檔案位置:linux-2.6.36.1/drivers/net/skfp/h/mubf.h

#define M_SIZE    4504 

#ifndef MAX_MBUF

#define MAX_MBUF    4

#endif

#ifndef NO_STD_MBUF

#define sm_next m_next

#define sm_off m_off

#define sm_len m_len

#define sm_data m_data

#define SMbuf Mbuf

#define mtod        smtod

#define mtodoff        smtodoff

struct s_mbuf {

    struct s_mbuf    *sm_next ;        /* low level linked list */

    short        sm_off ;            /* offset in m_data */

    u_int        sm_len ;            /* len of data */

#ifdef    PCI

    int        sm_use_count ;

    char        sm_data[M_SIZE] ;

} ;

typedef struct s_mbuf SMbuf ;

/* mbuf head, to typed data */

/* 得到s_mbuf中的資料轉換成指定的類型t */

#define    smtod(x,t)    ((t)((x)->sm_data + (x)->sm_off))

/* 這個宏沒有被别的地方調用,用途是将data指定偏移位址o的指針轉為類型t */

#define    smtodoff(x,t,o)    ((t)((x)->sm_data + (o)))

通過查詢SMbuf在源代碼中的引用,可以看出s_mbuf在linux2.6中的用途遠沒有mbuf在linux中廣泛——linux2.4中,mbuf負責了核心中的存儲器緩存。

那麼在linux2.6中,又由哪一個結構來承擔linux2.4中mbuf的作用——答案是sk_buff。

struct sk_buff {

    /*

These two members must be first. */

    /* 這兩個變量用于形成sk_buff的雙連結清單 */

    struct sk_buff        *next;

    struct sk_buff        *prev;

          /* 資料包到達的時間 */

    ktime_t            tstamp;

           /* 這個sk_buff被哪個sock擁有 */

    struct sock        *sk;

    /* 這個sk_buff到達的device或者要從哪個device發送 */

    struct net_device    *dev;

* This is the control buffer. It is free to use for every

* layer. Please put your private variables there. If you

* want to keep them across layers you have to do a skb_clone()

* first. This is owned by whoever has the skb queued ATM.

*/

    char            cb[48] __aligned(8);

           /* destination entry */

    unsigned long        _skb_refdst;

#ifdef CONFIG_XFRM

    struct    sec_path    *sp;

    /* len為實際資料長度,data_len為資料長度 */

    unsigned int        len,

                data_len;

    /* mac_len:資料鍊路層位址長度,hdr_len:克隆的skb可寫頭部的長度 */

    __u16            mac_len,

                hdr_len;

    union {

        __wsum        csum;

        struct {

            __u16    csum_start;

            __u16    csum_offset;

        };

    };

    /* 包的排隊優先級 */

    __u32            priority;

    kmemcheck_bitfield_begin(flags1);

    /*

           一些标志位:

           local_df:允許本地分片;

           nohdr:隻能引用其payload

    */

    __u8            local_df:1,

                cloned:1,

                ip_summed:2,

                nohdr:1,

                nfctinfo:3;

    __u8            pkt_type:3,

                fclone:2,

                ipvs_property:1,

                peeked:1,

                nf_trace:1;

    kmemcheck_bitfield_end(flags1);

    __be16            protocol;

    void            (*destructor)(struct sk_buff *skb);

#if defined(CONFIG_NF_CONNTRACK) ||defined(CONFIG_NF_CONNTRACK_MODULE)

    struct nf_conntrack    *nfct;

    struct sk_buff        *nfct_reasm;

#ifdef CONFIG_BRIDGE_NETFILTER

    struct nf_bridge_info    *nf_bridge;

          /* 由哪個interface到達的 */

    int            skb_iif;

#ifdef CONFIG_NET_SCHED

    __u16            tc_index;    /* traffic control index */

#ifdef CONFIG_NET_CLS_ACT

    __u16            tc_verd;    /* traffic control verdict */

    __u32            rxhash;

    kmemcheck_bitfield_begin(flags2);

    __u16            queue_mapping:16;

#ifdef CONFIG_IPV6_NDISC_NODETYPE

    __u8            ndisc_nodetype:2,

                deliver_no_wcard:1;

#else

    __u8            deliver_no_wcard:1;

    kmemcheck_bitfield_end(flags2);

0/14 bit hole */

#ifdef CONFIG_NET_DMA

    dma_cookie_t        dma_cookie;

#ifdef CONFIG_NETWORK_SECMARK

    __u32            secmark;

    /* 這個sk_buff被哪個sock擁有 */

        __u32        mark;

        __u32        dropcount;

    __u16            vlan_tci;

           /* 傳輸層報頭 */

    sk_buff_data_t        transport_header;

    /* 網絡層報頭 */

    sk_buff_data_t        network_header;

    /* 鍊路層報頭 */

    sk_buff_data_t        mac_header;

    sk_buff_data_t        tail;

    sk_buff_data_t        end;

    unsigned char        *head,

                *data;

    unsigned int        truesize;

    atomic_t        users;

};

今天隻能先寫到這裡,明天繼續分析sk_buff結構。其實在linux 2.6代碼中,每個變量的用途,注釋寫得很明白。

繼續閱讀