struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask) { struct sk_buff *n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); if (!n) return NULL; #define C(x) n->x = skb->x n->next = n->prev = NULL; n->list = NULL; n->sk = NULL; C(stamp); C(dev); C(real_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)); C(len); C(data_len); C(csum); C(local_df); n->cloned = 1; C(pkt_type); C(ip_summed); C(priority); C(protocol); C(security); n->destructor = NULL; #ifdef CONFIG_NETFILTER C(nfmark); C(nfcache); C(nfct); nf_conntrack_get(skb->nfct); #ifdef CONFIG_NETFILTER_DEBUG C(nf_debug); #endif #ifdef CONFIG_BRIDGE_NETFILTER C(nf_bridge); nf_bridge_get(skb->nf_bridge); #endif #endif /*CONFIG_NETFILTER*/ #if defined(CONFIG_HIPPI) C(private); #endif #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(skb->tc_verd); n->tc_verd = CLR_TC_MUNGED(skb->tc_verd); C(input_dev); C(tc_classid); #endif #endif #if defined(CONFIG_MIPS_BRCM) C(retfreeq_flags); n->retfreeq_flags &= ~SKB_PREALLOC; C(retfreeq_cb); C(retfreeq_context); C(rcvfrom); memcpy(n->extif, skb->extif, sizeof(skb->extif)); #endif C(truesize); atomic_set(&n->users, 1); C(head); C(data); C(tail); C(end); atomic_inc(&(skb_shinfo(skb)->dataref)); skb->cloned = 1; return n; }
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; } #define C(x) n->x = skb->x 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)); C(len); C(data_len); C(mac_len); C(csum); C(local_df); n->cloned = 1; n->nohdr = 0; 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; C(mark); #ifdef CONFIG_NETFILTER C(nfct); nf_conntrack_get(skb->nfct); C(nfctinfo); #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) C(nfct_reasm); nf_conntrack_get_reasm(skb->nfct_reasm); #endif #ifdef CONFIG_BRIDGE_NETFILTER C(nf_bridge); nf_bridge_get(skb->nf_bridge); #endif #endif /*CONFIG_NETFILTER*/ #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(iif); #endif skb_copy_secmark(n, skb); #endif C(truesize); atomic_set(&n->users, 1); C(head); C(data); C(tail); C(end); atomic_inc(&(skb_shinfo(skb)->dataref)); skb->cloned = 1; return n; }