Commit dec18810 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[SKBUFF]: Merge common code between copy_skb_header and skb_clone



This patch creates a new function __copy_skb_header to merge the common
code between copy_skb_header and skb_clone.  Having two functions which
are largely the same is a source of wasted labour as well as confusion.

In fact the tc_verd stuff is almost certainly a bug since it's treated
differently in skb_clone compared to the callers of copy_skb_header
(skb_copy/pskb_copy/skb_copy_expand).

I've kept that difference in tact with a comment added asking for
clarification.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f4921aff
Loading
Loading
Loading
Loading
+45 −71
Original line number Diff line number Diff line
@@ -362,6 +362,44 @@ void kfree_skb(struct sk_buff *skb)
	__kfree_skb(skb);
}

static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
{
	new->tstamp		= old->tstamp;
	new->dev		= old->dev;
	new->transport_header	= old->transport_header;
	new->network_header	= old->network_header;
	new->mac_header		= old->mac_header;
	new->dst		= dst_clone(old->dst);
#ifdef CONFIG_INET
	new->sp			= secpath_get(old->sp);
#endif
	memcpy(new->cb, old->cb, sizeof(old->cb));
	new->csum_start		= old->csum_start;
	new->csum_offset	= old->csum_offset;
	new->local_df		= old->local_df;
	new->pkt_type		= old->pkt_type;
	new->ip_summed		= old->ip_summed;
	skb_copy_queue_mapping(new, old);
	new->priority		= old->priority;
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
	new->ipvs_property	= old->ipvs_property;
#endif
	new->protocol		= old->protocol;
	new->mark		= old->mark;
	__nf_copy(new, old);
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
	new->nf_trace		= old->nf_trace;
#endif
#ifdef CONFIG_NET_SCHED
	new->tc_index		= old->tc_index;
#ifdef CONFIG_NET_CLS_ACT
	new->tc_verd		= old->tc_verd;
#endif
#endif
	skb_copy_secmark(new, old);
}

/**
 *	skb_clone	-	duplicate an sk_buff
 *	@skb: buffer to clone
@@ -397,51 +435,22 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)

	n->next = n->prev = NULL;
	n->sk = NULL;
	C(tstamp);
	C(dev);
	C(transport_header);
	C(network_header);
	C(mac_header);
	C(dst);
	dst_clone(skb->dst);
	C(sp);
#ifdef CONFIG_INET
	secpath_get(skb->sp);
#endif
	memcpy(n->cb, skb->cb, sizeof(skb->cb));
	__copy_skb_header(n, skb);

	C(len);
	C(data_len);
	C(mac_len);
	C(csum);
	C(local_df);
	n->cloned = 1;
	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
	n->nohdr = 0;
	C(pkt_type);
	C(ip_summed);
	skb_copy_queue_mapping(n, skb);
	C(priority);
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
	C(ipvs_property);
#endif
	C(protocol);
	n->destructor = NULL;
	C(mark);
	__nf_copy(n, skb);
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
	C(nf_trace);
#endif
#ifdef CONFIG_NET_SCHED
	C(tc_index);
#ifdef CONFIG_NET_CLS_ACT
	n->tc_verd = SET_TC_VERD(skb->tc_verd,0);
	/* FIXME What is this and why don't we do it in copy_skb_header? */
	n->tc_verd = SET_TC_VERD(n->tc_verd,0);
	n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
	n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
	C(iif);
#endif
#endif
	skb_copy_secmark(n, skb);
	C(truesize);
	atomic_set(&n->users, 1);
	C(head);
@@ -463,50 +472,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
	 */
	unsigned long offset = new->data - old->data;
#endif
	new->sk		= NULL;
	new->dev	= old->dev;
	skb_copy_queue_mapping(new, old);
	new->priority	= old->priority;
	new->protocol	= old->protocol;
	new->dst	= dst_clone(old->dst);
#ifdef CONFIG_INET
	new->sp		= secpath_get(old->sp);
#endif
	new->csum_start = old->csum_start;
	new->csum_offset = old->csum_offset;
	new->ip_summed = old->ip_summed;
	new->transport_header = old->transport_header;
	new->network_header   = old->network_header;
	new->mac_header	      = old->mac_header;

	__copy_skb_header(new, old);

#ifndef NET_SKBUFF_DATA_USES_OFFSET
	/* {transport,network,mac}_header are relative to skb->head */
	new->transport_header += offset;
	new->network_header   += offset;
	new->mac_header	      += offset;
#endif
	memcpy(new->cb, old->cb, sizeof(old->cb));
	new->local_df	= old->local_df;
	new->fclone	= SKB_FCLONE_UNAVAILABLE;
	new->pkt_type	= old->pkt_type;
	new->tstamp	= old->tstamp;
	new->destructor = NULL;
	new->mark	= old->mark;
	__nf_copy(new, old);
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
	new->nf_trace	= old->nf_trace;
#endif
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
	new->ipvs_property = old->ipvs_property;
#endif
#ifdef CONFIG_NET_SCHED
#ifdef CONFIG_NET_CLS_ACT
	new->tc_verd = old->tc_verd;
#endif
	new->tc_index	= old->tc_index;
#endif
	skb_copy_secmark(new, old);
	atomic_set(&new->users, 1);
	skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
	skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
	skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;