1. 程式人生 > >skb管理函數之skb_clone、pskb_copy、skb_copy

skb管理函數之skb_clone、pskb_copy、skb_copy

發送 converts reat bsp led where log roo ket

skb_clone--只復制skb描述符本身,如果只修改skb描述符則使用該函數克隆;

pskb_copy--復制skb描述符+線性數據區域(包括skb_shared_info),如果需要修改描述符以及數據則使用該函數復制;

skb_copy--復制所有數據,包括skb描述符+線性數據區域+非線性數據區,如果需要修改描述符和全部數據則使用該函數復制;

 1 /**
 2  *    skb_clone    -    duplicate an sk_buff
 3  *    @skb: buffer to clone
 4  *    @gfp_mask: allocation priority
5 * 6 * Duplicate an &sk_buff. The new one is not owned by a socket. Both 7 * copies share the same packet data but not structure. The new 8 * buffer has a reference count of 1. If the allocation fails the 9 * function returns %NULL otherwise the new buffer is returned.
10 * 11 * If this function is called from an interrupt gfp_mask() must be 12 * %GFP_ATOMIC. 13 */ 14 /* 15 用於修改skb描述符中的某些字段 16 克隆skb,該函數只克隆sk_buff部分 17 數據區域公用(需要遞增引用計數) 18 */ 19 struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) 20 { 21 /* 獲取到支持克隆的skb */ 22 struct
sk_buff_fclones *fclones = container_of(skb, 23 struct sk_buff_fclones, 24 skb1); 25 struct sk_buff *n; 26 27 /* 28 若發送標記有零拷貝,則拷貝用戶空間的 29 片段緩存到內核空間 30 */ 31 if (skb_orphan_frags(skb, gfp_mask)) 32 return NULL; 33 34 /* 如果skb可以被克隆,並且克隆引用為1 */ 35 if (skb->fclone == SKB_FCLONE_ORIG && 36 atomic_read(&fclones->fclone_ref) == 1) { 37 /* 待克隆n指向skb2 */ 38 n = &fclones->skb2; 39 /* 增加引用計數 */ 40 atomic_set(&fclones->fclone_ref, 2); 41 } 42 /* 否則,為新克隆的skb分配內存 */ 43 else { 44 if (skb_pfmemalloc(skb)) 45 gfp_mask |= __GFP_MEMALLOC; 46 47 n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); 48 if (!n) 49 return NULL; 50 51 kmemcheck_annotate_bitfield(n, flags1); 52 /* 初始化克隆狀態 */ 53 n->fclone = SKB_FCLONE_UNAVAILABLE; 54 } 55 56 /* 調用克隆 */ 57 return __skb_clone(n, skb); 58 }

 1 /*
 2     用於修改skb描述符和數據緩沖區內容時拷貝
 3     skb拷貝,拷貝skb描述符+ 線性數據緩沖區,
 4     線性緩沖區以外數據共享 
 5 */
 6 static inline struct sk_buff *pskb_copy(struct sk_buff *skb,
 7                     gfp_t gfp_mask)
 8 {
 9     return __pskb_copy(skb, skb_headroom(skb), gfp_mask);
10 }

 1 /**
 2  *    __pskb_copy_fclone    -  create copy of an sk_buff with private head.
 3  *    @skb: buffer to copy
 4  *    @headroom: headroom of new skb
 5  *    @gfp_mask: allocation priority
 6  *    @fclone: if true allocate the copy of the skb from the fclone
 7  *    cache instead of the head cache; it is recommended to set this
 8  *    to true for the cases where the copy will likely be cloned
 9  *
10  *    Make a copy of both an &sk_buff and part of its data, located
11  *    in header. Fragmented data remain shared. This is used when
12  *    the caller wishes to modify only header of &sk_buff and needs
13  *    private copy of the header to alter. Returns %NULL on failure
14  *    or the pointer to the buffer on success.
15  *    The returned buffer has a reference count of 1.
16  */
17 /* 
18     拷貝skb描述符+ 線性數據緩沖區,
19     線性緩沖區外部數據共享
20 */
21 struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
22                    gfp_t gfp_mask, bool fclone)
23 {
24     unsigned int size = skb_headlen(skb) + headroom;
25     int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0);
26     struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE);
27 
28     if (!n)
29         goto out;
30 
31     /* Set the data pointer */
32     /* 保留頭部空間 */
33     skb_reserve(n, headroom);
34     /* Set the tail pointer and length */
35     /* 增加尾指針和數據長度 */
36     skb_put(n, skb_headlen(skb));
37     /* Copy the bytes */
38     /* 拷貝線性緩沖區 */
39     skb_copy_from_linear_data(skb, n->data, n->len);
40 
41     /* 設置長度值 */
42     n->truesize += skb->data_len;
43     n->data_len  = skb->data_len;
44     n->len         = skb->len;
45 
46     /* 若有片段 */
47     if (skb_shinfo(skb)->nr_frags) {
48         int i;
49 
50         /* 片段數據拷貝到內核 */
51         if (skb_orphan_frags(skb, gfp_mask)) {
52             kfree_skb(n);
53             n = NULL;
54             goto out;
55         }
56 
57         /* 復制判斷內容 */
58         for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
59             skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
60             skb_frag_ref(skb, i);
61         }
62 
63         /* 片段數 */
64         skb_shinfo(n)->nr_frags = i;
65     }
66 
67     /* 如果有片段鏈表 */
68     if (skb_has_frag_list(skb)) {
69         /* 引用片段鏈表 */
70         skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
71         skb_clone_fraglist(n);
72     }
73 
74     /* 拷貝頭部信息 */
75     copy_skb_header(n, skb);
76 out:
77     return n;
78 }

 1 /**
 2  *    skb_copy    -    create private copy of an sk_buff
 3  *    @skb: buffer to copy
 4  *    @gfp_mask: allocation priority
 5  *
 6  *    Make a copy of both an &sk_buff and its data. This is used when the
 7  *    caller wishes to modify the data and needs a private copy of the
 8  *    data to alter. Returns %NULL on failure or the pointer to the buffer
 9  *    on success. The returned buffer has a reference count of 1.
10  *
11  *    As by-product this function converts non-linear &sk_buff to linear
12  *    one, so that &sk_buff becomes completely private and caller is allowed
13  *    to modify all the data of returned buffer. This means that this
14  *    function is not recommended for use in circumstances when only
15  *    header is going to be modified. Use pskb_copy() instead.
16  */
17 /* 拷貝skb描述符+線性緩沖區+非線性緩沖區 */
18 struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
19 {
20     /* 頭部空間長度 */
21     int headerlen = skb_headroom(skb);
22 
23     /* 分配空間= skb空間+ skb以外的數據空間 */
24     unsigned int size = skb_end_offset(skb) + skb->data_len;
25     struct sk_buff *n = __alloc_skb(size, gfp_mask,
26                     skb_alloc_rx_flag(skb), NUMA_NO_NODE);
27 
28     if (!n)
29         return NULL;
30 
31     /* Set the data pointer */
32     //保留頭部空間
33     skb_reserve(n, headerlen);
34     /* Set the tail pointer and length */
35     /* 偏移尾部指針修改總長度 */
36     skb_put(n, skb->len);
37 
38     /* 拷貝數據 */
39     if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len))
40         BUG();
41 
42     /* 拷貝skb頭 */
43     copy_skb_header(n, skb);
44     return n;
45 }

skb管理函數之skb_clone、pskb_copy、skb_copy