aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChangli Gao <xiaosuo@gmail.com>2010-12-15 14:57:25 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-20 00:50:20 -0500
commit71d9dec24dce548bf699815c976cf063ad9257e2 (patch)
treeaad41859f011a20125acb3a717b3fc3121f108a2
parent1a75972c61f2c224eb5283c183f9f6b17fb09b6b (diff)
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>
-rw-r--r--net/core/dev.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 92d414ac0e3..59877290bca 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1528,6 +1528,14 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1528} 1528}
1529EXPORT_SYMBOL_GPL(dev_forward_skb); 1529EXPORT_SYMBOL_GPL(dev_forward_skb);
1530 1530
1531static inline int deliver_skb(struct sk_buff *skb,
1532 struct packet_type *pt_prev,
1533 struct net_device *orig_dev)
1534{
1535 atomic_inc(&skb->users);
1536 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
1537}
1538
1531/* 1539/*
1532 * Support routine. Sends outgoing frames to any network 1540 * Support routine. Sends outgoing frames to any network
1533 * taps currently in use. 1541 * taps currently in use.
@@ -1536,6 +1544,8 @@ EXPORT_SYMBOL_GPL(dev_forward_skb);
1536static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) 1544static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
1537{ 1545{
1538 struct packet_type *ptype; 1546 struct packet_type *ptype;
1547 struct sk_buff *skb2 = NULL;
1548 struct packet_type *pt_prev = NULL;
1539 1549
1540#ifdef CONFIG_NET_CLS_ACT 1550#ifdef CONFIG_NET_CLS_ACT
1541 if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS))) 1551 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)
1552 if ((ptype->dev == dev || !ptype->dev) && 1562 if ((ptype->dev == dev || !ptype->dev) &&
1553 (ptype->af_packet_priv == NULL || 1563 (ptype->af_packet_priv == NULL ||
1554 (struct sock *)ptype->af_packet_priv != skb->sk)) { 1564 (struct sock *)ptype->af_packet_priv != skb->sk)) {
1555 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1565 if (pt_prev) {
1566 deliver_skb(skb2, pt_prev, skb->dev);
1567 pt_prev = ptype;
1568 continue;
1569 }
1570
1571 skb2 = skb_clone(skb, GFP_ATOMIC);
1556 if (!skb2) 1572 if (!skb2)
1557 break; 1573 break;
1558 1574
@@ -1574,9 +1590,11 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
1574 1590
1575 skb2->transport_header = skb2->network_header; 1591 skb2->transport_header = skb2->network_header;
1576 skb2->pkt_type = PACKET_OUTGOING; 1592 skb2->pkt_type = PACKET_OUTGOING;
1577 ptype->func(skb2, skb->dev, ptype, skb->dev); 1593 pt_prev = ptype;
1578 } 1594 }
1579 } 1595 }
1596 if (pt_prev)
1597 pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
1580 rcu_read_unlock(); 1598 rcu_read_unlock();
1581} 1599}
1582 1600
@@ -2820,14 +2838,6 @@ static void net_tx_action(struct softirq_action *h)
2820 } 2838 }
2821} 2839}
2822 2840
2823static inline int deliver_skb(struct sk_buff *skb,
2824 struct packet_type *pt_prev,
2825 struct net_device *orig_dev)
2826{
2827 atomic_inc(&skb->users);
2828 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
2829}
2830
2831#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && \ 2841#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && \
2832 (defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)) 2842 (defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE))
2833/* This hook is defined here for ATM LANE */ 2843/* This hook is defined here for ATM LANE */