diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-02-27 14:41:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 03:48:45 -0500 |
commit | eb1d16414339a6e113d89e2cca2556005d7ce919 (patch) | |
tree | b6c49f870cc36241a894a8c723a38e224d41464b /net/bridge/br_private.h | |
parent | 025d89c27f54c69cd0e51666d88aada33666bb6c (diff) |
bridge: Add core IGMP snooping support
This patch adds the core functionality of IGMP snooping support
without actually hooking it up. So this patch should be a no-op
as far as the bridge's external behaviour is concerned.
All the new code and data is controlled by the Kconfig option
BRIDGE_IGMP_SNOOPING. A run-time toggle is also available.
The multicast switching is done using an hash table that is
lockless on the read-side through RCU. On the write-side the
new multicast_lock is used for all operations. The hash table
supports dynamic growth/rehashing.
The hash table will be rehashed if any chain length exceeds a
preset limit. If rehashing does not reduce the maximum chain
length then snooping will be disabled.
These features may be added in future (in no particular order):
* IGMPv3 source support
* Non-querier router detection
* IPv6
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_private.h')
-rw-r--r-- | net/bridge/br_private.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fad5a2669d34..44345c9afdd3 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -57,6 +57,41 @@ struct net_bridge_fdb_entry | |||
57 | unsigned char is_static; | 57 | unsigned char is_static; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | struct net_bridge_port_group { | ||
61 | struct net_bridge_port *port; | ||
62 | struct net_bridge_port_group *next; | ||
63 | struct hlist_node mglist; | ||
64 | struct rcu_head rcu; | ||
65 | struct timer_list timer; | ||
66 | struct timer_list query_timer; | ||
67 | __be32 addr; | ||
68 | u32 queries_sent; | ||
69 | }; | ||
70 | |||
71 | struct net_bridge_mdb_entry | ||
72 | { | ||
73 | struct hlist_node hlist[2]; | ||
74 | struct hlist_node mglist; | ||
75 | struct net_bridge *br; | ||
76 | struct net_bridge_port_group *ports; | ||
77 | struct rcu_head rcu; | ||
78 | struct timer_list timer; | ||
79 | struct timer_list query_timer; | ||
80 | __be32 addr; | ||
81 | u32 queries_sent; | ||
82 | }; | ||
83 | |||
84 | struct net_bridge_mdb_htable | ||
85 | { | ||
86 | struct hlist_head *mhash; | ||
87 | struct rcu_head rcu; | ||
88 | struct net_bridge_mdb_htable *old; | ||
89 | u32 size; | ||
90 | u32 max; | ||
91 | u32 secret; | ||
92 | u32 ver; | ||
93 | }; | ||
94 | |||
60 | struct net_bridge_port | 95 | struct net_bridge_port |
61 | { | 96 | { |
62 | struct net_bridge *br; | 97 | struct net_bridge *br; |
@@ -84,6 +119,15 @@ struct net_bridge_port | |||
84 | 119 | ||
85 | unsigned long flags; | 120 | unsigned long flags; |
86 | #define BR_HAIRPIN_MODE 0x00000001 | 121 | #define BR_HAIRPIN_MODE 0x00000001 |
122 | |||
123 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
124 | u32 multicast_startup_queries_sent; | ||
125 | unsigned char multicast_router; | ||
126 | struct timer_list multicast_router_timer; | ||
127 | struct timer_list multicast_query_timer; | ||
128 | struct hlist_head mglist; | ||
129 | struct hlist_node rlist; | ||
130 | #endif | ||
87 | }; | 131 | }; |
88 | 132 | ||
89 | struct net_bridge | 133 | struct net_bridge |
@@ -124,6 +168,35 @@ struct net_bridge | |||
124 | unsigned char topology_change; | 168 | unsigned char topology_change; |
125 | unsigned char topology_change_detected; | 169 | unsigned char topology_change_detected; |
126 | 170 | ||
171 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
172 | unsigned char multicast_router; | ||
173 | |||
174 | u8 multicast_disabled:1; | ||
175 | |||
176 | u32 hash_elasticity; | ||
177 | u32 hash_max; | ||
178 | |||
179 | u32 multicast_last_member_count; | ||
180 | u32 multicast_startup_queries_sent; | ||
181 | u32 multicast_startup_query_count; | ||
182 | |||
183 | unsigned long multicast_last_member_interval; | ||
184 | unsigned long multicast_membership_interval; | ||
185 | unsigned long multicast_querier_interval; | ||
186 | unsigned long multicast_query_interval; | ||
187 | unsigned long multicast_query_response_interval; | ||
188 | unsigned long multicast_startup_query_interval; | ||
189 | |||
190 | spinlock_t multicast_lock; | ||
191 | struct net_bridge_mdb_htable *mdb; | ||
192 | struct hlist_head router_list; | ||
193 | struct hlist_head mglist; | ||
194 | |||
195 | struct timer_list multicast_router_timer; | ||
196 | struct timer_list multicast_querier_timer; | ||
197 | struct timer_list multicast_query_timer; | ||
198 | #endif | ||
199 | |||
127 | struct timer_list hello_timer; | 200 | struct timer_list hello_timer; |
128 | struct timer_list tcn_timer; | 201 | struct timer_list tcn_timer; |
129 | struct timer_list topology_change_timer; | 202 | struct timer_list topology_change_timer; |
@@ -133,6 +206,8 @@ struct net_bridge | |||
133 | 206 | ||
134 | struct br_input_skb_cb { | 207 | struct br_input_skb_cb { |
135 | struct net_device *brdev; | 208 | struct net_device *brdev; |
209 | int igmp; | ||
210 | int mrouters_only; | ||
136 | }; | 211 | }; |
137 | 212 | ||
138 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) | 213 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) |
@@ -204,6 +279,70 @@ extern struct sk_buff *br_handle_frame(struct net_bridge_port *p, | |||
204 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 279 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
205 | extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg); | 280 | extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg); |
206 | 281 | ||
282 | /* br_multicast.c */ | ||
283 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
284 | extern int br_multicast_rcv(struct net_bridge *br, | ||
285 | struct net_bridge_port *port, | ||
286 | struct sk_buff *skb); | ||
287 | extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | ||
288 | struct sk_buff *skb); | ||
289 | extern void br_multicast_add_port(struct net_bridge_port *port); | ||
290 | extern void br_multicast_del_port(struct net_bridge_port *port); | ||
291 | extern void br_multicast_enable_port(struct net_bridge_port *port); | ||
292 | extern void br_multicast_disable_port(struct net_bridge_port *port); | ||
293 | extern void br_multicast_init(struct net_bridge *br); | ||
294 | extern void br_multicast_open(struct net_bridge *br); | ||
295 | extern void br_multicast_stop(struct net_bridge *br); | ||
296 | #else | ||
297 | static inline int br_multicast_rcv(struct net_bridge *br, | ||
298 | struct net_bridge_port *port, | ||
299 | struct sk_buff *skb) | ||
300 | { | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | ||
305 | struct sk_buff *skb) | ||
306 | { | ||
307 | return NULL; | ||
308 | } | ||
309 | |||
310 | static inline void br_multicast_add_port(struct net_bridge_port *port) | ||
311 | { | ||
312 | } | ||
313 | |||
314 | static inline void br_multicast_del_port(struct net_bridge_port *port) | ||
315 | { | ||
316 | } | ||
317 | |||
318 | static inline void br_multicast_enable_port(struct net_bridge_port *port) | ||
319 | { | ||
320 | } | ||
321 | |||
322 | static inline void br_multicast_disable_port(struct net_bridge_port *port) | ||
323 | { | ||
324 | } | ||
325 | |||
326 | static inline void br_multicast_init(struct net_bridge *br) | ||
327 | { | ||
328 | } | ||
329 | |||
330 | static inline void br_multicast_open(struct net_bridge *br) | ||
331 | { | ||
332 | } | ||
333 | |||
334 | static inline void br_multicast_stop(struct net_bridge *br) | ||
335 | { | ||
336 | } | ||
337 | #endif | ||
338 | |||
339 | static inline bool br_multicast_is_router(struct net_bridge *br) | ||
340 | { | ||
341 | return br->multicast_router == 2 || | ||
342 | (br->multicast_router == 1 && | ||
343 | timer_pending(&br->multicast_router_timer)); | ||
344 | } | ||
345 | |||
207 | /* br_netfilter.c */ | 346 | /* br_netfilter.c */ |
208 | #ifdef CONFIG_BRIDGE_NETFILTER | 347 | #ifdef CONFIG_BRIDGE_NETFILTER |
209 | extern int br_netfilter_init(void); | 348 | extern int br_netfilter_init(void); |