Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+100 -2
+2
include/uapi/linux/if_link.h
··· 525 525 IFLA_BRPORT_BACKUP_PORT, 526 526 IFLA_BRPORT_MRP_RING_OPEN, 527 527 IFLA_BRPORT_MRP_IN_OPEN, 528 + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, 529 + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, 528 530 __IFLA_BRPORT_MAX 529 531 }; 530 532 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
+1
net/bridge/br_multicast.c
··· 1608 1608 int br_multicast_add_port(struct net_bridge_port *port) 1609 1609 { 1610 1610 port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; 1611 + port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT; 1611 1612 1612 1613 timer_setup(&port->multicast_router_timer, 1613 1614 br_multicast_router_expired, 0);
+22
net/bridge/br_multicast_eht.c
··· 127 127 { 128 128 WARN_ON(!hlist_empty(&eht_host->set_entries)); 129 129 130 + br_multicast_eht_hosts_dec(eht_host->pg); 131 + 130 132 rb_erase(&eht_host->rb_node, &eht_host->pg->eht_host_tree); 131 133 RB_CLEAR_NODE(&eht_host->rb_node); 132 134 kfree(eht_host); ··· 259 257 return this; 260 258 } 261 259 260 + if (br_multicast_eht_hosts_over_limit(pg)) 261 + return NULL; 262 + 262 263 eht_host = kzalloc(sizeof(*eht_host), GFP_ATOMIC); 263 264 if (!eht_host) 264 265 return NULL; ··· 273 268 274 269 rb_link_node(&eht_host->rb_node, parent, link); 275 270 rb_insert_color(&eht_host->rb_node, &pg->eht_host_tree); 271 + 272 + br_multicast_eht_hosts_inc(pg); 276 273 277 274 return eht_host; 278 275 } ··· 860 853 861 854 out: 862 855 return changed; 856 + } 857 + 858 + int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p, 859 + u32 eht_hosts_limit) 860 + { 861 + struct net_bridge *br = p->br; 862 + 863 + if (!eht_hosts_limit) 864 + return -EINVAL; 865 + 866 + spin_lock_bh(&br->multicast_lock); 867 + p->multicast_eht_hosts_limit = eht_hosts_limit; 868 + spin_unlock_bh(&br->multicast_lock); 869 + 870 + return 0; 863 871 }
+18 -1
net/bridge/br_netlink.c
··· 18 18 #include "br_private_stp.h" 19 19 #include "br_private_cfm.h" 20 20 #include "br_private_tunnel.h" 21 + #include "br_private_mcast_eht.h" 21 22 22 23 static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg, 23 24 u32 filter_mask) ··· 200 199 + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */ 201 200 + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_RING_OPEN */ 202 201 + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_IN_OPEN */ 202 + + nla_total_size(sizeof(u32)) /* IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT */ 203 + + nla_total_size(sizeof(u32)) /* IFLA_BRPORT_MCAST_EHT_HOSTS_CNT */ 203 204 + 0; 204 205 } 205 206 ··· 286 283 287 284 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 288 285 if (nla_put_u8(skb, IFLA_BRPORT_MULTICAST_ROUTER, 289 - p->multicast_router)) 286 + p->multicast_router) || 287 + nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, 288 + p->multicast_eht_hosts_limit) || 289 + nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, 290 + p->multicast_eht_hosts_cnt)) 290 291 return -EMSGSIZE; 291 292 #endif 292 293 ··· 827 820 [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 }, 828 821 [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, 829 822 [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, 823 + [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 }, 830 824 }; 831 825 832 826 /* Change the state of the port and notify spanning tree */ ··· 960 952 u8 mcast_router = nla_get_u8(tb[IFLA_BRPORT_MULTICAST_ROUTER]); 961 953 962 954 err = br_multicast_set_port_router(p, mcast_router); 955 + if (err) 956 + return err; 957 + } 958 + 959 + if (tb[IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT]) { 960 + u32 hlimit; 961 + 962 + hlimit = nla_get_u32(tb[IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT]); 963 + err = br_multicast_eht_set_hosts_limit(p, hlimit); 963 964 if (err) 964 965 return err; 965 966 }
+2
net/bridge/br_private.h
··· 310 310 #if IS_ENABLED(CONFIG_IPV6) 311 311 struct bridge_mcast_own_query ip6_own_query; 312 312 #endif /* IS_ENABLED(CONFIG_IPV6) */ 313 + u32 multicast_eht_hosts_limit; 314 + u32 multicast_eht_hosts_cnt; 313 315 unsigned char multicast_router; 314 316 struct bridge_mcast_stats __percpu *mcast_stats; 315 317 struct timer_list multicast_router_timer;
+28
net/bridge/br_private_mcast_eht.h
··· 4 4 #ifndef _BR_PRIVATE_MCAST_EHT_H_ 5 5 #define _BR_PRIVATE_MCAST_EHT_H_ 6 6 7 + #define BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT 512 8 + 7 9 union net_bridge_eht_addr { 8 10 __be32 ip4; 9 11 #if IS_ENABLED(CONFIG_IPV6) ··· 49 47 struct net_bridge_mcast_gc mcast_gc; 50 48 }; 51 49 50 + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 52 51 void br_multicast_eht_clean_sets(struct net_bridge_port_group *pg); 53 52 bool br_multicast_eht_handle(struct net_bridge_port_group *pg, 54 53 void *h_addr, ··· 57 54 u32 nsrcs, 58 55 size_t addr_size, 59 56 int grec_type); 57 + int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p, 58 + u32 eht_hosts_limit); 60 59 61 60 static inline bool 62 61 br_multicast_eht_should_del_pg(const struct net_bridge_port_group *pg) ··· 66 61 return !!((pg->key.port->flags & BR_MULTICAST_FAST_LEAVE) && 67 62 RB_EMPTY_ROOT(&pg->eht_host_tree)); 68 63 } 64 + 65 + static inline bool 66 + br_multicast_eht_hosts_over_limit(const struct net_bridge_port_group *pg) 67 + { 68 + const struct net_bridge_port *p = pg->key.port; 69 + 70 + return !!(p->multicast_eht_hosts_cnt >= p->multicast_eht_hosts_limit); 71 + } 72 + 73 + static inline void br_multicast_eht_hosts_inc(struct net_bridge_port_group *pg) 74 + { 75 + struct net_bridge_port *p = pg->key.port; 76 + 77 + p->multicast_eht_hosts_cnt++; 78 + } 79 + 80 + static inline void br_multicast_eht_hosts_dec(struct net_bridge_port_group *pg) 81 + { 82 + struct net_bridge_port *p = pg->key.port; 83 + 84 + p->multicast_eht_hosts_cnt--; 85 + } 86 + #endif /* CONFIG_BRIDGE_IGMP_SNOOPING */ 69 87 70 88 #endif /* _BR_PRIVATE_MCAST_EHT_H_ */
+26
net/bridge/br_sysfs_if.c
··· 16 16 #include <linux/sched/signal.h> 17 17 18 18 #include "br_private.h" 19 + #include "br_private_mcast_eht.h" 19 20 20 21 struct brport_attribute { 21 22 struct attribute attr; ··· 246 245 static BRPORT_ATTR(multicast_router, 0644, show_multicast_router, 247 246 store_multicast_router); 248 247 248 + static ssize_t show_multicast_eht_hosts_limit(struct net_bridge_port *p, 249 + char *buf) 250 + { 251 + return sprintf(buf, "%u\n", p->multicast_eht_hosts_limit); 252 + } 253 + 254 + static int store_multicast_eht_hosts_limit(struct net_bridge_port *p, 255 + unsigned long v) 256 + { 257 + return br_multicast_eht_set_hosts_limit(p, v); 258 + } 259 + static BRPORT_ATTR(multicast_eht_hosts_limit, 0644, 260 + show_multicast_eht_hosts_limit, 261 + store_multicast_eht_hosts_limit); 262 + 263 + static ssize_t show_multicast_eht_hosts_cnt(struct net_bridge_port *p, 264 + char *buf) 265 + { 266 + return sprintf(buf, "%u\n", p->multicast_eht_hosts_cnt); 267 + } 268 + static BRPORT_ATTR(multicast_eht_hosts_cnt, 0444, show_multicast_eht_hosts_cnt, 269 + NULL); 270 + 249 271 BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE); 250 272 BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST); 251 273 #endif ··· 298 274 &brport_attr_multicast_router, 299 275 &brport_attr_multicast_fast_leave, 300 276 &brport_attr_multicast_to_unicast, 277 + &brport_attr_multicast_eht_hosts_limit, 278 + &brport_attr_multicast_eht_hosts_cnt, 301 279 #endif 302 280 &brport_attr_proxyarp, 303 281 &brport_attr_proxyarp_wifi,
+1 -1
net/core/rtnetlink.c
··· 55 55 #include <net/net_namespace.h> 56 56 57 57 #define RTNL_MAX_TYPE 50 58 - #define RTNL_SLAVE_MAX_TYPE 36 58 + #define RTNL_SLAVE_MAX_TYPE 40 59 59 60 60 struct rtnl_link { 61 61 rtnl_doit_func doit;