ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire.

Commit 5eb902b8e7 ("net/ipv6: Remove expired routes with a
separated list of routes.") introduced a per-table GC list and
changed GC to iterate over that list instead of traversing
the entire route table.

However, it forgot to add permanent routes to tb6_gc_hlist
when exception routes are added.

Commit cfe82469a0 ("ipv6: add exception routes to GC list
in rt6_insert_exception") fixed that issue but introduced
another one.

Even after all exception routes expire, the permanent routes
remain in tb6_gc_hlist, potentially negating the performance
benefits intended by the initial change.

Let's count gc_args->more before and after rt6_age_exceptions()
and remove the permanent route when the delta is 0.

Note that the next patch will reuse fib6_age_exceptions().

Fixes: cfe82469a0 ("ipv6: add exception routes to GC list in rt6_insert_exception")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20260320072317.2561779-2-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Kuniyuki Iwashima
2026-03-20 07:22:59 +00:00
committed by Jakub Kicinski
parent bc0151c59e
commit 6af51e9f31

View File

@@ -2348,6 +2348,17 @@ static void fib6_flush_trees(struct net *net)
/*
* Garbage collection
*/
static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
unsigned long now)
{
bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires;
int old_more = gc_args->more;
rt6_age_exceptions(rt, gc_args, now);
if (!may_expire && old_more == gc_args->more)
fib6_remove_gc_list(rt);
}
static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args)
{
@@ -2370,7 +2381,7 @@ static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args)
* Note, that clones are aged out
* only if they are not in use now.
*/
rt6_age_exceptions(rt, gc_args, now);
fib6_age_exceptions(rt, gc_args, now);
return 0;
}