skb_clone/pskb_copy/skb_copy
Posted johnson37
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了skb_clone/pskb_copy/skb_copy相关的知识,希望对你有一定的参考价值。
在Linux对网络数据包的处理过程中,会用到对skb的拷贝,skb的拷贝分成了几种拷贝,之所以分成几种拷贝,在于不同情况下,可能需要修改的skb范围不同,核心思想在于尽可能小的重新开辟内存,尽可能的共享内存,共享数据区。
对一个正常的skb来讲,一般要包括sk_buff以及数据区两部分。而数据区又分成普通数据区和skb_shared_info.
- skb_clone: 只拷贝sk_buff, 换而言之,整个数据区从策略上讲,是没有计划修改的。
- pskb_copy: 拷贝sk_buff以及普通数据区两部分,对于skb_shared_info,会使用指针指向的方式。
- skb_copy: 实现全部拷贝
skb_clone
struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
{
struct sk_buff *n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
...
atomic_set(&n->users, 1);
C(head);
C(data);
C(tail);
C(end);
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
return n;
}
skb_clone的两个常见用法
- br_flood 当中,会skb_clone
- 当skb向上层协议栈传递时。
例如在ip_rcv当中:
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
struct iphdr *iph;
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
goto out;
}
...
}
static inline int skb_shared(const struct sk_buff *skb)
{
return atomic_read(&skb->users) != 1;
}
static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri)
{
might_sleep_if(pri & __GFP_WAIT);
if (skb_shared(skb)) {
struct sk_buff *nskb = skb_clone(skb, pri);
kfree_skb(skb);
skb = nskb;
}
return skb;
}
pskb_copy
skb_copy
以上是关于skb_clone/pskb_copy/skb_copy的主要内容,如果未能解决你的问题,请参考以下文章