Linux内核–网络协议栈深入分析(一)–与sk

本文分析基于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结构体

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

下面是他的定义,挺长

struct sk_buff {/* These two members must be first. */struct sk_buff*next;struct sk_buff*prev;ktime_ttstamp;struct sock*sk;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. */charcb[48] __aligned(8);unsigned long_skb_refdst;#ifdef CONFIG_XFRMstructsec_path*sp;#endifunsigned intlen,data_len;__u16mac_len,hdr_len;union {__wsumcsum;struct {__u16csum_start;__u16csum_offset;};};__u32priority;kmemcheck_bitfield_begin(flags1);__u8local_df:1,cloned:1,ip_summed:2,nohdr:1,nfctinfo:3;__u8pkt_type:3,fclone:2,ipvs_property:1,peeked:1,nf_trace:1;kmemcheck_bitfield_end(flags1);__be16protocol;void(*destructor)(struct sk_buff *skb);#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)struct nf_conntrack*nfct;#endif#ifdef NET_SKBUFF_NF_DEFRAG_NEEDEDstruct sk_buff*nfct_reasm;#endif#ifdef CONFIG_BRIDGE_NETFILTERstruct nf_bridge_info*nf_bridge;#endifintskb_iif;#ifdef CONFIG_NET_SCHED__u16tc_index;/* traffic control index */#ifdef CONFIG_NET_CLS_ACT__u16tc_verd;/* traffic control verdict */#endif#endif__u32rxhash;__u16queue_mapping;kmemcheck_bitfield_begin(flags2);#ifdef CONFIG_IPV6_NDISC_NODETYPE__u8ndisc_nodetype:2;#endif__u8ooo_okay:1;__u8l4_rxhash:1;kmemcheck_bitfield_end(flags2);/* 0/13 bit hole */#ifdef CONFIG_NET_DMAdma_cookie_tdma_cookie;#endif#ifdef CONFIG_NETWORK_SECMARK__u32secmark;#endifunion {__u32mark;__u32dropcount;};__u16vlan_tci;sk_buff_data_ttransport_header;sk_buff_data_tnetwork_header;sk_buff_data_tmac_header;/* These elements must be at the end, see alloc_skb() for details.  */sk_buff_data_ttail;sk_buff_data_tend;unsigned char*head,*data;unsigned inttruesize;atomic_tusers;};

可以看到新版本内核中发生了很多变化,其中数据包的首部在早期版本是以union的形式定义的,例如mac_header的定义方式如下:

union{    struct ethhdr *ethernet;    unsigned char *raw;}mac;

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

#ifdef NET_SKBUFF_DATA_USES_OFFSETtypedef unsigned int sk_buff_data_t;#elsetypedef unsigned char *sk_buff_data_t;#endif

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

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

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

2、sk_buff_head结构体

struct sk_buff_head {/* These two members must be first. */struct sk_buff*next;struct sk_buff*prev;__u32qlen;spinlock_tlock;};

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

3、skb_shared_info结构体

struct skb_shared_info {unsigned shortnr_frags;unsigned shortgso_size;//尺寸/* Warning: this field is not always filled in (UFO)! */unsigned shortgso_segs;//顺序unsigned short  gso_type;__be32          ip6_frag_id;__u8tx_flags;struct sk_buff*frag_list;//分片的sk_buff列表struct skb_shared_hwtstamps hwtstamps;//硬件时间戳/* * Warning : all fields before dataref are cleared in __alloc_skb() */atomic_tdataref;//使用计数/* Intermediate layers must ensure that destructor_arg * remains valid until skb destructor */void *destructor_arg;/* must be last field, see pskb_expand_head() */skb_frag_tfrags[MAX_SKB_FRAGS];};

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

#define skb_shinfo(SKB)((struct skb_shared_info *)(skb_end_pointer(SKB)))
#ifdef NET_SKBUFF_DATA_USES_OFFSETstatic inline unsigned char *skb_end_pointer(const struct sk_buff *skb){return skb->head + skb->end;}#elsestatic inline unsigned char *skb_end_pointer(const struct sk_buff *skb){return skb->end;}#endif

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

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

有人要进来,有一些人不得不离开。

Linux内核–网络协议栈深入分析(一)–与sk

相关文章:

你感兴趣的文章:

标签云: