net: increase skb->users instead of skb_clone()
In dev_queue_xmit_nit(), we have to clone skbs as we need to mangle skbs, however, we don't need to clone skbs for all the packet_types. Except for the first packet_type, we increase skb->users instead of skb_clone(). Signed-off-by: Changli Gao <xiaosuo@gmail.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1a75972c61
commit
71d9dec24d
1 changed files with 20 additions and 10 deletions
|
@ -1528,6 +1528,14 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dev_forward_skb);
|
||||
|
||||
static inline int deliver_skb(struct sk_buff *skb,
|
||||
struct packet_type *pt_prev,
|
||||
struct net_device *orig_dev)
|
||||
{
|
||||
atomic_inc(&skb->users);
|
||||
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support routine. Sends outgoing frames to any network
|
||||
* taps currently in use.
|
||||
|
@ -1536,6 +1544,8 @@ EXPORT_SYMBOL_GPL(dev_forward_skb);
|
|||
static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct packet_type *ptype;
|
||||
struct sk_buff *skb2 = NULL;
|
||||
struct packet_type *pt_prev = NULL;
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS)))
|
||||
|
@ -1552,7 +1562,13 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
|
|||
if ((ptype->dev == dev || !ptype->dev) &&
|
||||
(ptype->af_packet_priv == NULL ||
|
||||
(struct sock *)ptype->af_packet_priv != skb->sk)) {
|
||||
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
if (pt_prev) {
|
||||
deliver_skb(skb2, pt_prev, skb->dev);
|
||||
pt_prev = ptype;
|
||||
continue;
|
||||
}
|
||||
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!skb2)
|
||||
break;
|
||||
|
||||
|
@ -1574,9 +1590,11 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
skb2->transport_header = skb2->network_header;
|
||||
skb2->pkt_type = PACKET_OUTGOING;
|
||||
ptype->func(skb2, skb->dev, ptype, skb->dev);
|
||||
pt_prev = ptype;
|
||||
}
|
||||
}
|
||||
if (pt_prev)
|
||||
pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -2820,14 +2838,6 @@ static void net_tx_action(struct softirq_action *h)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int deliver_skb(struct sk_buff *skb,
|
||||
struct packet_type *pt_prev,
|
||||
struct net_device *orig_dev)
|
||||
{
|
||||
atomic_inc(&skb->users);
|
||||
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
|
||||
}
|
||||
|
||||
#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && \
|
||||
(defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE))
|
||||
/* This hook is defined here for ATM LANE */
|
||||
|
|
Loading…
Reference in a new issue