bridge: Add multicast_querier toggle and disable queries by default
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 13 Apr 2012 02:37:42 +0000 (02:37 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 15 Apr 2012 16:51:35 +0000 (12:51 -0400)
Sending general queries was implemented as an optimisation to speed
up convergence on start-up.  In order to prevent interference with
multicast routers a zero source address has to be used.

Unfortunately these packets appear to cause some multicast-aware
switches to misbehave, e.g., by disrupting multicast packets to us.

Since the multicast snooping feature still functions without sending
our own queries, this patch will change the default to not send
queries.

For those that need queries in order to speed up convergence on start-up,
a toggle is provided to restore the previous behaviour.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_sysfs_br.c

index b3647d090e1f5f0e807858ade656425727e8a8eb..708e84f31888fb6979f2220f2f5edac65e256bcb 100644 (file)
@@ -783,6 +783,7 @@ static void br_multicast_send_query(struct net_bridge *br,
        struct br_ip br_group;
 
        if (!netif_running(br->dev) || br->multicast_disabled ||
+           !br->multicast_querier ||
            timer_pending(&br->multicast_querier_timer))
                return;
 
@@ -1565,6 +1566,7 @@ void br_multicast_init(struct net_bridge *br)
        br->hash_max = 512;
 
        br->multicast_router = 1;
+       br->multicast_querier = 0;
        br->multicast_last_member_count = 2;
        br->multicast_startup_query_count = 2;
 
@@ -1760,6 +1762,24 @@ unlock:
        return err;
 }
 
+int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
+{
+       val = !!val;
+
+       spin_lock_bh(&br->multicast_lock);
+       if (br->multicast_querier == val)
+               goto unlock;
+
+       br->multicast_querier = val;
+       if (val)
+               br_multicast_start_querier(br);
+
+unlock:
+       spin_unlock_bh(&br->multicast_lock);
+
+       return 0;
+}
+
 int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
 {
        int err = -ENOENT;
index e1d882257877374e21c7a314740a7ee7f76f4ccc..f8ffd8c49054e192116dceb22f2a4d1198de2696 100644 (file)
@@ -224,6 +224,7 @@ struct net_bridge
        unsigned char                   multicast_router;
 
        u8                              multicast_disabled:1;
+       u8                              multicast_querier:1;
 
        u32                             hash_elasticity;
        u32                             hash_max;
@@ -417,6 +418,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val);
 extern int br_multicast_set_port_router(struct net_bridge_port *p,
                                        unsigned long val);
 extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
+extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
 extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
 
 static inline bool br_multicast_is_router(struct net_bridge *br)
index 766fd7fb02959206a4dad9b963a07fd8e97225cd..c5c059333eab675aeb73d4bf640f2b784d274902 100644 (file)
@@ -379,6 +379,23 @@ static ssize_t store_multicast_snooping(struct device *d,
 static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
                   show_multicast_snooping, store_multicast_snooping);
 
+static ssize_t show_multicast_querier(struct device *d,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct net_bridge *br = to_bridge(d);
+       return sprintf(buf, "%d\n", br->multicast_querier);
+}
+
+static ssize_t store_multicast_querier(struct device *d,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t len)
+{
+       return store_bridge_parm(d, buf, len, br_multicast_set_querier);
+}
+static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR,
+                  show_multicast_querier, store_multicast_querier);
+
 static ssize_t show_hash_elasticity(struct device *d,
                                    struct device_attribute *attr, char *buf)
 {
@@ -702,6 +719,7 @@ static struct attribute *bridge_attrs[] = {
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        &dev_attr_multicast_router.attr,
        &dev_attr_multicast_snooping.attr,
+       &dev_attr_multicast_querier.attr,
        &dev_attr_hash_elasticity.attr,
        &dev_attr_hash_max.attr,
        &dev_attr_multicast_last_member_count.attr,