diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-02-27 14:41:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 03:48:44 -0500 |
commit | 025d89c27f54c69cd0e51666d88aada33666bb6c (patch) | |
tree | 73063f6189c25d55c71ae6dad96a3711df87b7a6 /net/bridge | |
parent | 6088a539d8d1666dca6979b5759bf966ee9124ef (diff) |
bridge: Split may_deliver/deliver_clone out of br_flood
This patch moves the main loop body in br_flood into the function
may_deliver. The code that clones an skb and delivers it is moved
into the deliver_clone function.
This allows this to be reused by the future multicast forward
function.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_forward.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2e1cb434f6cd..86cd0712d63e 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * 2 of the License, or (at your option) any later version. | 11 | * 2 of the License, or (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/err.h> | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
16 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
@@ -103,6 +104,44 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
103 | kfree_skb(skb); | 104 | kfree_skb(skb); |
104 | } | 105 | } |
105 | 106 | ||
107 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, | ||
108 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
109 | struct sk_buff *skb)) | ||
110 | { | ||
111 | skb = skb_clone(skb, GFP_ATOMIC); | ||
112 | if (!skb) { | ||
113 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | ||
114 | |||
115 | dev->stats.tx_dropped++; | ||
116 | return -ENOMEM; | ||
117 | } | ||
118 | |||
119 | __packet_hook(prev, skb); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static struct net_bridge_port *maybe_deliver( | ||
124 | struct net_bridge_port *prev, struct net_bridge_port *p, | ||
125 | struct sk_buff *skb, | ||
126 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
127 | struct sk_buff *skb)) | ||
128 | { | ||
129 | int err; | ||
130 | |||
131 | if (!should_deliver(p, skb)) | ||
132 | return prev; | ||
133 | |||
134 | if (!prev) | ||
135 | goto out; | ||
136 | |||
137 | err = deliver_clone(prev, skb, __packet_hook); | ||
138 | if (err) | ||
139 | return ERR_PTR(err); | ||
140 | |||
141 | out: | ||
142 | return p; | ||
143 | } | ||
144 | |||
106 | /* called under bridge lock */ | 145 | /* called under bridge lock */ |
107 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, | 146 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, |
108 | struct sk_buff *skb0, | 147 | struct sk_buff *skb0, |
@@ -111,38 +150,22 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, | |||
111 | { | 150 | { |
112 | struct net_bridge_port *p; | 151 | struct net_bridge_port *p; |
113 | struct net_bridge_port *prev; | 152 | struct net_bridge_port *prev; |
114 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | ||
115 | 153 | ||
116 | prev = NULL; | 154 | prev = NULL; |
117 | 155 | ||
118 | list_for_each_entry_rcu(p, &br->port_list, list) { | 156 | list_for_each_entry_rcu(p, &br->port_list, list) { |
119 | if (should_deliver(p, skb)) { | 157 | prev = maybe_deliver(prev, p, skb, __packet_hook); |
120 | if (prev != NULL) { | 158 | if (IS_ERR(prev)) |
121 | struct sk_buff *skb2; | 159 | goto out; |
122 | |||
123 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { | ||
124 | dev->stats.tx_dropped++; | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | __packet_hook(prev, skb2); | ||
129 | } | ||
130 | |||
131 | prev = p; | ||
132 | } | ||
133 | } | 160 | } |
134 | 161 | ||
135 | if (!prev) | 162 | if (!prev) |
136 | goto out; | 163 | goto out; |
137 | 164 | ||
138 | if (skb0) { | 165 | if (skb0) |
139 | skb = skb_clone(skb, GFP_ATOMIC); | 166 | deliver_clone(prev, skb, __packet_hook); |
140 | if (!skb) { | 167 | else |
141 | dev->stats.tx_dropped++; | 168 | __packet_hook(prev, skb); |
142 | goto out; | ||
143 | } | ||
144 | } | ||
145 | __packet_hook(prev, skb); | ||
146 | return; | 169 | return; |
147 | 170 | ||
148 | out: | 171 | out: |