diff options
author | Changli Gao <xiaosuo@gmail.com> | 2010-12-15 14:57:25 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-20 00:50:20 -0500 |
commit | 71d9dec24dce548bf699815c976cf063ad9257e2 (patch) | |
tree | aad41859f011a20125acb3a717b3fc3121f108a2 | |
parent | 1a75972c61f2c224eb5283c183f9f6b17fb09b6b (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.c | 30 |
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 | } |
1529 | EXPORT_SYMBOL_GPL(dev_forward_skb); | 1529 | EXPORT_SYMBOL_GPL(dev_forward_skb); |
1530 | 1530 | ||
1531 | static 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); | |||
1536 | static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) | 1544 | static 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 | ||
2823 | static 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 */ |