|
@@ -400,37 +400,8 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
|
|
skb_copy_secmark(new, old);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * skb_clone - duplicate an sk_buff
|
|
|
- * @skb: buffer to clone
|
|
|
- * @gfp_mask: allocation priority
|
|
|
- *
|
|
|
- * Duplicate an &sk_buff. The new one is not owned by a socket. Both
|
|
|
- * copies share the same packet data but not structure. The new
|
|
|
- * buffer has a reference count of 1. If the allocation fails the
|
|
|
- * function returns %NULL otherwise the new buffer is returned.
|
|
|
- *
|
|
|
- * If this function is called from an interrupt gfp_mask() must be
|
|
|
- * %GFP_ATOMIC.
|
|
|
- */
|
|
|
-
|
|
|
-struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
|
|
+static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
|
|
|
{
|
|
|
- struct sk_buff *n;
|
|
|
-
|
|
|
- n = skb + 1;
|
|
|
- if (skb->fclone == SKB_FCLONE_ORIG &&
|
|
|
- n->fclone == SKB_FCLONE_UNAVAILABLE) {
|
|
|
- atomic_t *fclone_ref = (atomic_t *) (n + 1);
|
|
|
- n->fclone = SKB_FCLONE_CLONE;
|
|
|
- atomic_inc(fclone_ref);
|
|
|
- } else {
|
|
|
- n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
|
|
|
- if (!n)
|
|
|
- return NULL;
|
|
|
- n->fclone = SKB_FCLONE_UNAVAILABLE;
|
|
|
- }
|
|
|
-
|
|
|
#define C(x) n->x = skb->x
|
|
|
|
|
|
n->next = n->prev = NULL;
|
|
@@ -462,6 +433,58 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
|
|
skb->cloned = 1;
|
|
|
|
|
|
return n;
|
|
|
+#undef C
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * skb_morph - morph one skb into another
|
|
|
+ * @dst: the skb to receive the contents
|
|
|
+ * @src: the skb to supply the contents
|
|
|
+ *
|
|
|
+ * This is identical to skb_clone except that the target skb is
|
|
|
+ * supplied by the user.
|
|
|
+ *
|
|
|
+ * The target skb is returned upon exit.
|
|
|
+ */
|
|
|
+struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
|
|
|
+{
|
|
|
+ skb_release_data(dst);
|
|
|
+ return __skb_clone(dst, src);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(skb_morph);
|
|
|
+
|
|
|
+/**
|
|
|
+ * skb_clone - duplicate an sk_buff
|
|
|
+ * @skb: buffer to clone
|
|
|
+ * @gfp_mask: allocation priority
|
|
|
+ *
|
|
|
+ * Duplicate an &sk_buff. The new one is not owned by a socket. Both
|
|
|
+ * copies share the same packet data but not structure. The new
|
|
|
+ * buffer has a reference count of 1. If the allocation fails the
|
|
|
+ * function returns %NULL otherwise the new buffer is returned.
|
|
|
+ *
|
|
|
+ * If this function is called from an interrupt gfp_mask() must be
|
|
|
+ * %GFP_ATOMIC.
|
|
|
+ */
|
|
|
+
|
|
|
+struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
|
|
+{
|
|
|
+ struct sk_buff *n;
|
|
|
+
|
|
|
+ n = skb + 1;
|
|
|
+ if (skb->fclone == SKB_FCLONE_ORIG &&
|
|
|
+ n->fclone == SKB_FCLONE_UNAVAILABLE) {
|
|
|
+ atomic_t *fclone_ref = (atomic_t *) (n + 1);
|
|
|
+ n->fclone = SKB_FCLONE_CLONE;
|
|
|
+ atomic_inc(fclone_ref);
|
|
|
+ } else {
|
|
|
+ n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
|
|
|
+ if (!n)
|
|
|
+ return NULL;
|
|
|
+ n->fclone = SKB_FCLONE_UNAVAILABLE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return __skb_clone(n, skb);
|
|
|
}
|
|
|
|
|
|
static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|