]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipv4: Link IPv4 address to per-netns hash table.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 8 Oct 2024 17:29:03 +0000 (10:29 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 10 Oct 2024 03:08:07 +0000 (20:08 -0700)
As a prep for per-netns RTNL conversion, we want to namespacify
the IPv4 address hash table and the GC work.

Let's allocate the per-netns IPv4 address hash table to
net->ipv4.inet_addr_lst and link IPv4 addresses into it.

The actual users will be converted later.

Note that the IPv6 address hash table is already namespacified.

Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20241008172906.1326-2-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/inetdevice.h
include/net/netns/ipv4.h
net/ipv4/devinet.c

index cb5280e6cc219106bcc55972dac850edf34988ff..d0c2bf67a9b06c21b5acc157825ea6f1f958b0b6 100644 (file)
@@ -142,6 +142,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 
 struct in_ifaddr {
        struct hlist_node       hash;
+       struct hlist_node       addr_lst;
        struct in_ifaddr        __rcu *ifa_next;
        struct in_device        *ifa_dev;
        struct rcu_head         rcu_head;
index 276f622f3516871c438be27bafe61c039445b335..29eba2eaaa26d13f0d15c6d20ee716033e81985d 100644 (file)
@@ -270,5 +270,6 @@ struct netns_ipv4 {
 
        atomic_t        rt_genid;
        siphash_key_t   ip_id_key;
+       struct hlist_head       *inet_addr_lst;
 };
 #endif
index ab76744383cf3827a7b1d8118bb22879adc7f9a2..059807a627a6a40e31b985c1e4eb0e042cc3cce7 100644 (file)
@@ -134,11 +134,13 @@ static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa)
 
        ASSERT_RTNL();
        hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]);
+       hlist_add_head_rcu(&ifa->addr_lst, &net->ipv4.inet_addr_lst[hash]);
 }
 
 static void inet_hash_remove(struct in_ifaddr *ifa)
 {
        ASSERT_RTNL();
+       hlist_del_init_rcu(&ifa->addr_lst);
        hlist_del_init_rcu(&ifa->hash);
 }
 
@@ -228,6 +230,7 @@ static struct in_ifaddr *inet_alloc_ifa(struct in_device *in_dev)
        ifa->ifa_dev = in_dev;
 
        INIT_HLIST_NODE(&ifa->hash);
+       INIT_HLIST_NODE(&ifa->addr_lst);
 
        return ifa;
 }
@@ -2663,14 +2666,21 @@ static struct ctl_table ctl_forward_entry[] = {
 
 static __net_init int devinet_init_net(struct net *net)
 {
-       int err;
-       struct ipv4_devconf *all, *dflt;
 #ifdef CONFIG_SYSCTL
-       struct ctl_table *tbl;
        struct ctl_table_header *forw_hdr;
+       struct ctl_table *tbl;
 #endif
+       struct ipv4_devconf *all, *dflt;
+       int err;
+       int i;
 
        err = -ENOMEM;
+       net->ipv4.inet_addr_lst = kmalloc_array(IN4_ADDR_HSIZE,
+                                               sizeof(struct hlist_head),
+                                               GFP_KERNEL);
+       if (!net->ipv4.inet_addr_lst)
+               goto err_alloc_hash;
+
        all = kmemdup(&ipv4_devconf, sizeof(ipv4_devconf), GFP_KERNEL);
        if (!all)
                goto err_alloc_all;
@@ -2731,6 +2741,9 @@ static __net_init int devinet_init_net(struct net *net)
        net->ipv4.forw_hdr = forw_hdr;
 #endif
 
+       for (i = 0; i < IN4_ADDR_HSIZE; i++)
+               INIT_HLIST_HEAD(&net->ipv4.inet_addr_lst[i]);
+
        net->ipv4.devconf_all = all;
        net->ipv4.devconf_dflt = dflt;
        return 0;
@@ -2748,6 +2761,8 @@ err_alloc_ctl:
 err_alloc_dflt:
        kfree(all);
 err_alloc_all:
+       kfree(net->ipv4.inet_addr_lst);
+err_alloc_hash:
        return err;
 }
 
@@ -2766,6 +2781,7 @@ static __net_exit void devinet_exit_net(struct net *net)
 #endif
        kfree(net->ipv4.devconf_dflt);
        kfree(net->ipv4.devconf_all);
+       kfree(net->ipv4.inet_addr_lst);
 }
 
 static __net_initdata struct pernet_operations devinet_ops = {