aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-02-27 14:41:40 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-28 03:48:43 -0500
commit68b7c895be336b19f4c38d7cb500132fabba0afd (patch)
tree13f2a04c86d22abd1c44e9659e54a13c8f939689 /net
parent87557c18ac36241b596984589a0889c5c4bf916c (diff)
bridge: Allow tail-call on br_pass_frame_up
This patch allows tail-call on the call to br_pass_frame_up in br_handle_frame_finish. This is now possible because of the previous patch to call br_pass_frame_up last. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_input.c12
-rw-r--r--net/bridge/br_private.h6
2 files changed, 13 insertions, 5 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 9589937e1c0a..be5ab8df6661 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -20,9 +20,9 @@
20/* Bridge group multicast address 802.1d (pg 51). */ 20/* Bridge group multicast address 802.1d (pg 51). */
21const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 21const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
22 22
23static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) 23static int br_pass_frame_up(struct sk_buff *skb)
24{ 24{
25 struct net_device *indev, *brdev = br->dev; 25 struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
26 26
27 brdev->stats.rx_packets++; 27 brdev->stats.rx_packets++;
28 brdev->stats.rx_bytes += skb->len; 28 brdev->stats.rx_bytes += skb->len;
@@ -30,8 +30,8 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
30 indev = skb->dev; 30 indev = skb->dev;
31 skb->dev = brdev; 31 skb->dev = brdev;
32 32
33 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, 33 return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
34 netif_receive_skb); 34 netif_receive_skb);
35} 35}
36 36
37/* note: already called with rcu_read_lock (preempt_disabled) */ 37/* note: already called with rcu_read_lock (preempt_disabled) */
@@ -53,6 +53,8 @@ int br_handle_frame_finish(struct sk_buff *skb)
53 if (p->state == BR_STATE_LEARNING) 53 if (p->state == BR_STATE_LEARNING)
54 goto drop; 54 goto drop;
55 55
56 BR_INPUT_SKB_CB(skb)->brdev = br->dev;
57
56 /* The packet skb2 goes to the local host (NULL to skip). */ 58 /* The packet skb2 goes to the local host (NULL to skip). */
57 skb2 = NULL; 59 skb2 = NULL;
58 60
@@ -81,7 +83,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
81 } 83 }
82 84
83 if (skb2) 85 if (skb2)
84 br_pass_frame_up(br, skb2); 86 return br_pass_frame_up(skb2);
85 87
86out: 88out:
87 return 0; 89 return 0;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1f0c4f44b765..16513793156e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -131,6 +131,12 @@ struct net_bridge
131 struct kobject *ifobj; 131 struct kobject *ifobj;
132}; 132};
133 133
134struct br_input_skb_cb {
135 struct net_device *brdev;
136};
137
138#define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb)
139
134extern struct notifier_block br_device_notifier; 140extern struct notifier_block br_device_notifier;
135extern const u8 br_group_address[ETH_ALEN]; 141extern const u8 br_group_address[ETH_ALEN];
136 142