Commit 21a216a8 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

ipv6/addrconf: allocate a per netns hash table



Add a per netns hash table and a dedicated spinlock,
first step to get rid of the global inet6_addr_lst[] one.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b2309a71
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@ struct netns_ipv6 {
	struct sock             *tcp_sk;
	struct sock             *igmp_sk;
	struct sock		*mc_autojoin_sk;

	struct hlist_head	*inet6_addr_lst;
	spinlock_t		addrconf_hash_lock;

#ifdef CONFIG_IPV6_MROUTE
#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
	struct mr_table		*mrt6;
+20 −0
Original line number Diff line number Diff line
@@ -7111,6 +7111,13 @@ static int __net_init addrconf_init_net(struct net *net)
	int err = -ENOMEM;
	struct ipv6_devconf *all, *dflt;

	spin_lock_init(&net->ipv6.addrconf_hash_lock);
	net->ipv6.inet6_addr_lst = kcalloc(IN6_ADDR_HSIZE,
					   sizeof(struct hlist_head),
					   GFP_KERNEL);
	if (!net->ipv6.inet6_addr_lst)
		goto err_alloc_addr;

	all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
	if (!all)
		goto err_alloc_all;
@@ -7172,11 +7179,15 @@ static int __net_init addrconf_init_net(struct net *net)
err_alloc_dflt:
	kfree(all);
err_alloc_all:
	kfree(net->ipv6.inet6_addr_lst);
err_alloc_addr:
	return err;
}

static void __net_exit addrconf_exit_net(struct net *net)
{
	int i;

#ifdef CONFIG_SYSCTL
	__addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
				     NETCONFA_IFINDEX_DEFAULT);
@@ -7187,6 +7198,15 @@ static void __net_exit addrconf_exit_net(struct net *net)
	net->ipv6.devconf_dflt = NULL;
	kfree(net->ipv6.devconf_all);
	net->ipv6.devconf_all = NULL;

	/*
	 *	Check hash table, then free it.
	 */
	for (i = 0; i < IN6_ADDR_HSIZE; i++)
		WARN_ON_ONCE(!hlist_empty(&net->ipv6.inet6_addr_lst[i]));

	kfree(net->ipv6.inet6_addr_lst);
	net->ipv6.inet6_addr_lst = NULL;
}

static struct pernet_operations addrconf_ops = {