Re: [PATCH net-next v4 01/10] ipv6: add ip6_del_rt_reason()

Ido Schimmel <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <20260803081454.GA573507@shredder>
On Wed, Jul 29, 2026 at 09:07:30PM +0900, Yuyang Huang wrote:
> Add RTA_DEL_REASON and enum rta_del_reason to the rtnetlink uAPI, and
> add ip6_del_rt_reason(), which takes the reason a route is being
> deleted. ip6_del_rt() becomes a wrapper that passes
> RTA_DEL_REASON_UNSPEC, so its callers do not change.
> 
> The reason is unused for now. Subsequent patches propagate it to the
> deletion path and report it on RTM_DELROUTE.
> 
> Signed-off-by: Yuyang Huang <[email protected]>
> ---
>  include/net/ip6_route.h        |  9 +++++++++
>  include/uapi/linux/rtnetlink.h | 17 +++++++++++++++++
>  net/ipv6/route.c               |  8 +++++++-
>  3 files changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 09ffe0f13ce7..92ad5a0d03a2 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -128,12 +128,21 @@ int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
>  int ip6_ins_rt(struct net *net, struct fib6_info *f6i);
>  #if IS_ENABLED(CONFIG_IPV6)
>  int ip6_del_rt(struct net *net, struct fib6_info *f6i, bool skip_notify);
> +int ip6_del_rt_reason(struct net *net, struct fib6_info *f6i, bool skip_notify,
> +		      enum rta_del_reason del_reason);

From Sashiko:

"
This isn't a bug, but was carrying the reason in struct nl_info considered
instead of adding a parallel argument?
"

I did consider it, but it doesn't look like a good fit to carry a route
deletion reason in a generic netlink structure (also used by nexthops).

It later says:

"
One counter-point worth noting: rt6_fill_node() is also reached from dump,
GET and hw-flags paths that have no struct nl_info at all, so an explicit
parameter there is unavoidable either way, and nl_info is shared with
IPv4, MPLS and nexthop code.
"

https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260729120739.47880-1-sigefriedhyy%40gmail.com


>  #else
>  static inline int ip6_del_rt(struct net *net, struct fib6_info *f6i,
>  			     bool skip_notify)
>  {
>  	return -EAFNOSUPPORT;
>  }
> +
> +static inline int ip6_del_rt_reason(struct net *net, struct fib6_info *f6i,
> +				    bool skip_notify,
> +				    enum rta_del_reason del_reason)
> +{
> +	return -EAFNOSUPPORT;
> +}
>  #endif
>  
>  void rt6_flush_exceptions(struct fib6_info *f6i);
> diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
> index 27265fd31e5f..fe00e624f3c3 100644
> --- a/include/uapi/linux/rtnetlink.h
> +++ b/include/uapi/linux/rtnetlink.h
> @@ -399,6 +399,7 @@ enum rtattr_type_t {
>  	RTA_DPORT,
>  	RTA_NH_ID,
>  	RTA_FLOWLABEL,
> +	RTA_DEL_REASON,
>  	__RTA_MAX
>  };
>  
> @@ -407,6 +408,22 @@ enum rtattr_type_t {
>  #define RTM_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
>  #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
>  
> +/* RTA_DEL_REASON: why the kernel deleted the route. u32.
> + * Emitted only on RTM_DELROUTE notifications, and only when the deletion
> + * path records a cause. Absence means either an older kernel or a
> + * deletion path that does not (yet) record its cause - consumers must
> + * treat "absent" and "unspec" identically. New causes may be appended.
> + * Currently only IPv6 deletion paths record a cause.
> + */
> +enum rta_del_reason {
> +	RTA_DEL_REASON_UNSPEC,		/* cause not recorded */
> +	RTA_DEL_REASON_EXPIRED,		/* RTF_EXPIRES lifetime ran out (GC) */
> +	RTA_DEL_REASON_RA_WITHDRAWN,	/* zero-lifetime RA / PIO / RIO */
> +	__RTA_DEL_REASON_MAX
> +};
> +
> +#define RTA_DEL_REASON_MAX (__RTA_DEL_REASON_MAX - 1)

Valid comments from Sashiko:

"
This isn't a bug, but since these names become uAPI on first release, is
the RTA_ prefix the right choice for the payload values?

RTA_ is the established prefix for route attribute ids in enum
rtattr_type_t, and RTA_DEL_REASON is added to that very enum a few lines
above. So RTA_DEL_REASON_EXPIRED reads like an attribute id, and
RTA_DEL_REASON_MAX visually parallels RTA_MAX while meaning something
completely different. Elsewhere the payload value space of an attribute
gets its own prefix, for instance LWTUNNEL_ENCAP_* for RTA_ENCAP_TYPE.

[....]

RTA_DEL_REASON_RA_WITHDRAWN is an IPv6-specific cause placed in the
family-agnostic route attribute value space, and RTA_DEL_REASON_MAX has no
in-tree user by the end of the series (rtm_ipv6_policy has no
RTA_DEL_REASON entry). Would it be worth stating in the comment that the
value space must never be reinterpreted per family, so a later family
cannot reuse the numbers for its own causes?
"

And be aware of:

https://lore.kernel.org/all/83360de7addb13a3b5f4d5e722148f248fdb2ae0.1784884817.git.pabeni@redhat.com/

> +
>  /* RTM_MULTIPATH --- array of struct rtnexthop.
>   *
>   * "struct rtnexthop" describes all necessary nexthop information,
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index a1301334da48..9f82829923ab 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -3994,7 +3994,8 @@ static int __ip6_del_rt(struct fib6_info *rt, struct nl_info *info)
>  	return err;
>  }
>  
> -int ip6_del_rt(struct net *net, struct fib6_info *rt, bool skip_notify)
> +int ip6_del_rt_reason(struct net *net, struct fib6_info *rt, bool skip_notify,
> +		      enum rta_del_reason del_reason)

It's weird to have 'skip_notify' in a function that is supposed to
notify the deletion reason to user space. All the callers except
ip6_del_rt() pass 'false'. Can ip6_del_rt() call __ip6_del_rt() with
'RTA_DEL_REASON_UNSPEC' ?

>  {
>  	struct nl_info info = {
>  		.nl_net = net,
> @@ -4004,6 +4005,11 @@ int ip6_del_rt(struct net *net, struct fib6_info *rt, bool skip_notify)
>  	return __ip6_del_rt(rt, &info);
>  }
>  
> +int ip6_del_rt(struct net *net, struct fib6_info *rt, bool skip_notify)
> +{
> +	return ip6_del_rt_reason(net, rt, skip_notify, RTA_DEL_REASON_UNSPEC);
> +}
> +
>  static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
>  {
>  	struct nl_info *info = &cfg->fc_nlinfo;
> -- 
> 2.43.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.