{
        br_flood(br, skb, skb2, __br_forward);
 }
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+/* called with rcu_read_lock */
+static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
+                              struct sk_buff *skb, struct sk_buff *skb0,
+                              void (*__packet_hook)(
+                                       const struct net_bridge_port *p,
+                                       struct sk_buff *skb))
+{
+       struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+       struct net_bridge *br = netdev_priv(dev);
+       struct net_bridge_port *port;
+       struct net_bridge_port *lport, *rport;
+       struct net_bridge_port *prev;
+       struct net_bridge_port_group *p;
+       struct hlist_node *rp;
+
+       prev = NULL;
+
+       rp = br->router_list.first;
+       p = mdst ? mdst->ports : NULL;
+       while (p || rp) {
+               lport = p ? p->port : NULL;
+               rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
+                            NULL;
+
+               port = (unsigned long)lport > (unsigned long)rport ?
+                      lport : rport;
+
+               prev = maybe_deliver(prev, port, skb, __packet_hook);
+               if (IS_ERR(prev))
+                       goto out;
+
+               if ((unsigned long)lport >= (unsigned long)port)
+                       p = p->next;
+               if ((unsigned long)rport >= (unsigned long)port)
+                       rp = rp->next;
+       }
+
+       if (!prev)
+               goto out;
+
+       if (skb0)
+               deliver_clone(prev, skb, __packet_hook);
+       else
+               __packet_hook(prev, skb);
+       return;
+
+out:
+       if (!skb0)
+               kfree_skb(skb);
+}
+
+/* called with rcu_read_lock */
+void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
+                         struct sk_buff *skb)
+{
+       br_multicast_flood(mdst, skb, NULL, __br_deliver);
+}
+
+/* called with rcu_read_lock */
+void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
+                         struct sk_buff *skb, struct sk_buff *skb2)
+{
+       br_multicast_flood(mdst, skb, skb2, __br_forward);
+}
+#endif
 
 extern void br_multicast_init(struct net_bridge *br);
 extern void br_multicast_open(struct net_bridge *br);
 extern void br_multicast_stop(struct net_bridge *br);
+extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
+                                struct sk_buff *skb);
+extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
+                                struct sk_buff *skb, struct sk_buff *skb2);
 #else
 static inline int br_multicast_rcv(struct net_bridge *br,
                                   struct net_bridge_port *port,
 static inline void br_multicast_stop(struct net_bridge *br)
 {
 }
+
+static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
+                                       struct sk_buff *skb)
+{
+}
+
+static inline void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
+                                       struct sk_buff *skb,
+                                       struct sk_buff *skb2)
+{
+}
 #endif
 
 static inline bool br_multicast_is_router(struct net_bridge *br)