From: Jesper Dangaard Brouer Similar to the IPv4 inet_addr_lst hash table, IPv6 also uses a fixed 256-bucket hash table for address lookups. On hosts with many IPv6 addresses, this results in long hash chains walked under RCU. The inet6_addr_lst table is used in the route lookup path when no output interface is specified (oif == 0): udpv6_sendmsg ip6_sk_dst_lookup_flow ip6_dst_lookup_tail ip6_route_output -> fib6 lookup __rt6_device_match ipv6_chk_addr <-- walks inet6_addr_lst Add CONFIG_INET6_ADDR_HASH_BUCKETS (default 256, range 64-16384, EXPERT) so hosts with many addresses can size the table appropriately. The value is rounded up to the nearest power of 2 at compile time via order_base_2(). Memory cost is one hlist_head pointer per bucket per net namespace. Reported-by: Ivan Babrou Signed-off-by: Jesper Dangaard Brouer --- net/ipv6/Kconfig | 15 +++++++++++++++ net/ipv6/addrconf.c | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index b8f9a8c0302e..963fa0e1a014 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -238,6 +238,21 @@ config IPV6_FOU_TUNNEL default NET_FOU_IP_TUNNELS && IPV6_FOU select IPV6_TUNNEL +config INET6_ADDR_HASH_BUCKETS + int "IPv6 address hash table size" if EXPERT + range 64 16384 + default 256 + help + Number of hash buckets for looking up local IPv6 addresses, + e.g. in ipv6_chk_addr() and related callers. Rounded up to + the nearest power of 2. + + Hosts with many IPv6 addresses benefit from a larger table to + reduce hash chain lengths. + + The default of 256 is fine for most systems. A value of 1024 + suits hosts with ~500+ addresses. + config IPV6_MULTIPLE_TABLES bool "IPv6: Multiple Routing Tables" select FIB_RULES diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0e55f139e05d..dad08f0733ef 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -144,7 +144,7 @@ static int ipv6_generate_stable_address(struct in6_addr *addr, u8 dad_count, const struct inet6_dev *idev); -#define IN6_ADDR_HSIZE_SHIFT 8 +#define IN6_ADDR_HSIZE_SHIFT order_base_2(CONFIG_INET6_ADDR_HASH_BUCKETS) #define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT) static void addrconf_verify(struct net *net); -- 2.43.0