77范文网 - 专业文章范例文档资料分享平台

sk_buff详解

来源:网络收集 时间:2019-04-10 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

sk_buff详解

杨毅(yangyi@http://www.njliaohua.com/) 2008-12-31

概述

本文对Linux内核网络子系统中的核心数据结构sk_buff进行分析,以2.6.21-7的内核来本文档将回答以下几个与sk_buff有关的问题:

含skb_headlen(),skb_pagelen()等,分别在何种环境下使用?

2. 几个引用计数的区别:skb->users, skb->cloned, skb_shared_info->dataref; 3. 几个指针的关系和移动:head/data/tail/end, h.raw, nh.raw, mac.raw; 4. 与skb共享复制有关的几个操作有什么区别?

5. skb分配,释放的实现细节;网络子系统中会在哪些地方分配skb,有哪些区别? 6. skb的数据区分为哪几部分?为什么需要这么多种类,分别都应用在何种场景?互相之间的

转化关系如何?

分析,其余版本可能存在差别。

1. 几个长度有关的成员变量:skb->len, skb->data_len, skb->truesize之间的关系,还包

struct sk_buff成员变量

如下变量的区别需要注意: struct net_device *dev; int iif;

dev和iif

这几个变量都用于跟踪与 packet 相关的 device。由于 packet 在接收的过程中,可能会经过多个 virtual driver 处理,因此需要几个变量。

接收数据包的时候, dev 和 iif 都指向最初的 interface,此后,如果需要被 virtual driver 处理,那么 dev 会发生变化,而 iif 始终不变。

len,data_len, mac_len, truesize

unsigned int

len, data_len, mac_len; truesize;

unsigned int

‘len’ 表示此 SKB 管理的 Data Buffer 中数据的总长度;

如上图,一个skb结构描述的内存区域包含几个部分: 1)sk_buff结构体本身;

2)线性buffer区域,由skb->head,data,tail,end等几个指针来描述,并且包含skb_shared_info结构;

3)“paged data”:通过skb_shared_info结构管理的一组保存在 page 中的数据; 4)skb_shared_info(skb)->frag_list队列包含分片的skb队列,队列成员是skb链表指针。

skb有效数据区的长度使用skb->len记录,一共包括三个部分:

skb->len = skb_headlen()(?== linear_buffer_len) + skb->data_len 1. 从skb->data开始到skb->tail结束的线性buffer区,这一部分的长度可以使用skb_headlen()获得; 线性区有效数据长度:

linear_buffer_len = skb->tail - skb->data;(alloc_skb时为0) ?== skb_headlen() 线性区总长度:skb_data_len = skb->end - skb->head;(不包括skb_shared_info)

2. skb_shared_info(skb)->frags[]数组里包含的“paged data”,长度为所有frags->size的和;这一部分加上1中的数据长度可以使用skb_pagelen()获得;“paged data”占用长度: page_data_len = sum(skb_shared_info->frags[i]->size); skb_pagelen() = skb_headlen() + page_data_len

3. skb_shared_info(skb)->frag_list链表里所有skb的数据区长度(len),这一部分的长度加上2中的长度记录在skb->data_len里。

skb->data_len = page_data_len + sum(skb_shared_info->frag_list->len)

truesize = sizeof(struct sk_buff) + SKB_DATA_ALIGN(skb_data_len)+ skb->data_len (alloc_skb时为sizeof(struct sk_buff) + SKB_DATA_ALIGN(size)) len, data_len, truesize是否包含frag_list里的长度?? ? 是!

skb->truesize这个成员变量衡量的是整个skb结构所占的内存大小(为啥不包含struct sk_shared_info??),在“ip分片处理”和“socket的读写缓存分配”中使用,前者将在以后的ip层处理相关文档中详细说明,后者挑选几个典型应用如下: ?

skb_set_owner_w,skb_set_owner_r:datagram的skb和socket的写,读缓存联系起来: sock_hold(sk); skb->sk = sk;

skb->destructor = sock_wfree/sock_rfree;

atomic_add(skb->truesize, &sk->sk_wmem_alloc/ sk_rmem_alloc); ?

sock_wfree和sock_rfree:在kfree_skb时或skb_orphan时调用skb的destructor函数: struct sock *sk = skb->sk;

atomic_sub(skb->truesize, &sk-> sk_wmem_alloc/sk_rmem_alloc); ?

sock_queue_rcv_skb,sock_queue_err_skb在把收到的或者错误的skb放入队列中时会对socket接收缓存,skb->truesize及当前已经占用的读内存进行判断: if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=

(unsigned)sk->sk_rcvbuf)

return -ENOMEM;

而发送时的判断是调用比较复杂:sk_stream_alloc_pskb? sk_stream_wmem_schedule static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, { ??

skb = alloc_skb_fclone(size + hdr_len, gfp); }

static inline int sk_stream_wmem_schedule(struct sock *sk, int size) { }

跟这几个长度有关的几个inline函数如下: ?

skb_is_nonlinear():return skb->data_len; 即是否包含“paged data”或frag_list

return size <= sk->sk_forward_alloc || sk_stream_mem_schedule(sk, size, 0); if (skb) { }

skb->truesize += mem;

if (sk_stream_wmem_schedule(sk, skb->truesize)) { }

__kfree_skb(skb);

skb_reserve(skb, hdr_len); return skb;

int size, int mem, gfp_t gfp)

??

? ?

skb_headlen():return skb->len - skb->data_len; 即只包含线性区域实际使用长度,或“有效长度”;(??与skb->tail - skb->data的差别??)

skb_pagelen():所有“paged data”长度之和,再加上线性区域实际使用长度; static inline int skb_pagelen(const struct sk_buff *skb) { }

int i, len = 0;

for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)

len += skb_shinfo(skb)->frags[i].size; return len + skb_headlen(skb);

? ? ? ?

skb_push, skb_pull, skb_reserve, skb_put这几个函数移动data或tail指针,都会更改skb->len

skb_trim:修改skb->len的值,并且skb->tail = skb->data+len skb_headroom:skb->data - skb->head;

skb_tailroom:如果没有paged data或fragment list,为skb->end - skb->tail,否则为0

‘mac_len’ 指 MAC 头的长度。目前,它只在 IPSec 解封装的时候被使用。将来可能从 SKB 结构中去掉。

cloned, ip_summed, nohdr, users, dataref等

__u8

local_df:1,

cloned:1, ip_summed:2, nohdr:1, nfctinfo:3;

atomic_t }

users;

struct skb_shared_info {

atomic_t dataref; ??

“local_df”在IPv4中使用,设为1后代表允许对已经分片的数据包进行再次分片,在IPSec等情况下使用;

“ip_summed”代表网卡是否支持计算接收包checksum,在老版本kernel里可取值如下: ? ?

CHECKSUM_NONE:代表网卡不算checksum;

CHECKSUM_HW:代表网卡支持硬件计算checksum(对L4 head + payload的校验),并且已经将计算结果复制给skb->csum,软件需要计算“伪头(pseudo header)”的校验和,与skb->csum相加得到L4的结果; ?

CHECKSUM_UNNECESSARY:网卡已经计算并校验过整个包的校验,包括伪头,软件无需再次计算,一般用于loopback device。 本版本的内核里是如下定义,并有详细的注释:

#define CHECKSUM_NONE 0

#define CHECKSUM_PARTIAL 1

#define CHECKSUM_UNNECESSARY 2 #define CHECKSUM_COMPLETE 3

/* A. Checksumming of received packets by device. *

* NONE: device failed to checksum this packet. * *

* UNNECESSARY: device parsed packet and wouldbe verified checksum. *

skb->csum is undefined.

* It is bad option, but, unfortunately, many of vendors do this. * Apparently with secret goal to sell you new device, when you * will add new protocol to your host. F.e. IPv6. 8) *

* COMPLETE: the most generic way. Device supplied checksum of _all_ * the packet as seen by netif_rx in skb->csum.

* NOTE: Even if device supports only some protocols, but * is able to produce some skb->csum, it MUST use COMPLETE, * not UNNECESSARY. *

* B. Checksumming on output. *

* NONE: skb is checksummed by protocol or csum is not required. *

* PARTIAL: device is required to csum packet as seen by hard_start_xmit * from skb->h.raw to the end and to record the checksum * at skb->h.raw+skb->csum. *

* Device must show its capabilities in dev->features, set * at device setup time.

* NETIF_F_HW_CSUM - it is clever device, it is able to checksum *

everything.

* NETIF_F_NO_CSUM - loopback or reliable single hop media. * NETIF_F_IP_CSUM - device is dumb. It is able to csum only * * * *

* Any questions? No questions, good. */

“nohdr”:The 'nohdr' field is used in the support of TCP Segmentation Offload ('TSO' for short). Most devices supporting this feature need to make some minor modifications to the TCP and IP headers of an outgoing packet to get it in the right form for the hardware

--ANK

TCP/UDP over IPv4. Sigh. Vendors like this

way by an unknown reason. Though, see comment above about CHECKSUM_UNNECESSARY. 8) skb->csum is undefined.

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库sk_buff详解在线全文阅读。

sk_buff详解.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/zonghe/583952.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: