Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
来源:互联网 发布:电脑线转换成电话端口 编辑:程序博客网 时间:2024/06/10 19:58
本文分析基于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{
- 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的操作函数的实现。
0 0
- Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- 网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- sk_buff有关的几个重要的数据结构
- Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数
- Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数
- Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数
- 网络协议栈深入分析(二)--sk_buff的操作函数
- linux网络协议栈分析——重要数据结构及其关系(socket、sock、sk_buff)
- linux内核sk_buff的结构分析
- linux内核sk_buff的结构分析
- Linux内核sk_buff的结构分析
- linux内核sk_buff的结构分析
- linux内核sk_buff的结构分析
- linux内核sk_buff的结构分析
- linux内核sk_buff的结构分析
- 省市数据库
- 1111
- 数据库管理系统实现与设计
- 如何在面试中发现优秀程序员(转)
- MD5加密
- Linux内核--网络协议栈深入分析(一)--与sk_buff有关的几个重要的数据结构
- php实现在指定数组中取指定数量不重复的子集合
- ORACLE 误删数据的恢复[转]
- 百度语音合成(TTS)SDK使用方法
- DVSDK中的 Buffer_Handle结构
- 构建二叉树
- Spring下往Oracle中插入BLOB数据
- 618京东腾讯合体欺负阿里 用了什么招
- MapReduce实现大矩阵乘法