2、pskb_copy()
与skb_copy()不同,当一个函数不仅需要修改skb描述符,而且需要修改其缓冲区中的数据时,就需要复制缓冲区的数据。如果需要修改的数据在skb->head到skb->end之间,即数据是一个线性空间的数据时,便可调用pskb_copy()函数来完成此操作。
- /**
-
-
* pskb_copy - create copy of an sk_buff with private head.
-
-
* @skb: buffer to copy
-
-
* @gfp_mask: allocation priority
-
-
*
-
-
* Make a copy of both an &sk_buff and part of its data, located
-
-
* in header. Fragmented data remain shared. This is used when
-
-
* the caller wishes to modify only header of &sk_buff and needs
-
-
* private copy of the header to alter. Returns %NULL on failure
-
-
* or the pointer to the buffer on success.
-
-
* The returned buffer has a reference count of 1.
-
-
*/
-
-
-
-
struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
-
-
{
-
-
/*
-
-
* Allocate the copy buffer
-
-
*/
-
-
struct sk_buff *n;
-
-
/* 先申请skb描述符字段的内存空间,在这种情况下,skb描述符是不能继用预先分配的skb描述符的 */
-
-
#ifdef NET_SKBUFF_DATA_USES_OFFSET
-
-
n = alloc_skb(skb->end, gfp_mask);
-
-
#else
-
-
n = alloc_skb(skb->end - skb->head, gfp_mask);
-
-
#endif
-
-
if (!n)
-
-
goto out;
-
-
-
-
/* Set the data pointer */
-
-
/* 设置数据指针 */
-
-
skb_reserve(n, skb->data - skb->head);
-
-
/* Set the tail pointer and length */
-
-
/* 设置skb->tail指针和skb->len 长度 */
-
-
skb_put(n, skb_headlen(skb));
-
-
/* Copy the bytes */
-
-
/* 拷贝线性空间的数据 */
-
-
skb_copy_from_linear_data(skb, n->data, n->len);
-
-
-
-
/* 对share info结构进行拷贝,并设置相关字段的值 */
-
-
n->truesize += skb->data_len;
-
-
n->data_len = skb->data_len;
-
-
n->len = skb->len;
-
-
-
-
if (skb_shinfo(skb)->nr_frags) {
-
-
int i;
-
-
-
-
/*在share info中有数据的情况下,拷贝share字段,特别注意:这里并没有拷贝share info中的数据 */
-
-
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-
-
skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
-
-
get_page(skb_shinfo(n)->frags[i].page);
-
-
}
-
-
skb_shinfo(n)->nr_frags = i;
-
-
}
-
-
-
-
if (skb_has_frags(skb)) {
-
-
skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
-
-
skb_clone_fraglist(n);
-
-
}
-
-
-
-
/* 拷贝skb头部的相关字段 */
-
-
copy_skb_header(n, skb);
-
-
out:
-
-
return n;
-
-
}
-
-
-
-
/**
-
-
* skb_reserve - adjust headroom
-
-
* @skb: buffer to alter
-
-
* @len: bytes to move
-
-
*
-
-
* Increase the headroom of an empty &sk_buff by reducing the tail
-
-
* room. This is only allowed for an empty buffer.
-
-
*/
-
-
static inline void skb_reserve(struct sk_buff *skb, int len)
-
-
{
-
-
skb->data += len;
-
-
skb->tail += len;
-
-
}
特别说明:pskb_copy()与skb_copy()更重量级一些,他不仅仅拷贝skb描述符,还需要拷贝skb->data指向的数据,但他并不拷贝share info指向的非线性数据,新skb的share info指向与原始skb的share info相同的数据。
阅读(794) | 评论(0) | 转发(0) |