12.4.3  sk_buff数据结构的核心内容

sk_buff 数据结构中包含了一些指针和长度信息,从而可让协议层以标准的函数或方法对应用程序的数据进行处理,其定义于include/linux/skbuff.h中:

struct sk_buff {

         /* These two members must be first. */

        struct sk_buff  * next;       /* Next buffer in list*/                         

        struct sk_buff  * prev;        /* Previous buffer in list*/                     

 

         struct sk_buff_head * list;      /* List we are on */                             

          struct sock     *sk;           /* Socket we are owned by */                     

              struct timeval  stamp;                  /* Time we arrived */                            

struct net_device       *dev;         /* Device we arrived on/are leaving by  */

 

         /* Transport layer header */

       union

        {

                struct tcphdr   *th;

                struct udphdr   *uh;

                struct icmphdr  *icmph;

                struct igmphdr  *igmph;

                struct iphdr    *ipiph;

                 struct spxhdr   *spxh;

                 unsigned char   *raw;

         } h;

 

         /* Network layer header */

         union

         {

                struct iphdr    *iph;

                struct ipv6hdr  *ipv6h;

                struct arphdr   *arph;

                struct ipxhdr   *ipxh;

                 unsigned char   *raw;

        } nh;

 

        /* Link layer header */

         union

         {      

                 struct ethhdr   *ethernet;

                 unsigned char   *raw;

         } mac;

 

        struct  dst_entry *dst;

 

        /*

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

 

     unsigned int    len;          /* Length of actual data*/                       

     unsigned int    data_len;

     unsigned int    csum;             /* Checksum   */                                 

     unsigned char   __unused,       /* Dead field, may be reused  */                 

  cloned, /* head may be cloned (check refcnt to be sure). */

                  pkt_type,         /* Packet class   */                            

                 ip_summed;        /* Driver fed us an IP checksum    */            

    __u32           priority;      /* Packet queueing priority */                   

         atomic_t        users;     /* User count - see datagram.c,tcp.c */          

         unsigned short  protocol;    /* Packet protocol from driver.  */              

         unsigned short  security;   /* Security level of packet */                   

        unsigned int    truesize;         /* Buffer size */                                

 

        unsigned char   *head;         /* Head of buffer  */                            

        unsigned char   *data;                  /* Data head pointer                           

        unsigned char   *tail;                  /* Tail pointer                                

    unsigned char   *end;                 /* End pointer  */                               

        void      (*destructor)(struct sk_buff *);  /* Destruct function  */         

  

  }

   该结构的示意图如图12.13所示:                

 

 

 

 

 

 

 

 

 

 

 

 

 

 

12.13 sk_buff  结构

每个 sk_buff 均包含一个数据块、四个数据指针以及两个长度字段。利用四个数据指针,各协议层可操纵和管理套接字缓冲区的数据,这四个指针的用途是:

head指向内存中数据区的起始地址。sk_buff 和相关数据块在分配之后,该指针的值是固定的。

data 指向协议数据的当前起始地址。该指针的值随当前拥有 sk_buff 的协议层的变化而变化。

tail指向协议数据的当前结尾地址。和 data 指针一样,该指针的值也随当前拥有 sk_buff 的协议层的变化而变化。

end指向内存中数据区的结尾。和 head 指针一样,sk_buff 被分配之后,该指针的值也固定不变。

 

sk_buff 有两个非常重要长度字段,len truesize,分别描述当前协议数据包的长度和数据缓冲区的实际长度。