aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2012-04-12 22:37:42 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-15 12:51:35 -0400
commitc5c23260594c5701af66ef754916775ba6a46bbc (patch)
tree2e0f5ce991fd3d3ad77e61745c84a4ca32b8601d /net/bridge
parentc83b8fab06fc8c80d6440649f117bb7541df5fd0 (diff)
bridge: Add multicast_querier toggle and disable queries by default
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>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_multicast.c20
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_sysfs_br.c18
3 files changed, 40 insertions, 0 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b3647d090e1f..708e84f31888 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -783,6 +783,7 @@ static void br_multicast_send_query(struct net_bridge *br,
783 struct br_ip br_group; 783 struct br_ip br_group;
784 784
785 if (!netif_running(br->dev) || br->multicast_disabled || 785 if (!netif_running(br->dev) || br->multicast_disabled ||
786 !br->multicast_querier ||
786 timer_pending(&br->multicast_querier_timer)) 787 timer_pending(&br->multicast_querier_timer))
787 return; 788 return;
788 789
@@ -1565,6 +1566,7 @@ void br_multicast_init(struct net_bridge *br)
1565 br->hash_max = 512; 1566 br->hash_max = 512;
1566 1567
1567 br->multicast_router = 1; 1568 br->multicast_router = 1;
1569 br->multicast_querier = 0;
1568 br->multicast_last_member_count = 2; 1570 br->multicast_last_member_count = 2;
1569 br->multicast_startup_query_count = 2; 1571 br->multicast_startup_query_count = 2;
1570 1572
@@ -1760,6 +1762,24 @@ unlock:
1760 return err; 1762 return err;
1761} 1763}
1762 1764
1765int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
1766{
1767 val = !!val;
1768
1769 spin_lock_bh(&br->multicast_lock);
1770 if (br->multicast_querier == val)
1771 goto unlock;
1772
1773 br->multicast_querier = val;
1774 if (val)
1775 br_multicast_start_querier(br);
1776
1777unlock:
1778 spin_unlock_bh(&br->multicast_lock);
1779
1780 return 0;
1781}
1782
1763int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) 1783int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
1764{ 1784{
1765 int err = -ENOENT; 1785 int err = -ENOENT;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e1d882257877..f8ffd8c49054 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -224,6 +224,7 @@ struct net_bridge
224 unsigned char multicast_router; 224 unsigned char multicast_router;
225 225
226 u8 multicast_disabled:1; 226 u8 multicast_disabled:1;
227 u8 multicast_querier:1;
227 228
228 u32 hash_elasticity; 229 u32 hash_elasticity;
229 u32 hash_max; 230 u32 hash_max;
@@ -417,6 +418,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val);
417extern int br_multicast_set_port_router(struct net_bridge_port *p, 418extern int br_multicast_set_port_router(struct net_bridge_port *p,
418 unsigned long val); 419 unsigned long val);
419extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); 420extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
421extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
420extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); 422extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
421 423
422static inline bool br_multicast_is_router(struct net_bridge *br) 424static inline bool br_multicast_is_router(struct net_bridge *br)
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 766fd7fb0295..c5c059333eab 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -379,6 +379,23 @@ static ssize_t store_multicast_snooping(struct device *d,
379static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, 379static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
380 show_multicast_snooping, store_multicast_snooping); 380 show_multicast_snooping, store_multicast_snooping);
381 381
382static ssize_t show_multicast_querier(struct device *d,
383 struct device_attribute *attr,
384 char *buf)
385{
386 struct net_bridge *br = to_bridge(d);
387 return sprintf(buf, "%d\n", br->multicast_querier);
388}
389
390static ssize_t store_multicast_querier(struct device *d,
391 struct device_attribute *attr,
392 const char *buf, size_t len)
393{
394 return store_bridge_parm(d, buf, len, br_multicast_set_querier);
395}
396static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR,
397 show_multicast_querier, store_multicast_querier);
398
382static ssize_t show_hash_elasticity(struct device *d, 399static ssize_t show_hash_elasticity(struct device *d,
383 struct device_attribute *attr, char *buf) 400 struct device_attribute *attr, char *buf)
384{ 401{
@@ -702,6 +719,7 @@ static struct attribute *bridge_attrs[] = {
702#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 719#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
703 &dev_attr_multicast_router.attr, 720 &dev_attr_multicast_router.attr,
704 &dev_attr_multicast_snooping.attr, 721 &dev_attr_multicast_snooping.attr,
722 &dev_attr_multicast_querier.attr,
705 &dev_attr_hash_elasticity.attr, 723 &dev_attr_hash_elasticity.attr,
706 &dev_attr_hash_max.attr, 724 &dev_attr_hash_max.attr,
707 &dev_attr_multicast_last_member_count.attr, 725 &dev_attr_multicast_last_member_count.attr,