]>
Commit | Line | Data |
---|---|---|
1 | From c5c23260594c5701af66ef754916775ba6a46bbc Mon Sep 17 00:00:00 2001 | |
2 | From: Herbert Xu <herbert@gondor.apana.org.au> | |
3 | Date: Fri, 13 Apr 2012 02:37:42 +0000 | |
4 | Subject: bridge: Add multicast_querier toggle and disable queries by default | |
5 | ||
6 | Sending general queries was implemented as an optimisation to speed | |
7 | up convergence on start-up. In order to prevent interference with | |
8 | multicast routers a zero source address has to be used. | |
9 | ||
10 | Unfortunately these packets appear to cause some multicast-aware | |
11 | switches to misbehave, e.g., by disrupting multicast packets to us. | |
12 | ||
13 | Since the multicast snooping feature still functions without sending | |
14 | our own queries, this patch will change the default to not send | |
15 | queries. | |
16 | ||
17 | For those that need queries in order to speed up convergence on start-up, | |
18 | a toggle is provided to restore the previous behaviour. | |
19 | ||
20 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> | |
21 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
22 | --- | |
23 | diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c | |
24 | index b3647d0..708e84f 100644 | |
25 | --- a/net/bridge/br_multicast.c | |
26 | +++ b/net/bridge/br_multicast.c | |
27 | @@ -783,6 +783,7 @@ static void br_multicast_send_query(struct net_bridge *br, | |
28 | struct br_ip br_group; | |
29 | ||
30 | if (!netif_running(br->dev) || br->multicast_disabled || | |
31 | + !br->multicast_querier || | |
32 | timer_pending(&br->multicast_querier_timer)) | |
33 | return; | |
34 | ||
35 | @@ -1565,6 +1566,7 @@ void br_multicast_init(struct net_bridge *br) | |
36 | br->hash_max = 512; | |
37 | ||
38 | br->multicast_router = 1; | |
39 | + br->multicast_querier = 0; | |
40 | br->multicast_last_member_count = 2; | |
41 | br->multicast_startup_query_count = 2; | |
42 | ||
43 | @@ -1760,6 +1762,24 @@ unlock: | |
44 | return err; | |
45 | } | |
46 | ||
47 | +int br_multicast_set_querier(struct net_bridge *br, unsigned long val) | |
48 | +{ | |
49 | + val = !!val; | |
50 | + | |
51 | + spin_lock_bh(&br->multicast_lock); | |
52 | + if (br->multicast_querier == val) | |
53 | + goto unlock; | |
54 | + | |
55 | + br->multicast_querier = val; | |
56 | + if (val) | |
57 | + br_multicast_start_querier(br); | |
58 | + | |
59 | +unlock: | |
60 | + spin_unlock_bh(&br->multicast_lock); | |
61 | + | |
62 | + return 0; | |
63 | +} | |
64 | + | |
65 | int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) | |
66 | { | |
67 | int err = -ENOENT; | |
68 | diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h | |
69 | index e1d8822..f8ffd8c 100644 | |
70 | --- a/net/bridge/br_private.h | |
71 | +++ b/net/bridge/br_private.h | |
72 | @@ -224,6 +224,7 @@ struct net_bridge | |
73 | unsigned char multicast_router; | |
74 | ||
75 | u8 multicast_disabled:1; | |
76 | + u8 multicast_querier:1; | |
77 | ||
78 | u32 hash_elasticity; | |
79 | u32 hash_max; | |
80 | @@ -417,6 +418,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); | |
81 | extern int br_multicast_set_port_router(struct net_bridge_port *p, | |
82 | unsigned long val); | |
83 | extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); | |
84 | +extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val); | |
85 | extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); | |
86 | ||
87 | static inline bool br_multicast_is_router(struct net_bridge *br) | |
88 | diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c | |
89 | index 766fd7f..c5c0593 100644 | |
90 | --- a/net/bridge/br_sysfs_br.c | |
91 | +++ b/net/bridge/br_sysfs_br.c | |
92 | @@ -379,6 +379,23 @@ static ssize_t store_multicast_snooping(struct device *d, | |
93 | static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, | |
94 | show_multicast_snooping, store_multicast_snooping); | |
95 | ||
96 | +static ssize_t show_multicast_querier(struct device *d, | |
97 | + struct device_attribute *attr, | |
98 | + char *buf) | |
99 | +{ | |
100 | + struct net_bridge *br = to_bridge(d); | |
101 | + return sprintf(buf, "%d\n", br->multicast_querier); | |
102 | +} | |
103 | + | |
104 | +static ssize_t store_multicast_querier(struct device *d, | |
105 | + struct device_attribute *attr, | |
106 | + const char *buf, size_t len) | |
107 | +{ | |
108 | + return store_bridge_parm(d, buf, len, br_multicast_set_querier); | |
109 | +} | |
110 | +static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR, | |
111 | + show_multicast_querier, store_multicast_querier); | |
112 | + | |
113 | static ssize_t show_hash_elasticity(struct device *d, | |
114 | struct device_attribute *attr, char *buf) | |
115 | { | |
116 | @@ -702,6 +719,7 @@ static struct attribute *bridge_attrs[] = { | |
117 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | |
118 | &dev_attr_multicast_router.attr, | |
119 | &dev_attr_multicast_snooping.attr, | |
120 | + &dev_attr_multicast_querier.attr, | |
121 | &dev_attr_hash_elasticity.attr, | |
122 | &dev_attr_hash_max.attr, | |
123 | &dev_attr_multicast_last_member_count.attr, | |
124 | -- | |
125 | cgit v0.9.1 |