diff options
author | Nikolay Aleksandrov <nikolay@cumulusnetworks.com> | 2018-12-05 15:14:24 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-12-05 17:01:51 -0800 |
commit | 19e3a9c90c53479fecaa02307bf2db5ab8b3ffe3 (patch) | |
tree | 02a1154ab53b70ef1eafc301ec79cc4a3f14c3e5 /net/bridge/br_private.h | |
parent | ba5dfaff195557209015add52e57191899ccfca0 (diff) |
net: bridge: convert multicast to generic rhashtable
The bridge multicast code currently uses a custom resizable hashtable
which predates the generic rhashtable interface. It has many
shortcomings compared and duplicates functionality that is presently
available via the generic rhashtable, so this patch removes the custom
rhashtable implementation in favor of the kernel's generic rhashtable.
The hash maximum is kept and the rhashtable's size is used to do a loose
check if it's reached in which case we revert to the old behaviour and
disable further bridge multicast processing. Also now we can support any
hash maximum, doesn't need to be a power of 2.
v3: add non-rcu br_mdb_get variant and use it where multicast_lock is
held to avoid RCU splat, drop hash_max function and just set it
directly
v2: handle when IGMP snooping is undefined, add br_mdb_init/uninit
placeholders
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
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 | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d29f837cd7a2..a0ce0822921c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -213,23 +213,14 @@ struct net_bridge_port_group { }; struct net_bridge_mdb_entry { - struct hlist_node hlist[2]; + struct rhash_head rhnode; struct net_bridge *br; struct net_bridge_port_group __rcu *ports; struct rcu_head rcu; struct timer_list timer; struct br_ip addr; bool host_joined; -}; - -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 hlist_node mdb_node; }; struct net_bridge_port { @@ -400,7 +391,9 @@ struct net_bridge { unsigned long multicast_query_response_interval; unsigned long multicast_startup_query_interval; - struct net_bridge_mdb_htable __rcu *mdb; + struct rhashtable mdb_hash_tbl; + + struct hlist_head mdb_list; struct hlist_head router_list; struct timer_list multicast_router_timer; @@ -659,7 +652,6 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, /* br_multicast.c */ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING -extern unsigned int br_mdb_rehash_seq; int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb, u16 vid); struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, @@ -684,17 +676,16 @@ int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val); int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val); #endif struct net_bridge_mdb_entry * -br_mdb_ip_get(struct net_bridge_mdb_htable *mdb, struct br_ip *dst); +br_mdb_ip_get(struct net_bridge *br, struct br_ip *dst); struct net_bridge_mdb_entry * -br_multicast_new_group(struct net_bridge *br, struct net_bridge_port *port, - struct br_ip *group); +br_multicast_new_group(struct net_bridge *br, struct br_ip *group); void br_multicast_free_pg(struct rcu_head *head); struct net_bridge_port_group * br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, struct net_bridge_port_group __rcu *next, unsigned char flags, const unsigned char *src); -void br_mdb_init(void); -void br_mdb_uninit(void); +int br_mdb_hash_init(struct net_bridge *br); +void br_mdb_hash_fini(struct net_bridge *br); void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, struct br_ip *group, int type, u8 flags); void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, @@ -706,6 +697,8 @@ void br_multicast_uninit_stats(struct net_bridge *br); void br_multicast_get_stats(const struct net_bridge *br, const struct net_bridge_port *p, struct br_mcast_stats *dest); +void br_mdb_init(void); +void br_mdb_uninit(void); #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) @@ -831,6 +824,15 @@ static inline void br_mdb_uninit(void) { } +static inline int br_mdb_hash_init(struct net_bridge *br) +{ + return 0; +} + +static inline void br_mdb_hash_fini(struct net_bridge *br) +{ +} + static inline void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, const struct sk_buff *skb, |