summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@google.com>2026-06-29 18:11:01 +0000
committerPaolo Abeni <pabeni@redhat.com>2026-07-01 18:42:34 +0200
commiteef9bddc3313b01679c60892825afd2a7a83fba6 (patch)
tree61b746152d900d81ab4146134f5e704d87087a63 /net/ipv4
parent34ea2499389e7a2f1522682e003b257eccda26be (diff)
downloadlinux-next-eef9bddc3313b01679c60892825afd2a7a83fba6.tar.gz
linux-next-eef9bddc3313b01679c60892825afd2a7a83fba6.zip
net: fib_rules: Only hold RTNL for the first IPv4 RTM_NEWRULE.
Now, RTM_DELRULE no longer needs RTNL, and the only RTNL dependant in RTM_NEWRULE is fib_unmerge(), which is called for the first IPv4 rule. Let's add fib_rules_ops.need_rtnl() and hold RTNL only for the first IPv4 rule. Tested: The script below creates 1K rules in parallel in 4K netns, and it got 20x/30x faster for IPv4/IPv6. #!/bin/bash N=4096 F=rules.txt for i in $(seq $N); do ip netns add ns-$i; done printf 'rule add from all table %d\n' {1..1024} > $F for v in 4 6; do echo "=== IPv${v} ===" time { for i in $(seq $N); do nsenter \ --net=/var/run/netns/ns-$i ip -$v -batch $F & done; wait; } done for i in $(seq $N); do ip netns del ns-$i; done rm -f $F Without this series: # ./test.sh === IPv4 === real 0m22.752s user 0m7.834s sys 92m46.721s === IPv6 === real 0m35.181s user 0m8.635s sys 142m30.479s With this series: # ./test.sh === IPv4 === real 0m0.918s user 0m5.675s sys 2m7.024s === IPv6 === real 0m1.214s user 0m7.917s sys 4m19.489s Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260629181226.1929658-10-kuniyu@google.com Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_rules.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 16d202246a36..4edb0dca7be8 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -460,6 +460,11 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
rt_cache_flush(ops->fro_net);
}
+static bool fib4_rule_need_rtnl(struct net *net)
+{
+ return !net->ipv4.fib_has_custom_rules;
+}
+
static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
.family = AF_INET,
.rule_size = sizeof(struct fib4_rule),
@@ -473,6 +478,7 @@ static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
.fill = fib4_rule_fill,
.nlmsg_payload = fib4_rule_nlmsg_payload,
.flush_cache = fib4_rule_flush_cache,
+ .need_rtnl = fib4_rule_need_rtnl,
.nlgroup = RTNLGRP_IPV4_RULE,
.owner = THIS_MODULE,
};