struct sk_buff与struct socket及struct sock 结构体分析
sk_buff是Linux网络协议栈最重要的数据结构之一,该数据结构贯穿于整个数据包处理的流程。由于协议采用分层结构,上层向下层传递数据时需要增加包头,下层向上层数据时又需要去掉包头。sk_buff中保存了L2,L3,L4层的头指针,这样在层传递时只需要对数据缓冲区改变头部信息,并调整sk_buff中的指针,而不需要拷贝数据,这样大大减少了内存拷贝的需要。
/** * struct sk_buff - socket buffer* @next: Next buffer in list* @prev: Previous buffer in list* @tstamp: Time we arrived* @sk: Socket we are owned by* @dev: Device we arrived on/are leaving by* @cb: Control buffer. Free for use by every layer. Put private vars here* @_skb_refdst: destination entry (with norefcount bit)* @sp: the security path, used for xfrm* @len: Length of actual data* @data_len: Data length* @mac_len: Length of link layer header* @hdr_len: writable header length of cloned skb* @csum: Checksum (must include start/offset pair)* @csum_start: Offset from skb->head where checksumming should start* @csum_offset: Offset from csum_start where checksum should be stored* @priority: Packet queueing priority* @local_df: allow local fragmentation* @cloned: Head may be cloned (check refcnt to be sure)* @ip_summed: Driver fed us an IP checksum* @nohdr: Payload reference only, must not modify header* @nfctinfo: Relationship of this skb to the connection* @pkt_type: Packet class* @fclone: skbuff clone status* @ipvs_property: skbuff is owned by ipvs* @peeked: this packet has been seen already, so stats have been* done for it, don't do them again* @nf_trace: netfilter packet trace flag* @protocol: Packet protocol from driver* @destructor: Destruct function* @nfct: Associated connection, if any* @nfct_reasm: netfilter conntrack re-assembly pointer* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c* @skb_iif: ifindex of device we arrived on* @tc_index: Traffic control index* @tc_verd: traffic control verdict* @rxhash: the packet hash computed on receive* @queue_mapping: Queue mapping for multiqueue devices* @ndisc_nodetype: router type (from link layer)* @ooo_okay: allow the mapping of a socket to a queue to be changed* @l4_rxhash: indicate rxhash is a canonical 4-tuple hash over transport* ports.* @wifi_acked_valid: wifi_acked was set* @wifi_acked: whether frame was acked on wifi or not* @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS* @dma_cookie: a cookie to one of several possible DMA operations* done by skb DMA functions* @secmark: security marking* @mark: Generic packet mark* @dropcount: total number of sk_receive_queue overflows* @vlan_tci: vlan tag control information* @inner_transport_header: Inner transport layer header (encapsulation)* @inner_network_header: Network layer header (encapsulation)* @transport_header: Transport layer header* @network_header: Network layer header* @mac_header: Link layer header* @tail: Tail pointer* @end: End pointer* @head: Head of buffer* @data: Data head pointer* @truesize: Buffer size* @users: User count - see {datagram,tcp}.c*/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_XFRMstruct sec_path *sp;
#endifunsigned 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_NEEDEDstruct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTERstruct nf_bridge_info *nf_bridge;
#endifint skb_iif;__u32 rxhash;__u16 vlan_tci;#ifdef CONFIG_NET_SCHED__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT__u16 tc_verd; /* traffic control verdict */
#endif
#endif__u16 queue_mapping;kmemcheck_bitfield_begin(flags2);
#ifdef CONFIG_IPV6_NDISC_NODETYPE__u8 ndisc_nodetype:2;
#endif__u8 pfmemalloc:1;__u8 ooo_okay:1;__u8 l4_rxhash:1;__u8 wifi_acked_valid:1;__u8 wifi_acked:1;__u8 no_fcs:1;__u8 head_frag:1;/* Encapsulation protocol and NIC drivers should use* this flag to indicate to each other if the skb contains* encapsulated packet or not and maybe use the inner packet* headers if needed*/__u8 encapsulation:1;/* 7/9 bit hole (depending on ndisc_nodetype presence) */kmemcheck_bitfield_end(flags2);#ifdef CONFIG_NET_DMAdma_cookie_t dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK__u32 secmark;
#endifunion {__u32 mark;__u32 dropcount;__u32 reserved_tailroom;};sk_buff_data_t inner_transport_header;sk_buff_data_t inner_network_header;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;
};
struct sk_buff {//介绍
struct sk_buff *next *prev;//双向链表指针
ktime_t tstamp ;//时间撮
struct sock *sk; //对应于传输层,标示属于哪个socket ?
struct net_device *dev; //数据来自或者发送自哪个设备
char cb[48];//控制信息buffer,在每个层都可以用,并且目前为止足够大
int len; 实际总长度
int data_len; 数据的长度 //也许是paged的data
__u16 mac_len; 数据链路层头的长度
__u16 hdr_len; writable header length of cloned skb
sk_buff_data_t transport_header; 传输层头指针
sk_buff_data_t network_header; 网络层头指针
sk_buff_data_t mac_header; 数据链路层头
unsigned char *head; //buffer 头
unsigned char *data; 数据头
sk_buff_data_t tail; 数据结尾
sk_buff_data_t end; buffer 结尾
unsigned int truesize; //bufffer 大小
cloned 是不是cloned
mark 数据包mark
destructor 销毁函数指针
pkt_type : 根据二层头确定的包信息
__be16 protocol : 三层协议 IP ARP 等,用于和全局数组qtype_base中的数据对比,该数组可以通过dev_add_pack()注册.
}
由于该结构将用于各个层,内核提供了一系列的sk_buff的操作函数
skb_put() 减小tailroom,buffer下后扩展
skb_push() 减小headroom,buffer向上扩张
skb_trim() cut buffer到一个长度
skb_pull 从数据头cut一定长度的数据
skb_reserve 增大headroom,减少tailroom,只能用于buffer为空时
skb_headroom headroom的大小
skb_tailroom tailroom的太小
alloc_skb() 分配一个sk_buff结构及buffer区域
kfree_slb() reference 减一,并且free skb和buffer如果不再有引用
dev_alloc_skb() 方便接收数据的sk_buff的分配函数
dev_free_skb()
skb_shinfo() 获得和sk_buff 一块分配的struct skb_shared_info
skb_clone() //复制sk_buff ,但是buffer不变
pskb_copy() //拷贝sk_buff和私有的头部,常用于需要修改sk_buff的头部时
skb_copy() //完全拷贝
skb_queue_head_init()
skb_queue_head()
skb_queue_tail()
skb_dequeue_head()
skb_dequeue_tail()
skb_queue_purge() //list 清空
skb_queue_walk() //遍历list用
/** kmemcheck_bitfield_begin(type); unsigned long flags; struct socket_wq *wq; struct file *file; |
代码中的注释对于每一个变量说的都很清楚——看到这里,我先感叹一下,linux2.6的结构体的注释比老版本要清楚的多。到目前为止,我所看到的关键的结构体,都有清晰的注释。我们可以看出struct socket中的sock变量,是socket变量的工作核心。
struct sock { }; |
其中,sk_rcvbuf和sk_sendbuf分别是接收和发送缓存的字节数。
struct sk_buff_head { __u32 qlen; |
可以看出socket的接收和发送缓存是使用一个双链表将sk_buff组织起来的。
struct sk_buff与struct socket及struct sock 结构体分析相关推荐
- 网络协议栈3:sock结构体
sock结构体是我们在网络编程中遇到的第一个庞大的结构体 struct sock { struct options *opt;/*IP选项缓存于此处*/ volatile unsi ...
- 三、初识Socket套接字结构体
一.初识Socket套接字结构体 1.通用套接字结构体类型 struct sockaddr{sa_family_t sa_family; //协议簇char sa_data[14]; //协议簇数据} ...
- linux sock结构体,struct socket结构体详解
在内核中为什么要有struct socket结构体呢? struct socket结构体的作用是什么? 下面这个图,我觉得可以回答以上两个问题. 由这个图可知,内核中的进程可以通过使用struct ...
- C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)
示例: typedef struct _user {char name[20];char sex[20];int age;struct list_head mylist;//自定义结构体里保存双向循环 ...
- socket编程之addrinfo结构体与getaddrinfo函数
1. 概述 IPv4中使用gethostbyname()函数完成主机名到地址解析,这个函数仅仅支持IPv4,且不允许调用者指定所需地址类型的任何信息,返回的结构只包含了用于存储IPv4地址的空间.IP ...
- C# Socket 入门5 UPD 结构体 与 C++ 通信
这篇文章本来是星期五晚写好了, 因6日去旅游了, 没来得急发上来 1. 同样, 我们先看看这一个比简单的 结构体 代码 using System; using System.Collections.G ...
- struct sk_buff结构体详解
struct sk_buff是linux网络系统中的核心结构体,linux网络中的所有数据包的封装以及解封装都是在这个结构体的基础上进行. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- 非常详细的详谈struct sk_buff
非常详细的详谈struct sk_buff 排版太慢 难看的话可以下载WOR文档 专门详解struct_sk_buff 链接: http://pan.baidu.com/s/1gf8VNKR 密码: ...
- 内核中用于数据接收的结构体struct msghdr以及iovec介绍
我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用send ...
最新文章
- Strategy_Level1
- VC++ 单文档的状态栏编程、CEditView类实现编辑器功能、编辑框显示行号列号
- 外国人居留证办理手续
- mysql udf提权_三分钟解析postgresql提权
- 河南省多校连萌(一) E题【kruskal】
- BZOJ 1901 Zju2112 Dynamic Rankings 题解
- 同济版《线性代数》引争议,从清华改用MIT数学课程看中美数学教育差距!
- [经验教程]Windows电脑上移动电信联通光宽带如何测速电信光纤200m宽带测速多少正常?
- ubuntu下使用CPU频率控制
- 【调剂】长江大学张菲菲教授招收硕士生
- go语言命令入门之env(操作环境信息)
- Parsed mapper file:项目启动不起来
- android微信认证失败怎么办,微信登陆好友头像验证失败该怎么办?
- springBoot redis开发的Java快递代拿系统(含人脸识别,验证码登录)
- 天津理工大学计算机最牛导师,孟祥太_天津理工大学研究生导师信息
- MySQL-实操:部门、员工信息与管理
- 计算机编程语言及C语言简介,编程语言基础:C语言
- 单片机教学打铃控制器C语言
- 文件未上传成功再次点击上传报错问题处理
- Google新动作频出 Google Trends发布
热门文章
- torchvision resize 指定生成图片的尺寸
- 解决seaborn绘制热力图使用科学记数法
- 复制网页中的表格格式后导入到excel、markdown、数据库、json中,并转换表格格式
- python 数组打包_Python:打包多字节数组
- [洛谷P3292] [SCOI2016]幸运数字
- 《神经网络和深度学习》系列文章五:用简单的网络结构解决手写数字识别
- Hibernate学习笔记--映射配置文件详解
- HTC ThunderBolt无法打开3G问题解决方法
- 在WinForm中使用Web Service来实现软件自动升级
- ArcGIS的BLOB字段与Access数据库BLOB字段的交换