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

sk_buff详解(3)

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

{ } ?

通过了eth_type_trans后,skb->data指针指向网络层的头部,在netif_receive_skb里初始化nh.raw和h.raw:

skb->h.raw = skb->nh.raw = skb->data; skb->mac_len = skb->nh.raw - skb->mac.raw; netif_receive_skb ? packet_type->func() ? ip_rcv() ?

如果只是转发,不用处理到L4,只有发给本机的包才需要,在进入L4处理之前,ip_local_deliver_finish会把h.raw初始化为L4的头部: int ihl = skb->nh.iph->ihl*4;

__skb_pull(skb, ihl);

/* Point into the IP datagram, just past the header. */ skb->h.raw = skb->data;

return (struct ethhdr *)skb->mac.raw;

其他相关结构

skb_shared_info

当调用 alloc_skb() 构造 SKB 和 data buffer时,需要的 buffer 大小是这样计算的: data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);

除了指定的 size 以外,还包括一个 struct skb_shared_info 结构的空间大小。也就是说,当调用 alloc_skb(size) 要求分配 size 大小的 buffer 的时候,同时还创建了一个 skb_shared_info 。这个结构定义如下: struct skb_shared_info { };

“dataref”:skb的data区域(线性buffer)引用计数,即有多少个skb结构指向这块data区域(skb_clone时++),被分为两部分:高16bits用于描述skb->data中payload部分的引用计数(skb->nohdr = 1时才有效),低16bits用来描述整个skb->data的引用计数,如下: /* We divide dataref into two halves. The higher 16 bits hold references * to the payload part of skb->data. The lower 16 bits hold references to

atomic_t dataref;

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; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS];

* the entire skb->data. It is up to the users of the skb to agree on * where the payload starts. *

* All users must obey the rule that the skb->data reference count must be * greater than or equal to the payload reference count. *

* Holding a reference to the payload part means that the user does not * care about modifications to the header part of skb->data. */

#define SKB_DATAREF_SHIFT 16

#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)

“nr_frags”: “paged_data”计数,最多为MAX_SKB_FRAGS = 65536/PAGE_SIZE + 2(4k的PAGE_SIZE,为18)

“skb_frag_t frags[MAX_SKB_FRAGS]”:用来记录paged_data实际位置,包含page指针,在page中的offset,以及占用的size 。(可以有不同的skb指向同一个page中的不同offset和size,也可以指向相同的,由page里头的_count来代表引用计数) struct skb_frag_struct { };

“gso_size”,“gso_segs”,“gso_type”由“GSO”(Generic Segmentation Offload,或叫“TSO”,即TCP Segmentation Offload)功能使用 enum { };

“frag_list”:分片处理中,记录分片使用。

我们只要把 end 从 char* 转换成skb_shared_info* ,就能访问到这个结构 Linux 提供一个宏来做这种转换:

#define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end)) 那么,这个隐藏的结构用意何在?它至少有两个目的: 1、 用于管理 paged data 2、 用于管理分片

SKB_GSO_TCPV4 = 1 << 0, SKB_GSO_UDP = 1 << 1,

/* This indicates the skb is from an untrusted source. */ SKB_GSO_DODGY = 1 << 2,

/* This indicates the tcp segment has CWR set. */ SKB_GSO_TCP_ECN = 1 << 3, SKB_GSO_TCPV6 = 1 << 4, struct page *page; __u16 page_offset; __u16 size;

sk_buff_head和skb队列

协议栈处理中经常用到sk_buff的队列,队列头使用struct sk_buff_head来描述,如下: struct sk_buff_head { };

其中包含一个指示队列长度的qlen,和一个自旋锁lock用于不同的进程同时操作队列时的保护。 一个sk_buff队列如下图:

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

qlen;

spinlock_t lock;

sk_buff操作

下面对net/core/skbuff.c里调用EXPORT_SYMBOL导出的函数进行较为详细的分析,但仅限于每个函数本身完成的功能,具体调用的位置还得参考协议栈处理其他部分的代码。

EXPORT_SYMBOL(___pskb_trim); EXPORT_SYMBOL(__kfree_skb); EXPORT_SYMBOL(kfree_skb); EXPORT_SYMBOL(__pskb_pull_tail); EXPORT_SYMBOL(__alloc_skb); EXPORT_SYMBOL(__netdev_alloc_skb); EXPORT_SYMBOL(pskb_copy); EXPORT_SYMBOL(pskb_expand_head);

EXPORT_SYMBOL(skb_checksum); EXPORT_SYMBOL(skb_clone);

EXPORT_SYMBOL(skb_clone_fraglist); EXPORT_SYMBOL(skb_copy);

EXPORT_SYMBOL(skb_copy_and_csum_bits); EXPORT_SYMBOL(skb_copy_and_csum_dev); EXPORT_SYMBOL(skb_copy_bits); EXPORT_SYMBOL(skb_copy_expand); EXPORT_SYMBOL(skb_over_panic); EXPORT_SYMBOL(skb_pad);

EXPORT_SYMBOL(skb_realloc_headroom); EXPORT_SYMBOL(skb_under_panic); EXPORT_SYMBOL(skb_dequeue); EXPORT_SYMBOL(skb_dequeue_tail); EXPORT_SYMBOL(skb_insert); EXPORT_SYMBOL(skb_queue_purge); EXPORT_SYMBOL(skb_queue_head); EXPORT_SYMBOL(skb_queue_tail); EXPORT_SYMBOL(skb_unlink); EXPORT_SYMBOL(skb_append); EXPORT_SYMBOL(skb_split);

EXPORT_SYMBOL(skb_prepare_seq_read); EXPORT_SYMBOL(skb_seq_read); EXPORT_SYMBOL(skb_abort_seq_read); EXPORT_SYMBOL(skb_find_text);

EXPORT_SYMBOL(skb_append_datato_frags);

skb分配相关操作

__alloc_skb, alloc_skb,alloc_skb_fclone, __dev_alloc_skb,

__netdev_alloc_skb,sock_alloc_send_pskb, sock_alloc_send_skb, sk_stream_alloc_skb, sk_stream_alloc_pskb, sock_wmalloc等

基本上内核里所有的skb分配都是通过直接调用__alloc_skb或相应的包装函数来完成,下面先对__alloc_skb进行分析,然后再稍微讨论几个包装函数。 1. 输入参数:跟内存分配/相关的暂时不讨论;

a) size:指的是线性buffer的长度,即skb->end - skb->head; b) gfp_mask:allocation_mask,跟内存分配的优先级等相关;

c) fclone:从skbuff_fclone_cache还是skbuff_head_cache分配skb结构,用于快速clone;

d) node:用于分配内存的numa node

2. 具体操作:

a) 分配skb结构本身:根据fclone选择cache,然后把gfp_mask&~__GFP_DMA,得到

skb,分配失败则退出;

b) 分配skb->data线性buffer区:

i. ii. iii.

size = SKB_DATA_ALIGN(size); 根据L1_CACHE_BYTES(X86上为128 bytes)调整大小,补齐为128的整数倍;

kmalloc的内存大小为size + sizeof(struct skb_shared_info) 初始化skb成员变量

1. truesize之前的都置为0;

2. truesize = SKB_DATA_ALIGN(size) + sizeof(struct sk_buff),并不包

含skb_shared_info; 3. users置为1,head/data/tail指向线性buffer的开始;end指向结束; 4. 根据fclone设置skb->fclone,以及对应的兄弟skb及fclone_ref;

iv. skb_shared_info初始化 1. dataref置为1; 2. 其他置为0或NULL;

3. 返回值:skb或data内存分配失败,返回NULL;否则返回创建的sk_buff指针。

常见的__alloc_skb包装函数包括:

? alloc_skb和alloc_fclone_skb:原型如下,一个fclone,另一个不理;numa node

都是-1;

static inline struct sk_buff *alloc_skb(unsigned int size,gfp_t priority) {

return __alloc_skb(size, priority, 0, -1);

}

static inline struct sk_buff *alloc_skb_fclone(unsigned int size,gfp_t priority) { } ?

dev_alloc_skb和__dev_alloc_skb:一般是网卡驱动分配用于接收缓存的skb,length会加上NET_SKB_PAD,调用完alloc_skb后,会通过skb_reserve在线性buffer的头部保留一块长度为NET_SKB_PAD的区域,有关NET_SKB_PAD和NET_IP_ALIGN的说明,可以参见内核代码中的注释; /*

* CPUs often take a performance hit when accessing unaligned memory * locations. The actual performance hit varies, it can be small if the * hardware handles it or large if we have to take an exception and fix it * in software. *

* Since an ethernet header is 14 bytes network drivers often end up with * the IP header at an unaligned offset. The IP header can be aligned by * shifting the start of the packet by 2 bytes. Drivers should do this * with:

*

* skb_reserve(NET_IP_ALIGN); *

return __alloc_skb(size, priority, 1, -1);

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

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