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

sk_buff详解(2)

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

to process. We do not want these modifications to be seen by packet sniffers and the like. So we use this 'nohdr' field and a special bit in the data area reference count to keep track of whether the device needs to replace the data area before making the packet header modifications.

简单来说,nohdr代表了skb_shared_info里的dataref有没有被分成两部分: ? ?

nohdr = 0:dataref代表整个skb数据区的引用计数;

nohdr = 1:dataref的高16bits代表skb数据区“payload部分”的引用计数,低16bits代表整个skb数据区的引用计数。

与之相关的函数有:skb_header_cloned(), skb_header_release()等。

“cloned”代表skb是否被clone,为了能迅速的引用一个 SKB 的数据,当 clone 一个已存在的 SKB 时,会产生一个新的 SKB,但是这个 SKB 会共享已有 SKB 的数据区。当一个 SKB 被 clone 后,原来的 SKB 和新的 SKB 结构中,‘cloned’都要被设置为1。

“users”:是sk_buff结构本身的引用计数,在kfree_skb时会先先使用原子操作对users计数-1,如果=0,才调用__kfree_skb真正去释放skb。 ? ?

skb_shared()检查skb->users是否为1;

skb_shared_check():如果skb->users > 1,则clone一个新的。

有关dataref,clone,users这些引用计数的区别和应用场景请见后续的“skb共享复制相关操作”一节。

“nfctinfo”:用于netfilter子系统中的conntrack模块记录连接状态,可取值为enum变量: enum ip_conntrack_info {

/* Part of an established connection (either direction). */ */ */ };

IP_CT_NEW, IP_CT_IS_REPLY,

IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 /* >= this indicates reply direction */

/* Number of distinct IP_CT types (no NEW in reply dirn). */

IP_CT_RELATED,

/* Started a new connection to track (only IP_CT_DIR_ORIGINAL); may be a retransmission.

IP_CT_ESTABLISHED,

/* Like NEW, but related to an existing connection, or ICMP error (in either direction).

pkt_type, fclone, ipvs_property

__u8

pkt_type:3,

fclone:2, ipvs_property:1;

“pkt_type”表示根据L2的目的地址得到包类型,可能取值在include/linux/if_packet.h,以太网设备中使用eth_type_trans函数来初始化这个值:

? PACKET_HOST:

? ? ? ? ? ?

PACKET_MULTICAST: PACKET_BROADCAST: PACKET_OTHERHOST: PACKET_OUTGOING: PACKET_LOOPBACK: PACKET_FASTROUTE:

“fclone”:是较新版kernel中添加的一个特性,以前版本的kernel中skb在分配的时候都是从后备高速缓存(lookaside cache)skbuff_head_cache中获取sk_buff的结构;而现在可以在调用alloc_skb(),通过fclone参数选择从skbuff_head_cache或者skbuff_fclone_cache中分配。两者的区别在于skbuff_head_cache在创建时指定的单位内存区域的大小是

sizeof(structsk_buff),可以容纳任意数目的struct sk_buff,而skbuff_fclone_cache在创建时指定的单位内存区域大小是2*sizeof(struct sk_buff)+sizeof(atomic_t),它的最小区域单位是一对strcut sk_buff和一个引用计数,这一对sk_buff是克隆的,即它们指向同一个数据缓冲区,引用计数值是0(SKB_FCLONE_UNAVAILABLE),1(SKB_FCLONE_ORIG)或2(SKB_FCLONE_CLONE),表示这一对中有几个sk_buff已被使用: ? ?

分配skb时,skb->fclone = SKB_FCLONE_ORIG; atomic_set(fclone_ref, 1);

child->fclone = SKB_FCLONE_UNAVAILABLE; skb_clone时,如下处理 struct sk_buff *n; n = skb + 1;

if (skb->fclone == SKB_FCLONE_ORIG && n->fclone == SKB_FCLONE_UNAVAILABLE) { }

atomic_t *fclone_ref = (atomic_t *) (n + 1); n->fclone = SKB_FCLONE_CLONE; atomic_inc(fclone_ref);

n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); if (!n)

return NULL;

n->fclone = SKB_FCLONE_UNAVAILABLE;

} else {

即如果设置了fclone,第一次clone采用快速clone,直接使用child_skb,并且增加fclone_ref,child_skb->fclone = SKB_FCLONE_CLONE;其他情况都从skbuff_head_cache里分配新的skb; ?

在释放skb结构时如下处理

switch (skb->fclone) { case SKB_FCLONE_UNAVAILABLE:

kmem_cache_free(skbuff_head_cache, skb); break;

case SKB_FCLONE_ORIG:

fclone_ref = (atomic_t *) (skb + 2); if (atomic_dec_and_test(fclone_ref)) kmem_cache_free(skbuff_fclone_cache, skb);

break;

case SKB_FCLONE_CLONE:

fclone_ref = (atomic_t *) (skb + 1); other = skb - 1;

/* The clone portion is available for * fast-cloning again. */

skb->fclone = SKB_FCLONE_UNAVAILABLE; if (atomic_dec_and_test(fclone_ref))

kmem_cache_free(skbuff_fclone_cache, other); break;

};

? ?

SKB_FCLONE_UNAVAILABLE:直接归还给skbuff_head_cache;(虽然没有经过clone的child_skb->fclone也是这个标志,但没有被clone也不会被释放)

SKB_FCLONE_ORIG:代表释放的是从skbuff_fclone_cache里分配的skb,如果fclone_ref = 1(未被clone过)则归还skb给skbuff_fclone_cache;否则(已经被clone过)只是将fclone_ref--; ?

SKB_FCLONE_CLONE:代表释放的代表释放的是从skbuff_fclone_cache里分配的skb经过clone操作后得到的新skb,则把fclone标志置为SKB_FCLONE_UNAVAILABLE,留作下次快速clone使用。如果fclone_ref--=0,代表这个skb的兄弟skb已经被释放了,则归还skb给skbuff_fclone_cache。

根据skb->fclone标志:

“ipvs_property”是为ip_vs模块添加的变量,置为1代表已经被ip_vs某个部分处理过,后续不需要再处理。可以参考ip_vs_out()函数。

head/data/tail/end指针,h/nh/mac指针

unsigned char

*head, *data, *tail, *end;

*th; *uh;

union {

struct tcphdr struct udphdr

struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; struct ipv6hdr *ipv6h; unsigned char

*raw;

} h; union {

struct iphdr *iph; struct ipv6hdr *ipv6h; struct arphdr unsigned char

*arph; *raw;

} nh; union {

head, data, tail, end四个指针分别指向data buffer的不同位置,如下图:

unsigned char *raw; } mac;

这四个指针的移动,最常用的四个函数为:(a)skb_put, (b)skb_push, (c)skb_pull, (d)skb_reserve ,如下图所示。

h,nh,mac分别指向各层网络协议的头部,下面讨论各个指针在接收时都在哪些地方被初始化: ? { ?? }

static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)

skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN); eth = eth_hdr(skb);

mac为L2的头部指针,在eth_type_trans里初始化

__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)

??

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

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