From: Herbert Xu <herbert.xu@redhat.com> Date: Wed, 27 May 2009 23:29:06 +1000 Subject: [net] skbuff: merge code copy_skb_header and skb_clone Message-id: 20090527132906.GA16250@gondor.apana.org.au O-Subject: Re: [PATCH 7/17] [SKBUFF]: Merge common code between copy_skb_header and skb_clone Bugzilla: 499347 RH-Acked-by: Michal Schmidt <mschmidt@redhat.com> RH-Acked-by: David Miller <davem@redhat.com> RH-Acked-by: Neil Horman <nhorman@redhat.com> RH-Acked-by: Thomas Graf <tgraf@redhat.com> [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: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cd6803f..528115d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -434,6 +434,45 @@ void consume_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->h.raw = old->h.raw; + new->nh.raw = old->nh.raw; + new->mac.raw = old->mac.raw; + new->dst = dst_clone(old->dst); +#ifdef CONFIG_XFRM + new->sp = secpath_get(old->sp); +#endif + memcpy(new->cb, old->cb, sizeof(old->cb)); + new->csum = old->csum; + new->local_df = old->local_df; +#ifdef CONFIG_XEN + new->proto_data_valid = old->proto_data_valid; + new->proto_csum_blank = old->proto_csum_blank; +#endif + new->pkt_type = old->pkt_type; + new->ip_summed = old->ip_summed; + 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; + __nf_copy(new, old); +#ifdef CONFIG_NET_SCHED + new->tc_index = old->tc_index; +#ifdef CONFIG_NET_CLS_ACT + new->tc_verd = SET_TC_VERD(old->tc_verd, 0); + new->tc_verd = CLR_TC_OK2MUNGE(new->tc_verd); + new->tc_verd = CLR_TC_MUNGED(new->tc_verd); + new->input_dev = old->input_dev; +#endif +#endif + + skb_copy_secmark(new, old); +} + /** * skb_clone - duplicate an sk_buff * @skb: buffer to clone @@ -469,47 +508,14 @@ 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(h); - C(nh); - C(mac); - 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(csum); - C(local_df); n->cloned = 1; n->nohdr = 0; -#ifdef CONFIG_XEN - C(proto_data_valid); - C(proto_csum_blank); -#endif - C(pkt_type); - C(ip_summed); - C(priority); -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) - C(ipvs_property); -#endif - C(protocol); n->destructor = NULL; - __nf_copy(n, skb); -#ifdef CONFIG_NET_SCHED - C(tc_index); -#ifdef CONFIG_NET_CLS_ACT - n->tc_verd = SET_TC_VERD(skb->tc_verd,0); - n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); - n->tc_verd = CLR_TC_MUNGED(n->tc_verd); - C(input_dev); -#endif - skb_copy_secmark(n, skb); -#endif C(truesize); atomic_set(&n->users, 1); C(head); @@ -530,35 +536,12 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) */ unsigned long offset = new->data - old->data; - new->sk = NULL; - new->dev = old->dev; - 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->h.raw = old->h.raw + offset; - new->nh.raw = old->nh.raw + offset; - new->mac.raw = old->mac.raw + offset; - 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; - __nf_copy(new, old); -#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); + __copy_skb_header(new, old); + + new->h.raw += offset; + new->nh.raw += offset; + new->mac.raw += offset; + 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;