- struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
-
{
- /*
- 用skb的data减去head就是这层协议头部的大小,也许是L2,L3,和L4。
- */
-
int headerlen = skb->data - skb->head;
-
/*
-
* Allocate the copy buffer
-
*/
-
struct sk_buff *n;
/*
申请新的skb buffer。
当定义了NET_SKBUFF_DATA_USES_OFFSET时,skb->end实际上为偏移值。
而没有定义的时候,skb->end为指针。
这里我有一个疑惑,为什么还要加上skb->data_len,这样的话,申请的内存比原有的skb的size要大了啊。
因为不加data_len,就已经等于原skb的大小了。
*/
-
#ifdef NET_SKBUFF_DATA_USES_OFFSET
-
n = alloc_skb(skb->end + skb->data_len, gfp_mask);
-
#else
-
n = alloc_skb(skb->end - skb->head + skb->data_len, gfp_mask);
-
#endif
-
if (!n)
-
return NULL;
/*
为header保留空间
*/
-
/* Set the data pointer */
-
skb_reserve(n, headerlen);
- /*
- 保留原skb->len的data段大小
- */
-
/* Set the tail pointer and length */
-
skb_put(n, skb->len);
/*
完整的复制skb的数据,包括分片
*/
-
if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len))
-
BUG();
/*
复制skb的报文头部信息以及gso信息
*/
-
copy_skb_header(n, skb);
-
return n;
-
}