summaryrefslogtreecommitdiff
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@amazon.com>2025-02-27 20:23:19 -0800
committerJakub Kicinski <kuba@kernel.org>2025-03-03 15:04:09 -0800
commitcfc47029fa124e5e04411fb1dbd3726db90fd346 (patch)
tree20b42aa20d930fb4183510d91dc93e05e350188b /net/ipv4/fib_semantics.c
parentfa336adc100e1d76a50da782c3e9abb1541a72f3 (diff)
ipv4: fib: Allocate fib_info_hash[] during netns initialisation.
We will allocate fib_info_hash[] and fib_info_laddrhash[] for each netns. Currently, fib_info_hash[] is allocated when the first route is added. Let's move the first allocation to a new __net_init function. Note that we must call fib4_semantics_exit() in fib_net_exit_batch() because ->exit() is called earlier than ->exit_batch(). Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20250228042328.96624-4-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 23aae379ba42..b7e2023bf742 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1420,28 +1420,21 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
}
#endif
- err = -ENOBUFS;
-
if (fib_info_cnt >= fib_info_hash_size) {
+ unsigned int new_hash_bits = fib_info_hash_bits + 1;
struct hlist_head *new_info_hash;
- unsigned int new_hash_bits;
-
- if (!fib_info_hash_bits)
- new_hash_bits = 4;
- else
- new_hash_bits = fib_info_hash_bits + 1;
new_info_hash = fib_info_hash_alloc(new_hash_bits);
if (new_info_hash)
fib_info_hash_move(new_info_hash, 1 << new_hash_bits);
-
- if (!fib_info_hash_size)
- goto failure;
}
fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
- if (!fi)
+ if (!fi) {
+ err = -ENOBUFS;
goto failure;
+ }
+
fi->fib_metrics = ip_fib_metrics_init(cfg->fc_mx, cfg->fc_mx_len, extack);
if (IS_ERR(fi->fib_metrics)) {
err = PTR_ERR(fi->fib_metrics);
@@ -1862,7 +1855,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local)
struct fib_info *fi;
int ret = 0;
- if (!fib_info_laddrhash || local == 0)
+ if (!local)
return 0;
head = fib_info_laddrhash_bucket(net, local);
@@ -2264,3 +2257,29 @@ check_saddr:
fl4->saddr = inet_select_addr(l3mdev, 0, RT_SCOPE_LINK);
}
}
+
+int __net_init fib4_semantics_init(struct net *net)
+{
+ unsigned int hash_bits = 4;
+
+ if (!net_eq(net, &init_net))
+ return 0;
+
+ fib_info_hash = fib_info_hash_alloc(hash_bits);
+ if (!fib_info_hash)
+ return -ENOMEM;
+
+ fib_info_hash_bits = hash_bits;
+ fib_info_hash_size = 1 << hash_bits;
+ fib_info_laddrhash = fib_info_hash + fib_info_hash_size;
+
+ return 0;
+}
+
+void __net_exit fib4_semantics_exit(struct net *net)
+{
+ if (!net_eq(net, &init_net))
+ return;
+
+ fib_info_hash_free(fib_info_hash);
+}