aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_private.h
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-02-27 19:41:45 +0000
committerDavid S. Miller <davem@davemloft.net>2010-02-28 00:48:45 -0800
commiteb1d16414339a6e113d89e2cca2556005d7ce919 (patch)
treeb6c49f870cc36241a894a8c723a38e224d41464b /net/bridge/br_private.h
parent025d89c27f54c69cd0e51666d88aada33666bb6c (diff)
downloadkernel_samsung_smdk4412-eb1d16414339a6e113d89e2cca2556005d7ce919.zip
kernel_samsung_smdk4412-eb1d16414339a6e113d89e2cca2556005d7ce919.tar.gz
kernel_samsung_smdk4412-eb1d16414339a6e113d89e2cca2556005d7ce919.tar.bz2
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.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index fad5a26..44345c9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -57,6 +57,41 @@ struct net_bridge_fdb_entry
unsigned char is_static;
};
+struct net_bridge_port_group {
+ struct net_bridge_port *port;
+ struct net_bridge_port_group *next;
+ struct hlist_node mglist;
+ struct rcu_head rcu;
+ struct timer_list timer;
+ struct timer_list query_timer;
+ __be32 addr;
+ u32 queries_sent;
+};
+
+struct net_bridge_mdb_entry
+{
+ struct hlist_node hlist[2];
+ struct hlist_node mglist;
+ struct net_bridge *br;
+ struct net_bridge_port_group *ports;
+ struct rcu_head rcu;
+ struct timer_list timer;
+ struct timer_list query_timer;
+ __be32 addr;
+ u32 queries_sent;
+};
+
+struct net_bridge_mdb_htable
+{
+ struct hlist_head *mhash;
+ struct rcu_head rcu;
+ struct net_bridge_mdb_htable *old;
+ u32 size;
+ u32 max;
+ u32 secret;
+ u32 ver;
+};
+
struct net_bridge_port
{
struct net_bridge *br;
@@ -84,6 +119,15 @@ struct net_bridge_port
unsigned long flags;
#define BR_HAIRPIN_MODE 0x00000001
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+ u32 multicast_startup_queries_sent;
+ unsigned char multicast_router;
+ struct timer_list multicast_router_timer;
+ struct timer_list multicast_query_timer;
+ struct hlist_head mglist;
+ struct hlist_node rlist;
+#endif
};
struct net_bridge
@@ -124,6 +168,35 @@ struct net_bridge
unsigned char topology_change;
unsigned char topology_change_detected;
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+ unsigned char multicast_router;
+
+ u8 multicast_disabled:1;
+
+ u32 hash_elasticity;
+ u32 hash_max;
+
+ u32 multicast_last_member_count;
+ u32 multicast_startup_queries_sent;
+ u32 multicast_startup_query_count;
+
+ unsigned long multicast_last_member_interval;
+ unsigned long multicast_membership_interval;
+ unsigned long multicast_querier_interval;
+ unsigned long multicast_query_interval;
+ unsigned long multicast_query_response_interval;
+ unsigned long multicast_startup_query_interval;
+
+ spinlock_t multicast_lock;
+ struct net_bridge_mdb_htable *mdb;
+ struct hlist_head router_list;
+ struct hlist_head mglist;
+
+ struct timer_list multicast_router_timer;
+ struct timer_list multicast_querier_timer;
+ struct timer_list multicast_query_timer;
+#endif
+
struct timer_list hello_timer;
struct timer_list tcn_timer;
struct timer_list topology_change_timer;
@@ -133,6 +206,8 @@ struct net_bridge
struct br_input_skb_cb {
struct net_device *brdev;
+ int igmp;
+ int mrouters_only;
};
#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,
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg);
+/* br_multicast.c */
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+extern int br_multicast_rcv(struct net_bridge *br,
+ struct net_bridge_port *port,
+ struct sk_buff *skb);
+extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
+ struct sk_buff *skb);
+extern void br_multicast_add_port(struct net_bridge_port *port);
+extern void br_multicast_del_port(struct net_bridge_port *port);
+extern void br_multicast_enable_port(struct net_bridge_port *port);
+extern void br_multicast_disable_port(struct net_bridge_port *port);
+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);
+#else
+static inline int br_multicast_rcv(struct net_bridge *br,
+ struct net_bridge_port *port,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
+ struct sk_buff *skb)
+{
+ return NULL;
+}
+
+static inline void br_multicast_add_port(struct net_bridge_port *port)
+{
+}
+
+static inline void br_multicast_del_port(struct net_bridge_port *port)
+{
+}
+
+static inline void br_multicast_enable_port(struct net_bridge_port *port)
+{
+}
+
+static inline void br_multicast_disable_port(struct net_bridge_port *port)
+{
+}
+
+static inline void br_multicast_init(struct net_bridge *br)
+{
+}
+
+static inline void br_multicast_open(struct net_bridge *br)
+{
+}
+
+static inline void br_multicast_stop(struct net_bridge *br)
+{
+}
+#endif
+
+static inline bool br_multicast_is_router(struct net_bridge *br)
+{
+ return br->multicast_router == 2 ||
+ (br->multicast_router == 1 &&
+ timer_pending(&br->multicast_router_timer));
+}
+
/* br_netfilter.c */
#ifdef CONFIG_BRIDGE_NETFILTER
extern int br_netfilter_init(void);