On Sun, Jul 19, 2026 at 3:53 PM Ido Schimmel <[email protected]> wrote:
> Please expand more on the motivation: Which user space application is
> going to consume this information and what is it going to do with it?

Thanks for the review, let me add more background information.

My current use case comes from Android devices, but I think it is a
general problem that any consumer device running Linux will face,
especially on Wi-Fi networks (multicast delivery on Wi-Fi is not
guaranteed, e.g. frames can be lost around DTIM for clients in power
save mode).

On Android, the userspace NetworkStack process listens on
RTMGRP_IPV6_ROUTE and today treats any loss of the IPv6 default route
as "router lost". To prevent the device from repeatedly gaining and
losing IPv6 connectivity on a badly configured network (e.g. a
misconfigured RA interval), when it detects the device is on a
dual-stack network with working IPv4 connectivity, it defensively
clears accept_ra_defrtr and restarts IPv6. The intention is to stop
userspace apps from continuing to use broken global IPv6 connectivity
(while keeping link-local IPv6 working). However, if the route was
withdrawn by a zero-lifetime RA (some ISPs do this intentionally for
various reconfiguration reasons), that reaction is wrong - with
accept_ra_defrtr off, IPv6 never recovers when the router advertises
again. If the route genuinely expired, the defensive reaction is
right, since the router failed to refresh it in time.

We tried to fix this in userspace but found we cannot get the needed
information from the kernel. RTM_NEWROUTE carries the initial route
lifetime (in rta_cacheinfo), but when a later RA refreshes the
lifetime, the kernel does not resend RTM_NEWROUTE. So to distinguish
the cause of an RTM_DELROUTE, userspace would have to open a raw
socket, listen to RAs, and track lifetimes itself. That is not ideal:
this logic already exists in the kernel, and userspace should not
need to replicate it.

I also considered sending RTM_NEWROUTE on every RA lifetime update,
but that would be spammy and is technically wrong (a lifetime update
does not add a new route, so it should not trigger RTM_NEWROUTE).

I think RTA_DEL_REASON is the architecturally correct fix: it tells
userspace why the route was deleted so it can react accordingly. In
our use case, NetworkStack should defensively disable global IPv6
only on RTA_DEL_REASON_EXPIRED, and take no action on
RTA_DEL_REASON_RA_WITHDRAWN since that is RFC-compliant behavior.

Feel free to let me know if more background is needed. If this use
case makes sense, I will summarize it in the v2 commit message.

> Also, Sashiko has some valid comments. Please take a look.

Here is the reply to the sashiko's feedback.

>Does this new attribute violate the Netlink uAPI guidelines for integer
>types? The guidelines state we should avoid integer types smaller than 32
>bits since they save no memory due to 4-byte attribute alignment padding,
>unless the value is a fixed protocol header field.
>Should this be defined as a u32?
...
>Since this deletion reason is a software classification and not a compact
>protocol field, it has no natural requirement to be 8-bit. Would it be
>better to document and serialize this as a 32-bit integer to prevent
>artificially limiting the enum space for future additions?
...
>If the attribute type in the YAML spec is updated to u32, this call to
>nla_put_u8() in rt6_fill_node() would also need to be updated to
>nla_put_u32() to match the 32-bit width.

Good point, given u8 saves nothing, will change it to u32 in v2.

>Will this operation cause a TypeError crash during test execution?
>In Python 3, using the subtraction operator between a set and a dict_keys
>object raises an unsupported operand type error. Since the caller
>ipv6_route_del_reason_ra_withdrawn() passes a set for the want parameter,
>want - seen.keys() will crash the test.
>Should this be converted to a set first, such as want - set(seen.keys())?

I don't think this is a bug (dict_keys is a set-like view) and the
test passes correctly in my local test. But the suggested form reads
better, so I'll apply it in v2.

Thanks,

Yuyang

Reply via email to