【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析

来源:互联网 发布:监控工程预算软件 编辑:程序博客网 时间:2024/05/16 18:15

【linux驱动分析】之dm9000驱动分析(一):dm9000原理及硬件分析 

【linux驱动分析】之dm9000驱动分析(二):定义在板文件中的资源和设备以及几个宏 

【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析 

【linux驱动分析】之dm9000驱动分析(四):net_device结构体 

【linux驱动分析】之dm9000驱动分析(五):另外几个重要的结构体 

【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现 

【linux驱动分析】之dm9000驱动分析(七):dm9000的卸载挂起和恢复以及打开和停止


源码分析
sk_buff_head和sk_buff定义在include/linux/skbuff.h中,下面是linux-2.6.38中的定义。
1、在内核中sk_buff是一个网络数据包,它是一个双向链表,而链表头就是sk_buff_head。
而sk_buff的内存布局可以分作3个段,第一个就是sk_buff自身,第二个是linear-data buff,第三个是paged-data buff(也就是skb_shared_info)。先来看一下sk_buff_head:
struct sk_buff_head {    /* These two members must be first. */    struct sk_buff    *next;    struct sk_buff    *prev;    __u32        qlen;    spinlock_t    lock;};
这里可以看到前两个域是和sk_buff一致的,而且内核的注释是必须放到最前面。这里的原因是: 

这使得两个不同的结构可以放到同一个链表中,尽管sk_buff_head要比sk_buff小巧的多。另外,相同的函数可以同样应用于sk_buff和sk_buff_head。 

然后qlen域表示了当前的sk_buff链上包含多少个skb。 

lock域是自旋锁。 2、sk_buff结构
  1 /**   2  *    struct sk_buff - socket buffer  3  *    @next: Next buffer in list  4  *    @prev: Previous buffer in list  5  *    @sk: Socket we are owned by  6  *    @tstamp: Time we arrived  7  *    @dev: Device we arrived on/are leaving by  8  *    @transport_header: Transport layer header  9  *    @network_header: Network layer header 10  *    @mac_header: Link layer header 11  *    @_skb_refdst: destination entry (with norefcount bit) 12  *    @sp: the security path, used for xfrm 13  *    @cb: Control buffer. Free for use by every layer. Put private vars here 14  *    @len: Length of actual data 15  *    @data_len: Data length 16  *    @mac_len: Length of link layer header 17  *    @hdr_len: writable header length of cloned skb 18  *    @csum: Checksum (must include start/offset pair) 19  *    @csum_start: Offset from skb->head where checksumming should start 20  *    @csum_offset: Offset from csum_start where checksum should be stored 21  *    @local_df: allow local fragmentation 22  *    @cloned: Head may be cloned (check refcnt to be sure) 23  *    @nohdr: Payload reference only, must not modify header 24  *    @pkt_type: Packet class 25  *    @fclone: skbuff clone status 26  *    @ip_summed: Driver fed us an IP checksum 27  *    @priority: Packet queueing priority 28  *    @users: User count - see {datagram,tcp}.c 29  *    @protocol: Packet protocol from driver 30  *    @truesize: Buffer size  31  *    @head: Head of buffer 32  *    @data: Data head pointer 33  *    @tail: Tail pointer 34  *    @end: End pointer 35  *    @destructor: Destruct function 36  *    @mark: Generic packet mark 37  *    @nfct: Associated connection, if any 38  *    @ipvs_property: skbuff is owned by ipvs 39  *    @peeked: this packet has been seen already, so stats have been 40  *        done for it, don't do them again 41  *    @nf_trace: netfilter packet trace flag 42  *    @nfctinfo: Relationship of this skb to the connection 43  *    @nfct_reasm: netfilter conntrack re-assembly pointer 44  *    @nf_bridge: Saved data about a bridged frame - see br_netfilter.c 45  *    @skb_iif: ifindex of device we arrived on 46  *    @rxhash: the packet hash computed on receive 47  *    @queue_mapping: Queue mapping for multiqueue devices 48  *    @tc_index: Traffic control index 49  *    @tc_verd: traffic control verdict 50  *    @ndisc_nodetype: router type (from link layer) 51  *    @dma_cookie: a cookie to one of several possible DMA operations 52  *        done by skb DMA functions 53  *    @secmark: security marking 54  *    @vlan_tci: vlan tag control information 55  */ 56  57 struct sk_buff { 58     /* These two members must be first. */ 59     struct sk_buff        *next; 60     struct sk_buff        *prev; 61  62     //表示这个skb被接收的时间。 63     ktime_t            tstamp; 64     //表示从属于那个socket,主要是被4层用到 65     struct sock        *sk; 66     /*这个表示一个网络设备,当skb为输出时它表示skb将要输出的设备,当接收时,它表示输入设备。 67      * 要注意,这个设备有可能会是虚拟设备(在3层以上看来) 68      */ 69     struct net_device    *dev; 70  71     /* 72      * This is the control buffer. It is free to use for every 73      * layer. Please put your private variables there. If you 74      * want to keep them across layers you have to do a skb_clone() 75      * first. This is owned by whoever has the skb queued ATM. 76      */ 77     char            cb[48] __aligned(8); 78     ///这里其实应该是dst_entry类型,不知道为什么内核要改为ul。这个域主要用于路由子系统。 79     //这个数据结构保存了一些路由相关信息  80     unsigned long        _skb_refdst; 81 #ifdef CONFIG_XFRM 82     struct    sec_path    *sp; 83 #endif 84     ///这个长度表示当前的skb中的数据的长度,这个长度即包括buf中的数据也包括切片的数据, 85     //也就是保存在skb_shared_info中的数据。这个值是会随着从一层到另一层而改变的。下面我们会对比这几个长度的。 86     unsigned int        len, 87     ///这个长度只表示切片数据的长度,也就是skb_shared_info中的长度 88                     data_len; 89     //链路层头部的长度 90     __u16            mac_len, 91     //这个主要用于clone的时候,它表示clone的skb的头的长度 92                 hdr_len; 93     //接下来是校验相关的域 94     union { 95         __wsum        csum; 96         struct { 97             __u16    csum_start; 98             __u16    csum_offset; 99         };100     };101     __u32            priority;102     kmemcheck_bitfield_begin(flags1);103     //首先是是否可以本地切片的标志。104     __u8            local_df:1,105     //为1说明头可能已被clone106                 cloned:1,107     //这个表示校验相关的一个标记,表示硬件驱动是否为我们已经进行了校验108                 ip_summed:2,109     //这个域如果为1,则说明这个skb的头域指针已经分配完毕,因此这个时候计算头的长度只需要head和data的差就可以了。110                 nohdr:1,111                 nfctinfo:3;112     //pkt_type主要是表示数据包的类型,比如多播,单播,回环等等113     __u8            pkt_type:3,114     //这个域是一个clone标记。主要是在fast clone中被设置,我们后面讲到fast clone时会详细介绍这个域115                 fclone:2,116     //ipvs拥有的域117                 ipvs_property:1,118     //这个包已经被查看过了119                 peeked:1,120     //netfilter使用的域。是一个trace 标记121                 nf_trace:1;122     kmemcheck_bitfield_end(flags1);123     __be16            protocol;124     //skb的析构函数,一般都是设置为sock_rfree或者sock_wfree125     void            (*destructor)(struct sk_buff *skb);126 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)127     struct nf_conntrack    *nfct;128 #endif129 #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED130     struct sk_buff        *nfct_reasm;131 #endif132 #ifdef CONFIG_BRIDGE_NETFILTER133     struct nf_bridge_info    *nf_bridge;134 #endif135     //接收设备的index136     int            skb_iif;137 138     //流量控制的相关域139 #ifdef CONFIG_NET_SCHED140     __u16            tc_index;    /* traffic control index */141 #ifdef CONFIG_NET_CLS_ACT142     __u16            tc_verd;    /* traffic control verdict */143 #endif144 #endif145 146     __u32            rxhash;147 148     kmemcheck_bitfield_begin(flags2);149     //多队列设备的映射,也就是说映射到那个队列150     __u16            queue_mapping:16;151 #ifdef CONFIG_IPV6_NDISC_NODETYPE152     __u8            ndisc_nodetype:2,153                 deliver_no_wcard:1;154 #else155     __u8            deliver_no_wcard:1;156 #endif157     __u8            ooo_okay:1;158     kmemcheck_bitfield_end(flags2);159 160     /* 0/13 bit hole */161 162 #ifdef CONFIG_NET_DMA163     dma_cookie_t        dma_cookie;164 #endif165 #ifdef CONFIG_NETWORK_SECMARK166     __u32            secmark;167 #endif168     union {169         //skb的标记170         __u32        mark;171         __u32        dropcount;172     };173     //vlan的控制tag174     __u16            vlan_tci;175     //传输层的头176     sk_buff_data_t        transport_header;177     //网络层的头178     sk_buff_data_t        network_header;179     //链路层的头180     sk_buff_data_t        mac_header;181     /* These elements must be at the end, see alloc_skb() for details.  */182     sk_buff_data_t        tail;183     sk_buff_data_t        end;184     unsigned char        *head,185                 *data;186     //这个表示整个skb的大小,包括skb本身,以及数据187     unsigned int        truesize;188     //skb的引用计数189     atomic_t        users;190 };
18 0
原创粉丝点击