zoukankan      html  css  js  c++  java
  • Linux内核网络协议栈深入分析(一)与sk_buff有关的几个重要的数据结构

    本文分析基于Linux Kernel 3.2.1

    原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7971463

    更多请查看专栏http://blog.csdn.net/column/details/linux-kernel-net.html

    作者:闫明


    几个月之前做了关于Linux内核版本1.2.13网络栈的结构框架分析并实现了基于Netfilter的包过滤防火墙,这里以内核3.2.1内核为例来进一步分析,更全面的分析网络栈的结构。


    1、先说一下sk_buff结构体

    这个结构体是套接字的缓冲区,详细记录了一个数据包的组成,时间、网络设备、各层的首部及首部长度和数据的首尾指针。

    下面是他的定义,挺长

    1. struct sk_buff {  
    2.     /* These two members must be first. */  
    3.     struct sk_buff      *next;  
    4.     struct sk_buff      *prev;  
    5.   
    6.     ktime_t         tstamp;  
    7.   
    8.     struct sock     *sk;  
    9.     struct net_device   *dev;  
    10.   
    11.     /* 
    12.      * This is the control buffer. It is free to use for every 
    13.      * layer. Please put your private variables there. If you 
    14.      * want to keep them across layers you have to do a skb_clone() 
    15.      * first. This is owned by whoever has the skb queued ATM. 
    16.      */  
    17.     char            cb[48] __aligned(8);  
    18.   
    19.     unsigned long       _skb_refdst;  
    20. #ifdef CONFIG_XFRM  
    21.     struct  sec_path    *sp;  
    22. #endif  
    23.     unsigned int        len,  
    24.                 data_len;  
    25.     __u16           mac_len,  
    26.                 hdr_len;  
    27.     union {  
    28.         __wsum      csum;  
    29.         struct {  
    30.             __u16   csum_start;  
    31.             __u16   csum_offset;  
    32.         };  
    33.     };  
    34.     __u32           priority;  
    35.     kmemcheck_bitfield_begin(flags1);  
    36.     __u8            local_df:1,  
    37.                 cloned:1,  
    38.                 ip_summed:2,  
    39.                 nohdr:1,  
    40.                 nfctinfo:3;  
    41.     __u8            pkt_type:3,  
    42.                 fclone:2,  
    43.                 ipvs_property:1,  
    44.                 peeked:1,  
    45.                 nf_trace:1;  
    46.     kmemcheck_bitfield_end(flags1);  
    47.     __be16          protocol;  
    48.   
    49.     void            (*destructor)(struct sk_buff *skb);  
    50. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)  
    51.     struct nf_conntrack *nfct;  
    52. #endif  
    53. #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED  
    54.     struct sk_buff      *nfct_reasm;  
    55. #endif  
    56. #ifdef CONFIG_BRIDGE_NETFILTER  
    57.     struct nf_bridge_info   *nf_bridge;  
    58. #endif  
    59.   
    60.     int         skb_iif;  
    61. #ifdef CONFIG_NET_SCHED  
    62.     __u16           tc_index;   /* traffic control index */  
    63. #ifdef CONFIG_NET_CLS_ACT  
    64.     __u16           tc_verd;    /* traffic control verdict */  
    65. #endif  
    66. #endif  
    67.   
    68.     __u32           rxhash;  
    69.   
    70.     __u16           queue_mapping;  
    71.     kmemcheck_bitfield_begin(flags2);  
    72. #ifdef CONFIG_IPV6_NDISC_NODETYPE  
    73.     __u8            ndisc_nodetype:2;  
    74. #endif  
    75.     __u8            ooo_okay:1;  
    76.     __u8            l4_rxhash:1;  
    77.     kmemcheck_bitfield_end(flags2);  
    78.   
    79.     /* 0/13 bit hole */  
    80.   
    81. #ifdef CONFIG_NET_DMA  
    82.     dma_cookie_t        dma_cookie;  
    83. #endif  
    84. #ifdef CONFIG_NETWORK_SECMARK  
    85.     __u32           secmark;  
    86. #endif  
    87.     union {  
    88.         __u32       mark;  
    89.         __u32       dropcount;  
    90.     };  
    91.   
    92.     __u16           vlan_tci;  
    93.   
    94.     sk_buff_data_t      transport_header;  
    95.     sk_buff_data_t      network_header;  
    96.     sk_buff_data_t      mac_header;  
    97.     /* These elements must be at the end, see alloc_skb() for details.  */  
    98.     sk_buff_data_t      tail;  
    99.     sk_buff_data_t      end;  
    100.     unsigned char       *head,  
    101.                 *data;  
    102.     unsigned int        truesize;  
    103.     atomic_t        users;  
    104. };  
    可以看到新版本内核中发生了很多变化,其中数据包的首部在早期版本是以union的形式定义的,例如mac_header的定义方式如下:

    1. union{  
    2.     struct ethhdr *ethernet;  
    3.     unsigned char *raw;  
    4. }mac;  

    这里是以指针的形式给出的

    1. #ifdef NET_SKBUFF_DATA_USES_OFFSET  
    2. typedef unsigned int sk_buff_data_t;  
    3. #else  
    4. typedef unsigned char *sk_buff_data_t;  
    5. #endif  

    这里主要说明下后面几个后面的四个属性的含义head、data、tail、end

    head是缓冲区的头指针,data是数据的起始地址,tail是数据的结束地址,end是缓冲区的结束地址。


    char cb[48] __aligned(8);中的48个字节是控制字段,配合各层协议工作,为每层存储必要的控制信息。


    2、sk_buff_head结构体

    1. struct sk_buff_head {  
    2.     /* These two members must be first. */  
    3.     struct sk_buff  *next;  
    4.     struct sk_buff  *prev;  
    5.   
    6.     __u32       qlen;  
    7.     spinlock_t  lock;  
    8. };  

    这个结构体比较简单,前面两个指针是用于和sk_buff结构串成双向链表,用于管理sk_buff双链表,qlen属性表示该链表中sk_buff的数目,lock是自旋锁。


    3、skb_shared_info结构体

    1. struct skb_shared_info {  
    2.     unsigned short  nr_frags;  
    3.     unsigned short  gso_size;//尺寸  
    4.     /* Warning: this field is not always filled in (UFO)! */  
    5.     unsigned short  gso_segs;//顺序  
    6.     unsigned short  gso_type;  
    7.     __be32          ip6_frag_id;  
    8.     __u8        tx_flags;  
    9.     struct sk_buff  *frag_list;//分片的sk_buff列表  
    10.     struct skb_shared_hwtstamps hwtstamps;//硬件时间戳  
    11.   
    12.     /* 
    13.      * Warning : all fields before dataref are cleared in __alloc_skb() 
    14.      */  
    15.     atomic_t    dataref;//使用计数  
    16.   
    17.     /* Intermediate layers must ensure that destructor_arg 
    18.      * remains valid until skb destructor */  
    19.     void *      destructor_arg;  
    20.   
    21.     /* must be last field, see pskb_expand_head() */  
    22.     skb_frag_t  frags[MAX_SKB_FRAGS];  
    23. };  


    该类型用来管理数据包分片信息,通过宏可以表示与skb的关系

    1. #define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB)))  

    1. #ifdef NET_SKBUFF_DATA_USES_OFFSET  
    2. static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)  
    3. {  
    4.     return skb->head + skb->end;  
    5. }  
    6. #else  
    7. static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)  
    8. {  
    9.     return skb->end;  
    10. }  
    11. #endif  

    可以看到如果用户没有自己使用偏移量,就是skb的end属性指针,也就是该信息存储在缓冲区之后。


    下篇将看有关sk_buff的操作函数的实现。

  • 相关阅读:
    BZOJ2821 作诗(Poetize) 【分块】
    BZOJ2724 蒲公英 【分块】
    Codeforces 17E Palisection 【Manacher】
    BZOJ2565 最长双回文串 【Manacher】
    Codeforces 25E Test 【Hash】
    CODEVS3013 单词背诵 【Hash】【MAP】
    HDU2825 Wireless Password 【AC自动机】【状压DP】
    HDU2896 病毒侵袭 【AC自动机】
    HDU3065 病毒侵袭持续中【AC自动机】
    HDU2222 Keywords Search 【AC自动机】
  • 原文地址:https://www.cnblogs.com/wangfengju/p/6173194.html
Copyright © 2011-2022 走看看