diff options
-rw-r--r-- | net/bridge/br_forward.c | 67 | ||||
-rw-r--r-- | net/bridge/br_private.h | 15 |
2 files changed, 82 insertions, 0 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 86cd0712d63e..d61e6f741125 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -186,3 +186,70 @@ void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, | |||
186 | { | 186 | { |
187 | br_flood(br, skb, skb2, __br_forward); | 187 | br_flood(br, skb, skb2, __br_forward); |
188 | } | 188 | } |
189 | |||
190 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
191 | /* called with rcu_read_lock */ | ||
192 | static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, | ||
193 | struct sk_buff *skb, struct sk_buff *skb0, | ||
194 | void (*__packet_hook)( | ||
195 | const struct net_bridge_port *p, | ||
196 | struct sk_buff *skb)) | ||
197 | { | ||
198 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | ||
199 | struct net_bridge *br = netdev_priv(dev); | ||
200 | struct net_bridge_port *port; | ||
201 | struct net_bridge_port *lport, *rport; | ||
202 | struct net_bridge_port *prev; | ||
203 | struct net_bridge_port_group *p; | ||
204 | struct hlist_node *rp; | ||
205 | |||
206 | prev = NULL; | ||
207 | |||
208 | rp = br->router_list.first; | ||
209 | p = mdst ? mdst->ports : NULL; | ||
210 | while (p || rp) { | ||
211 | lport = p ? p->port : NULL; | ||
212 | rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : | ||
213 | NULL; | ||
214 | |||
215 | port = (unsigned long)lport > (unsigned long)rport ? | ||
216 | lport : rport; | ||
217 | |||
218 | prev = maybe_deliver(prev, port, skb, __packet_hook); | ||
219 | if (IS_ERR(prev)) | ||
220 | goto out; | ||
221 | |||
222 | if ((unsigned long)lport >= (unsigned long)port) | ||
223 | p = p->next; | ||
224 | if ((unsigned long)rport >= (unsigned long)port) | ||
225 | rp = rp->next; | ||
226 | } | ||
227 | |||
228 | if (!prev) | ||
229 | goto out; | ||
230 | |||
231 | if (skb0) | ||
232 | deliver_clone(prev, skb, __packet_hook); | ||
233 | else | ||
234 | __packet_hook(prev, skb); | ||
235 | return; | ||
236 | |||
237 | out: | ||
238 | if (!skb0) | ||
239 | kfree_skb(skb); | ||
240 | } | ||
241 | |||
242 | /* called with rcu_read_lock */ | ||
243 | void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, | ||
244 | struct sk_buff *skb) | ||
245 | { | ||
246 | br_multicast_flood(mdst, skb, NULL, __br_deliver); | ||
247 | } | ||
248 | |||
249 | /* called with rcu_read_lock */ | ||
250 | void br_multicast_forward(struct net_bridge_mdb_entry *mdst, | ||
251 | struct sk_buff *skb, struct sk_buff *skb2) | ||
252 | { | ||
253 | br_multicast_flood(mdst, skb, skb2, __br_forward); | ||
254 | } | ||
255 | #endif | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 44345c9afdd3..c85943c2b23f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -293,6 +293,10 @@ extern void br_multicast_disable_port(struct net_bridge_port *port); | |||
293 | extern void br_multicast_init(struct net_bridge *br); | 293 | extern void br_multicast_init(struct net_bridge *br); |
294 | extern void br_multicast_open(struct net_bridge *br); | 294 | extern void br_multicast_open(struct net_bridge *br); |
295 | extern void br_multicast_stop(struct net_bridge *br); | 295 | extern void br_multicast_stop(struct net_bridge *br); |
296 | extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, | ||
297 | struct sk_buff *skb); | ||
298 | extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst, | ||
299 | struct sk_buff *skb, struct sk_buff *skb2); | ||
296 | #else | 300 | #else |
297 | static inline int br_multicast_rcv(struct net_bridge *br, | 301 | static inline int br_multicast_rcv(struct net_bridge *br, |
298 | struct net_bridge_port *port, | 302 | struct net_bridge_port *port, |
@@ -334,6 +338,17 @@ static inline void br_multicast_open(struct net_bridge *br) | |||
334 | static inline void br_multicast_stop(struct net_bridge *br) | 338 | static inline void br_multicast_stop(struct net_bridge *br) |
335 | { | 339 | { |
336 | } | 340 | } |
341 | |||
342 | static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, | ||
343 | struct sk_buff *skb) | ||
344 | { | ||
345 | } | ||
346 | |||
347 | static inline void br_multicast_forward(struct net_bridge_mdb_entry *mdst, | ||
348 | struct sk_buff *skb, | ||
349 | struct sk_buff *skb2) | ||
350 | { | ||
351 | } | ||
337 | #endif | 352 | #endif |
338 | 353 | ||
339 | static inline bool br_multicast_is_router(struct net_bridge *br) | 354 | static inline bool br_multicast_is_router(struct net_bridge *br) |