diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-02-27 14:41:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 03:48:43 -0500 |
commit | 68b7c895be336b19f4c38d7cb500132fabba0afd (patch) | |
tree | 13f2a04c86d22abd1c44e9659e54a13c8f939689 /net | |
parent | 87557c18ac36241b596984589a0889c5c4bf916c (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.c | 12 | ||||
-rw-r--r-- | net/bridge/br_private.h | 6 |
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). */ |
21 | const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | 21 | const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; |
22 | 22 | ||
23 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | 23 | static 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 | ||
86 | out: | 88 | out: |
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 | ||
134 | struct 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 | |||
134 | extern struct notifier_block br_device_notifier; | 140 | extern struct notifier_block br_device_notifier; |
135 | extern const u8 br_group_address[ETH_ALEN]; | 141 | extern const u8 br_group_address[ETH_ALEN]; |
136 | 142 | ||