Merge branch 'net-bridge-multicast-per-port-eht-hosts-limit'

Nikolay Aleksandrov says:

====================
net: bridge: multicast: per-port EHT hosts limit

This set adds a simple configurable per-port EHT tracked hosts limit.
Patch 01 adds a default limit of 512 tracked hosts per-port, since the EHT
changes are still only in net-next that shouldn't be a problem. Then
patch 02 adds the ability to configure and retrieve the hosts limit
and to retrieve the current number of tracked hosts per port.
Let's be on the safe side and limit the number of tracked hosts by
default while allowing the user to increase that limit if needed.
====================

Link: https://lore.kernel.org/r/20210126093533.441338-1-razor@blackwall.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2021-01-27 17:40:36 -08:00
commit c7f3489bfc
8 changed files with 100 additions and 2 deletions

View File

@ -525,6 +525,8 @@ enum {
IFLA_BRPORT_BACKUP_PORT,
IFLA_BRPORT_MRP_RING_OPEN,
IFLA_BRPORT_MRP_IN_OPEN,
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)

View File

@ -1608,6 +1608,7 @@ static void br_mc_disabled_update(struct net_device *dev, bool value)
int br_multicast_add_port(struct net_bridge_port *port)
{
port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
timer_setup(&port->multicast_router_timer,
br_multicast_router_expired, 0);

View File

@ -127,6 +127,8 @@ static void __eht_destroy_host(struct net_bridge_group_eht_host *eht_host)
{
WARN_ON(!hlist_empty(&eht_host->set_entries));
br_multicast_eht_hosts_dec(eht_host->pg);
rb_erase(&eht_host->rb_node, &eht_host->pg->eht_host_tree);
RB_CLEAR_NODE(&eht_host->rb_node);
kfree(eht_host);
@ -257,6 +259,9 @@ __eht_lookup_create_host(struct net_bridge_port_group *pg,
return this;
}
if (br_multicast_eht_hosts_over_limit(pg))
return NULL;
eht_host = kzalloc(sizeof(*eht_host), GFP_ATOMIC);
if (!eht_host)
return NULL;
@ -269,6 +274,8 @@ __eht_lookup_create_host(struct net_bridge_port_group *pg,
rb_link_node(&eht_host->rb_node, parent, link);
rb_insert_color(&eht_host->rb_node, &pg->eht_host_tree);
br_multicast_eht_hosts_inc(pg);
return eht_host;
}
@ -854,3 +861,18 @@ bool br_multicast_eht_handle(struct net_bridge_port_group *pg,
out:
return changed;
}
int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p,
u32 eht_hosts_limit)
{
struct net_bridge *br = p->br;
if (!eht_hosts_limit)
return -EINVAL;
spin_lock_bh(&br->multicast_lock);
p->multicast_eht_hosts_limit = eht_hosts_limit;
spin_unlock_bh(&br->multicast_lock);
return 0;
}

View File

@ -18,6 +18,7 @@
#include "br_private_stp.h"
#include "br_private_cfm.h"
#include "br_private_tunnel.h"
#include "br_private_mcast_eht.h"
static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
u32 filter_mask)
@ -199,6 +200,8 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */
+ nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_RING_OPEN */
+ nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_IN_OPEN */
+ nla_total_size(sizeof(u32)) /* IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT */
+ nla_total_size(sizeof(u32)) /* IFLA_BRPORT_MCAST_EHT_HOSTS_CNT */
+ 0;
}
@ -283,7 +286,11 @@ static int br_port_fill_attrs(struct sk_buff *skb,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
if (nla_put_u8(skb, IFLA_BRPORT_MULTICAST_ROUTER,
p->multicast_router))
p->multicast_router) ||
nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
p->multicast_eht_hosts_limit) ||
nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
p->multicast_eht_hosts_cnt))
return -EMSGSIZE;
#endif
@ -820,6 +827,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 },
[IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 },
[IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 },
[IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 },
};
/* Change the state of the port and notify spanning tree */
@ -955,6 +963,15 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
if (err)
return err;
}
if (tb[IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT]) {
u32 hlimit;
hlimit = nla_get_u32(tb[IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT]);
err = br_multicast_eht_set_hosts_limit(p, hlimit);
if (err)
return err;
}
#endif
if (tb[IFLA_BRPORT_GROUP_FWD_MASK]) {

View File

@ -310,6 +310,8 @@ struct net_bridge_port {
#if IS_ENABLED(CONFIG_IPV6)
struct bridge_mcast_own_query ip6_own_query;
#endif /* IS_ENABLED(CONFIG_IPV6) */
u32 multicast_eht_hosts_limit;
u32 multicast_eht_hosts_cnt;
unsigned char multicast_router;
struct bridge_mcast_stats __percpu *mcast_stats;
struct timer_list multicast_router_timer;

View File

@ -4,6 +4,8 @@
#ifndef _BR_PRIVATE_MCAST_EHT_H_
#define _BR_PRIVATE_MCAST_EHT_H_
#define BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT 512
union net_bridge_eht_addr {
__be32 ip4;
#if IS_ENABLED(CONFIG_IPV6)
@ -47,6 +49,7 @@ struct net_bridge_group_eht_set {
struct net_bridge_mcast_gc mcast_gc;
};
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
void br_multicast_eht_clean_sets(struct net_bridge_port_group *pg);
bool br_multicast_eht_handle(struct net_bridge_port_group *pg,
void *h_addr,
@ -54,6 +57,8 @@ bool br_multicast_eht_handle(struct net_bridge_port_group *pg,
u32 nsrcs,
size_t addr_size,
int grec_type);
int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p,
u32 eht_hosts_limit);
static inline bool
br_multicast_eht_should_del_pg(const struct net_bridge_port_group *pg)
@ -62,4 +67,27 @@ br_multicast_eht_should_del_pg(const struct net_bridge_port_group *pg)
RB_EMPTY_ROOT(&pg->eht_host_tree));
}
static inline bool
br_multicast_eht_hosts_over_limit(const struct net_bridge_port_group *pg)
{
const struct net_bridge_port *p = pg->key.port;
return !!(p->multicast_eht_hosts_cnt >= p->multicast_eht_hosts_limit);
}
static inline void br_multicast_eht_hosts_inc(struct net_bridge_port_group *pg)
{
struct net_bridge_port *p = pg->key.port;
p->multicast_eht_hosts_cnt++;
}
static inline void br_multicast_eht_hosts_dec(struct net_bridge_port_group *pg)
{
struct net_bridge_port *p = pg->key.port;
p->multicast_eht_hosts_cnt--;
}
#endif /* CONFIG_BRIDGE_IGMP_SNOOPING */
#endif /* _BR_PRIVATE_MCAST_EHT_H_ */

View File

@ -16,6 +16,7 @@
#include <linux/sched/signal.h>
#include "br_private.h"
#include "br_private_mcast_eht.h"
struct brport_attribute {
struct attribute attr;
@ -245,6 +246,29 @@ static int store_multicast_router(struct net_bridge_port *p,
static BRPORT_ATTR(multicast_router, 0644, show_multicast_router,
store_multicast_router);
static ssize_t show_multicast_eht_hosts_limit(struct net_bridge_port *p,
char *buf)
{
return sprintf(buf, "%u\n", p->multicast_eht_hosts_limit);
}
static int store_multicast_eht_hosts_limit(struct net_bridge_port *p,
unsigned long v)
{
return br_multicast_eht_set_hosts_limit(p, v);
}
static BRPORT_ATTR(multicast_eht_hosts_limit, 0644,
show_multicast_eht_hosts_limit,
store_multicast_eht_hosts_limit);
static ssize_t show_multicast_eht_hosts_cnt(struct net_bridge_port *p,
char *buf)
{
return sprintf(buf, "%u\n", p->multicast_eht_hosts_cnt);
}
static BRPORT_ATTR(multicast_eht_hosts_cnt, 0444, show_multicast_eht_hosts_cnt,
NULL);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST);
#endif
@ -274,6 +298,8 @@ static const struct brport_attribute *brport_attrs[] = {
&brport_attr_multicast_router,
&brport_attr_multicast_fast_leave,
&brport_attr_multicast_to_unicast,
&brport_attr_multicast_eht_hosts_limit,
&brport_attr_multicast_eht_hosts_cnt,
#endif
&brport_attr_proxyarp,
&brport_attr_proxyarp_wifi,

View File

@ -55,7 +55,7 @@
#include <net/net_namespace.h>
#define RTNL_MAX_TYPE 50
#define RTNL_SLAVE_MAX_TYPE 36
#define RTNL_SLAVE_MAX_TYPE 40
struct rtnl_link {
rtnl_doit_func doit;