* [PATCH v3 net 0/2] ipv6: Fix two GC issues with permanent routes.
@ 2026-03-09 18:06 Kuniyuki Iwashima
2026-03-09 18:06 ` [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire Kuniyuki Iwashima
2026-03-09 18:06 ` [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist Kuniyuki Iwashima
0 siblings, 2 replies; 6+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-09 18:06 UTC (permalink / raw)
To: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Kui-Feng Lee, Xin Long, Simon Horman, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
Patch 1 fixes the unbounded growth of tb6_gc_hlist due to
permanent routes whose exception routes have all expired.
Patch 2 fixes an issue where exception routes tied to
permanent routes are not properly aged.
Changes:
v3:
Patch 2: Use IS_ENABLED()
v2: https://lore.kernel.org/netdev/20260308032304.1841198-1-kuniyu@google.com/
Patch 2: Fix build failure when CONFIG_IPV6=n (no net->ipv6 definition)
v1: https://lore.kernel.org/netdev/20260307024709.718395-1-kuniyu@google.com/
Kuniyuki Iwashima (2):
ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions
expire.
ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist.
include/net/ip6_fib.h | 19 ++++++++++++++++++-
net/ipv6/addrconf.c | 4 ++--
net/ipv6/ip6_fib.c | 15 +++++++++++++--
net/ipv6/route.c | 2 +-
4 files changed, 34 insertions(+), 6 deletions(-)
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire.
2026-03-09 18:06 [PATCH v3 net 0/2] ipv6: Fix two GC issues with permanent routes Kuniyuki Iwashima
@ 2026-03-09 18:06 ` Kuniyuki Iwashima
2026-03-10 14:08 ` Xin Long
2026-03-09 18:06 ` [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist Kuniyuki Iwashima
1 sibling, 1 reply; 6+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-09 18:06 UTC (permalink / raw)
To: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Kui-Feng Lee, Xin Long, Simon Horman, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
Commit 5eb902b8e719 ("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 cfe82469a00f ("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: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
net/ipv6/ip6_fib.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 9058e71241dc..fadfca49d6b1 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -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;
}
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist.
2026-03-09 18:06 [PATCH v3 net 0/2] ipv6: Fix two GC issues with permanent routes Kuniyuki Iwashima
2026-03-09 18:06 ` [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire Kuniyuki Iwashima
@ 2026-03-09 18:06 ` Kuniyuki Iwashima
2026-03-10 14:09 ` Xin Long
1 sibling, 1 reply; 6+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-09 18:06 UTC (permalink / raw)
To: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Kui-Feng Lee, Xin Long, Simon Horman, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
The cited commit mechanically put fib6_remove_gc_list()
just after every fib6_clean_expires() call.
When a temporary route is promoted to a permanent route,
there may already be exception routes tied to it.
If fib6_remove_gc_list() removes the route from tb6_gc_hlist,
such exception routes will no longer be aged.
Let's replace fib6_remove_gc_list() with a new helper
fib6_may_remove_gc_list() and use fib6_age_exceptions() there.
Note that net->ipv6 is only compiled when CONFIG_IPV6 is
enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded.
Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
v3: Use IS_ENABLED()
v2: Fix build failure when CONFIG_IPV6=n (no net->ipv6 definition)
---
include/net/ip6_fib.h | 19 ++++++++++++++++++-
net/ipv6/addrconf.c | 4 ++--
net/ipv6/ip6_fib.c | 6 +++---
net/ipv6/route.c | 2 +-
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 88b0dd4d8e09..7e91f8f35552 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -507,12 +507,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt,
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
unsigned int flags);
+void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
+ unsigned long now);
void fib6_run_gc(unsigned long expires, struct net *net, bool force);
-
void fib6_gc_cleanup(void);
int fib6_init(void);
+#if IS_ENABLED(CONFIG_IPV6)
/* Add the route to the gc list if it is not already there
*
* The callers should hold f6i->fib6_table->tb6_lock.
@@ -545,6 +547,21 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i)
hlist_del_init(&f6i->gc_link);
}
+static inline void fib6_may_remove_gc_list(struct net *net,
+ struct fib6_info *f6i)
+{
+ struct fib6_gc_args gc_args;
+
+ if (hlist_unhashed(&f6i->gc_link))
+ return;
+
+ gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval),
+ gc_args.more = 0,
+
+ fib6_age_exceptions(f6i, &gc_args, jiffies);
+}
+#endif
+
struct ipv6_route_iter {
struct seq_net_private p;
struct fib6_walker w;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0e55f139e05d..f4e23b543585 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2862,7 +2862,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
fib6_add_gc_list(rt);
} else {
fib6_clean_expires(rt);
- fib6_remove_gc_list(rt);
+ fib6_may_remove_gc_list(net, rt);
}
spin_unlock_bh(&table->tb6_lock);
@@ -4840,7 +4840,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
if (!(flags & RTF_EXPIRES)) {
fib6_clean_expires(f6i);
- fib6_remove_gc_list(f6i);
+ fib6_may_remove_gc_list(net, f6i);
} else {
fib6_set_expires(f6i, expires);
fib6_add_gc_list(f6i);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index fadfca49d6b1..dd26657b6a4a 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
return -EEXIST;
if (!(rt->fib6_flags & RTF_EXPIRES)) {
fib6_clean_expires(iter);
- fib6_remove_gc_list(iter);
+ fib6_may_remove_gc_list(info->nl_net, iter);
} else {
fib6_set_expires(iter, rt->expires);
fib6_add_gc_list(iter);
@@ -2348,8 +2348,8 @@ 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)
+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;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 08cd86f49bf9..cb521700cee7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1033,7 +1033,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
if (!addrconf_finite_timeout(lifetime)) {
fib6_clean_expires(rt);
- fib6_remove_gc_list(rt);
+ fib6_may_remove_gc_list(net, rt);
} else {
fib6_set_expires(rt, jiffies + HZ * lifetime);
fib6_add_gc_list(rt);
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire.
2026-03-09 18:06 ` [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire Kuniyuki Iwashima
@ 2026-03-10 14:08 ` Xin Long
0 siblings, 0 replies; 6+ messages in thread
From: Xin Long @ 2026-03-10 14:08 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Kui-Feng Lee, Simon Horman, Kuniyuki Iwashima,
netdev
On Mon, Mar 9, 2026 at 2:08 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> Commit 5eb902b8e719 ("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 cfe82469a00f ("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: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> ---
> net/ipv6/ip6_fib.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index 9058e71241dc..fadfca49d6b1 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -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;
> }
> --
> 2.53.0.473.g4a7958ca14-goog
>
LGTM, thanks for the fix.
Reviewed-by: Xin Long <lucien.xin@gmail.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist.
2026-03-09 18:06 ` [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist Kuniyuki Iwashima
@ 2026-03-10 14:09 ` Xin Long
2026-03-10 16:01 ` Kuniyuki Iwashima
0 siblings, 1 reply; 6+ messages in thread
From: Xin Long @ 2026-03-10 14:09 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Kui-Feng Lee, Simon Horman, Kuniyuki Iwashima,
netdev
On Mon, Mar 9, 2026 at 2:08 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> The cited commit mechanically put fib6_remove_gc_list()
> just after every fib6_clean_expires() call.
>
> When a temporary route is promoted to a permanent route,
> there may already be exception routes tied to it.
>
> If fib6_remove_gc_list() removes the route from tb6_gc_hlist,
> such exception routes will no longer be aged.
>
> Let's replace fib6_remove_gc_list() with a new helper
> fib6_may_remove_gc_list() and use fib6_age_exceptions() there.
>
> Note that net->ipv6 is only compiled when CONFIG_IPV6 is
> enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded.
>
> Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> ---
> v3: Use IS_ENABLED()
> v2: Fix build failure when CONFIG_IPV6=n (no net->ipv6 definition)
> ---
> include/net/ip6_fib.h | 19 ++++++++++++++++++-
> net/ipv6/addrconf.c | 4 ++--
> net/ipv6/ip6_fib.c | 6 +++---
> net/ipv6/route.c | 2 +-
> 4 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
> index 88b0dd4d8e09..7e91f8f35552 100644
> --- a/include/net/ip6_fib.h
> +++ b/include/net/ip6_fib.h
> @@ -507,12 +507,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt,
> void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
> unsigned int flags);
>
> +void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
> + unsigned long now);
> void fib6_run_gc(unsigned long expires, struct net *net, bool force);
> -
> void fib6_gc_cleanup(void);
>
> int fib6_init(void);
>
> +#if IS_ENABLED(CONFIG_IPV6)
> /* Add the route to the gc list if it is not already there
> *
> * The callers should hold f6i->fib6_table->tb6_lock.
> @@ -545,6 +547,21 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i)
> hlist_del_init(&f6i->gc_link);
> }
>
> +static inline void fib6_may_remove_gc_list(struct net *net,
> + struct fib6_info *f6i)
> +{
> + struct fib6_gc_args gc_args;
> +
> + if (hlist_unhashed(&f6i->gc_link))
> + return;
> +
> + gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval),
> + gc_args.more = 0,
Why is it using comma instead of semicolon here?
> +
> + fib6_age_exceptions(f6i, &gc_args, jiffies);
> +}
> +#endif
> +
> struct ipv6_route_iter {
> struct seq_net_private p;
> struct fib6_walker w;
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 0e55f139e05d..f4e23b543585 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -2862,7 +2862,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
> fib6_add_gc_list(rt);
> } else {
> fib6_clean_expires(rt);
> - fib6_remove_gc_list(rt);
> + fib6_may_remove_gc_list(net, rt);
> }
>
> spin_unlock_bh(&table->tb6_lock);
> @@ -4840,7 +4840,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
>
> if (!(flags & RTF_EXPIRES)) {
> fib6_clean_expires(f6i);
> - fib6_remove_gc_list(f6i);
> + fib6_may_remove_gc_list(net, f6i);
> } else {
> fib6_set_expires(f6i, expires);
> fib6_add_gc_list(f6i);
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index fadfca49d6b1..dd26657b6a4a 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
> return -EEXIST;
> if (!(rt->fib6_flags & RTF_EXPIRES)) {
> fib6_clean_expires(iter);
> - fib6_remove_gc_list(iter);
> + fib6_may_remove_gc_list(info->nl_net, iter);
> } else {
> fib6_set_expires(iter, rt->expires);
> fib6_add_gc_list(iter);
> @@ -2348,8 +2348,8 @@ 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)
> +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;
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 08cd86f49bf9..cb521700cee7 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1033,7 +1033,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
>
> if (!addrconf_finite_timeout(lifetime)) {
> fib6_clean_expires(rt);
> - fib6_remove_gc_list(rt);
> + fib6_may_remove_gc_list(net, rt);
> } else {
> fib6_set_expires(rt, jiffies + HZ * lifetime);
> fib6_add_gc_list(rt);
> --
> 2.53.0.473.g4a7958ca14-goog
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist.
2026-03-10 14:09 ` Xin Long
@ 2026-03-10 16:01 ` Kuniyuki Iwashima
0 siblings, 0 replies; 6+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-10 16:01 UTC (permalink / raw)
To: Xin Long
Cc: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Kui-Feng Lee, Simon Horman, Kuniyuki Iwashima,
netdev
On Tue, Mar 10, 2026 at 7:09 AM Xin Long <lucien.xin@gmail.com> wrote:
>
> On Mon, Mar 9, 2026 at 2:08 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
> >
> > The cited commit mechanically put fib6_remove_gc_list()
> > just after every fib6_clean_expires() call.
> >
> > When a temporary route is promoted to a permanent route,
> > there may already be exception routes tied to it.
> >
> > If fib6_remove_gc_list() removes the route from tb6_gc_hlist,
> > such exception routes will no longer be aged.
> >
> > Let's replace fib6_remove_gc_list() with a new helper
> > fib6_may_remove_gc_list() and use fib6_age_exceptions() there.
> >
> > Note that net->ipv6 is only compiled when CONFIG_IPV6 is
> > enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded.
> >
> > Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.")
> > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> > ---
> > v3: Use IS_ENABLED()
> > v2: Fix build failure when CONFIG_IPV6=n (no net->ipv6 definition)
> > ---
> > include/net/ip6_fib.h | 19 ++++++++++++++++++-
> > net/ipv6/addrconf.c | 4 ++--
> > net/ipv6/ip6_fib.c | 6 +++---
> > net/ipv6/route.c | 2 +-
> > 4 files changed, 24 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
> > index 88b0dd4d8e09..7e91f8f35552 100644
> > --- a/include/net/ip6_fib.h
> > +++ b/include/net/ip6_fib.h
> > @@ -507,12 +507,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt,
> > void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
> > unsigned int flags);
> >
> > +void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
> > + unsigned long now);
> > void fib6_run_gc(unsigned long expires, struct net *net, bool force);
> > -
> > void fib6_gc_cleanup(void);
> >
> > int fib6_init(void);
> >
> > +#if IS_ENABLED(CONFIG_IPV6)
> > /* Add the route to the gc list if it is not already there
> > *
> > * The callers should hold f6i->fib6_table->tb6_lock.
> > @@ -545,6 +547,21 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i)
> > hlist_del_init(&f6i->gc_link);
> > }
> >
> > +static inline void fib6_may_remove_gc_list(struct net *net,
> > + struct fib6_info *f6i)
> > +{
> > + struct fib6_gc_args gc_args;
> > +
> > + if (hlist_unhashed(&f6i->gc_link))
> > + return;
> > +
> > + gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval),
> > + gc_args.more = 0,
> Why is it using comma instead of semicolon here?
Ah, my silly mistake.
I initially used designated initialiser and later moved it down
after adding hlist_unhashed(), but forgot to replace s/,/;/.
I'll update this.
Thanks for catching !
pw-bot: cr
>
> > +
> > + fib6_age_exceptions(f6i, &gc_args, jiffies);
> > +}
> > +#endif
> > +
> > struct ipv6_route_iter {
> > struct seq_net_private p;
> > struct fib6_walker w;
> > diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> > index 0e55f139e05d..f4e23b543585 100644
> > --- a/net/ipv6/addrconf.c
> > +++ b/net/ipv6/addrconf.c
> > @@ -2862,7 +2862,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
> > fib6_add_gc_list(rt);
> > } else {
> > fib6_clean_expires(rt);
> > - fib6_remove_gc_list(rt);
> > + fib6_may_remove_gc_list(net, rt);
> > }
> >
> > spin_unlock_bh(&table->tb6_lock);
> > @@ -4840,7 +4840,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
> >
> > if (!(flags & RTF_EXPIRES)) {
> > fib6_clean_expires(f6i);
> > - fib6_remove_gc_list(f6i);
> > + fib6_may_remove_gc_list(net, f6i);
> > } else {
> > fib6_set_expires(f6i, expires);
> > fib6_add_gc_list(f6i);
> > diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> > index fadfca49d6b1..dd26657b6a4a 100644
> > --- a/net/ipv6/ip6_fib.c
> > +++ b/net/ipv6/ip6_fib.c
> > @@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
> > return -EEXIST;
> > if (!(rt->fib6_flags & RTF_EXPIRES)) {
> > fib6_clean_expires(iter);
> > - fib6_remove_gc_list(iter);
> > + fib6_may_remove_gc_list(info->nl_net, iter);
> > } else {
> > fib6_set_expires(iter, rt->expires);
> > fib6_add_gc_list(iter);
> > @@ -2348,8 +2348,8 @@ 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)
> > +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;
> > diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> > index 08cd86f49bf9..cb521700cee7 100644
> > --- a/net/ipv6/route.c
> > +++ b/net/ipv6/route.c
> > @@ -1033,7 +1033,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
> >
> > if (!addrconf_finite_timeout(lifetime)) {
> > fib6_clean_expires(rt);
> > - fib6_remove_gc_list(rt);
> > + fib6_may_remove_gc_list(net, rt);
> > } else {
> > fib6_set_expires(rt, jiffies + HZ * lifetime);
> > fib6_add_gc_list(rt);
> > --
> > 2.53.0.473.g4a7958ca14-goog
> >
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-10 16:01 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-09 18:06 [PATCH v3 net 0/2] ipv6: Fix two GC issues with permanent routes Kuniyuki Iwashima
2026-03-09 18:06 ` [PATCH v3 net 1/2] ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions expire Kuniyuki Iwashima
2026-03-10 14:08 ` Xin Long
2026-03-09 18:06 ` [PATCH v3 net 2/2] ipv6: Don't remove permanent routes with exceptions from tb6_gc_hlist Kuniyuki Iwashima
2026-03-10 14:09 ` Xin Long
2026-03-10 16:01 ` Kuniyuki Iwashima
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox