您的位置:首页 > 理论基础 > 数据结构算法

sk_buff有关的几个重要的数据结构

2016-11-11 21:32 573 查看
1。sk_buff结构体

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

下面是他的定义,挺长

struct sk_buff {
/* These two members must be first. */
struct sk_buff      *next;
struct sk_buff      *prev;

ktime_t         tstamp;

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.
*/
char            cb[48] __aligned(8);

unsigned long       _skb_refdst;
#ifdef CONFIG_XFRM
struct  sec_path    *sp;
#endif
unsigned int        len,
data_len;
__u16           mac_len,
hdr_len;
union {
__wsum      csum;
struct {
__u16   csum_start;
__u16   csum_offset;
};
};
__u32           priority;
kmemcheck_bitfield_begin(flags1);
__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;
#endif
#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
struct sk_buff      *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info   *nf_bridge;
#endif

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;

__u16           queue_mapping;
kmemcheck_bitfield_begin(flags2);
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8            ndisc_nodetype:2;
#endif
__u8            ooo_okay:1;
__u8            l4_rxhash:1;
kmemcheck_bitfield_end(flags2);

/* 0/13 bit hole */

#ifdef CONFIG_NET_DMA
dma_cookie_t        dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32           secmark;
#endif
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;
/* These elements must be at the end, see alloc_skb() for details.  */
sk_buff_data_t      tail;
sk_buff_data_t      end;
unsigned char       *head,
*data;
unsigned int        truesize;
atomic_t        users;
};


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

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


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

#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif


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

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



char cb[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;

__u32       qlen;
spinlock_t  lock;
};


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

3。skb_shared_info结构体

struct skb_shared_info {
unsigned short  nr_frags;
unsigned short  gso_size;//尺寸
/* Warning: this field is not always filled in (UFO)! */
unsigned short  gso_segs;//顺序
unsigned short  gso_type;
__be32          ip6_frag_id;
__u8        tx_flags;
struct sk_buff  *frag_list;//分片的sk_buff列表
struct skb_shared_hwtstamps hwtstamps;//硬件时间戳

/*
* Warning : all fields before dataref are cleared in __alloc_skb()
*/
atomic_t    dataref;//使用计数

/* 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_t  frags[MAX_SKB_FRAGS];
};


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

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

#ifdef NET_SKBUFF_DATA_USES_OFFSET
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
return skb->head + skb->end;
}
#else
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
return skb->end;
}
#endif


可以看到如果用户没有自己使用偏移量,就是skb的end属性指针,也就是该信息存储在缓冲区之后。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐