本文分析基于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_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属性指针,也就是该信息存储在缓冲区之后。
下篇将看有关sk_buff的操作函数的实现。
分享到:
相关推荐
linux内核sk_buff结构体详解,从sk_buff结构到流程详细讲解sk_buff结构体
linux内核skb_buf相关操作介绍
很清楚的分析了一个数据包如何通过查询路由进入内核ipsec协议栈的处理、Linux 内核ipsec协议栈详细的加解密流程以及加解密完后如何将数据包发送出去。 文档中前半部分主要介绍一些关键的数据结构,及其相互之间的...
详细介绍linux内核网络模块中重要的结构体sk_buff
主要分析linux网络协议栈中SK_BUFF的实现
此Linux内核学习资料包中有Linux内核--网络栈实现分析(二)--数据包的传递过程(上).pdf Linux内核--网络栈实现分析(三)--驱动程序层+链路层(上).pdf Linux内核--网络栈实现分析(四)--网络层之IP协议(上)....
基于Linux内核的用户态网络协议栈的实现.pdf
linux-2.6.18内核基础上分析网络协议栈,适合初学者看
几个月之前做了关于Linux内核版本1.2.13网络栈的结构框架分析并实现了基于Netfilter的包过滤防火墙,这里以内核3.2.1内核为例来进一步分析,更全面的分析网络栈的结构。 1、先说一下sk_buff结构体 这个...
详解Linux协议栈的数据流向,SOCKET的操作流程,unicast multicast等等的区别。
LINUX-2.4.0内核网络栈实现源代码分析 LINUX-2.4.0内核网络栈实现源代码分析 LINUX-2.4.0内核网络栈实现源代码分析
linux内核TCP/IP协议栈分析(附含其它一些相关知识点,如系统启动流程)。从网络收集,本着有益分享的宗旨,低资源分提供下载(相较于某处资源分40而言)。
全面分析linux内核的网络协议栈,非常适合对linux网络协议栈源码的学习
详细描述了linux内核协议栈的实现原理及相关数据结构,为linux内核协议栈分析人员提供了重要参考。
《Linux内核网络栈源代码情景分析》主要对Linux1.2.13内核协议栈的全部源代码做了详细的分析,该版本所有代码都在一个文件夹中,每种协议的实现都只有一个文件与之对应,分析该版本源代码可以方便读者迅速掌握Linux...
linux内核--linux内核--linux内核--linux内核--linux内核经典书籍
linux-1.2.13内核网络栈实现源代码分析.pdf 带书签
Linux网络体系结构 Linux内核中网络协议的设计与实现,Linux网络体系结构 Linux内核中网络协议的设计与实现
第2~5章在介绍了实现网络体系结构、协议栈、设备驱动程序的两个最重要的数据结构sk_buff和net_device的基础上,展示了Linux内核中为网络设备驱动程序设计和开发而建立的系统构架,最后以两个实例来具体说明如何着手...