skb管理函數之skb_clone、pskb_copy、skb_copy
阿新 • • 發佈:2017-09-16
發送 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 priority5 * 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 structsk_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