且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

struct s_mbuf与struct sk_buff

更新时间:2022-09-01 18:14:21

struct s_mbuf与struct sk_buff
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以***拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客: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
#endif

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 ;
#endif
    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;

#endif

    /* 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;

#endif

#ifdef CONFIG_BRIDGE_NETFILTER

    struct nf_bridge_info    *nf_bridge;

#endif

 

          /* 由哪个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 */

#endif

#endif

 

    __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;

#endif

    kmemcheck_bitfield_end(flags2);

 

    /* 0/14 bit hole */

 

#ifdef CONFIG_NET_DMA

    dma_cookie_t        dma_cookie;

#endif

#ifdef CONFIG_NETWORK_SECMARK

    __u32            secmark;

#endif

    /* 这个sk_buff被哪个sock拥有 */

    union {

        __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代码中,每个变量的用途,注释写得很明白。