aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-02-27 14:41:46 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-28 03:48:45 -0500
commit5cb5e947d8f82011e3d7e7017e9d10db9a40ae9f (patch)
tree126e3b2112f780120bf9e95c67fdb1b81e73c314 /net
parenteb1d16414339a6e113d89e2cca2556005d7ce919 (diff)
bridge: Add multicast forwarding functions
This patch adds code to perform selective multicast forwarding. We forward multicast traffic to a set of ports plus all multicast router ports. In order to avoid duplications among these two sets of ports, we order all ports by the numeric value of their pointers. The two lists are then walked in lock-step to eliminate duplicates. 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_forward.c67
-rw-r--r--net/bridge/br_private.h15
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 */
192static 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
237out:
238 if (!skb0)
239 kfree_skb(skb);
240}
241
242/* called with rcu_read_lock */
243void 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 */
250void 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);
293extern void br_multicast_init(struct net_bridge *br); 293extern void br_multicast_init(struct net_bridge *br);
294extern void br_multicast_open(struct net_bridge *br); 294extern void br_multicast_open(struct net_bridge *br);
295extern void br_multicast_stop(struct net_bridge *br); 295extern void br_multicast_stop(struct net_bridge *br);
296extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
297 struct sk_buff *skb);
298extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
299 struct sk_buff *skb, struct sk_buff *skb2);
296#else 300#else
297static inline int br_multicast_rcv(struct net_bridge *br, 301static 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)
334static inline void br_multicast_stop(struct net_bridge *br) 338static inline void br_multicast_stop(struct net_bridge *br)
335{ 339{
336} 340}
341
342static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
343 struct sk_buff *skb)
344{
345}
346
347static 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
339static inline bool br_multicast_is_router(struct net_bridge *br) 354static inline bool br_multicast_is_router(struct net_bridge *br)