Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default RA lifetime not set in route #428

Open
ColinMcInnes opened this issue Jan 6, 2025 · 12 comments
Open

default RA lifetime not set in route #428

ColinMcInnes opened this issue Jan 6, 2025 · 12 comments

Comments

@ColinMcInnes
Copy link
Contributor

ColinMcInnes commented Jan 6, 2025

the default route is being sent by the router via RA, and they are setting a lifetime of 1800s and a hop limit of 64. However this is not showing up in the ip -6 route show.

$ ip -6 route show ::/0
default via fe80::2efa:a2ff:fe90:e275 dev eth0 proto ra metric 1002 pref medium

$ dhcpcd -U eth0
reason=ROUTERADVERT
interface=eth0
protocol=ra
nd1_from=fe80::2efa:a2ff:fe90:e275
nd1_acquired=1100
nd1_now=1152
nd1_hoplimit=64
nd1_flags=M
nd1_lifetime=1800
nd1_source_address=2cfaa290e275
nd1_prefix_information1_length=64
nd1_prefix_information1_flags=L
nd1_prefix_information1_vltime=2592000
nd1_prefix_information1_pltime=604800
nd1_prefix_information1_prefix=2001:192:168:228::

dhcpcd 10.1.0 linux

here's what it looks like if I use ISC's dhclient 4.4.3

default via fe80::2efa:a2ff:fe90:e275 dev eth0 proto ra metric 1024 expires 1609sec hoplimit 64 pref medium

Any ideas where to start looking?

@ColinMcInnes
Copy link
Contributor Author

Found it, in if-linux and ipv6. I'll create a patch to send it to netlink.

ColinMcInnes added a commit to ColinMcInnes/dhcpcd that referenced this issue Jan 8, 2025
Sends route lifetime to NETLINK RTA_EXPIRES

Partially addresses NetworkConfiguration#428
@rsmarples
Copy link
Member

ISC dhclient doesn't set any routes, just addresses.
Something Else (TM) must be setting the routes :)

dhcpcd will expire the routes anyway, so any fix we do is purely cosmetic (unless of course dhcpcd has stopped for whatever reason)

@ColinMcInnes
Copy link
Contributor Author

dhcpcd will expire the routes anyway, so any fix we do is purely cosmetic (unless of course dhcpcd has stopped for whatever reason)

Yes, I agree it's purely cosmetic. I have some other code that reports the current route lifetime from nl, so this is why I'm adding it for informational purposes.

ISC dhclient doesn't set any routes, just addresses. Something Else (TM) must be setting the routes :)

I found that out once I started looking deeper. :)

@rsmarples
Copy link
Member

If it helps, hop limit is defined here in the kernel: https://elixir.bootlin.com/linux/v6.12.6/source/include/uapi/linux/rtnetlink.h#L485

So it's a property of RTA_METRICS. Good luck!

@juw
Copy link

juw commented Jan 24, 2025

Unfortunately the change to add the lifetime to the route is not only cosmetic. It seems, that the lifetime does not get updated once a new RA is received and hence the route will expire, removed and only then re-added once a new RA is received. While before this did not happen.

@ColinMcInnes
Copy link
Contributor Author

ColinMcInnes commented Jan 24, 2025

Unfortunately the change to add the lifetime to the route is not only cosmetic. It seems, that the lifetime does not get updated once a new RA is received and hence the route will expire, removed and only then re-added once a new RA is received. While before this did not happen.

That's no good. I suspect what was happening before was it was effectively setting "infinite" lifetime for default route.

I can replicate this. I think it needs a couple of fixes

  • At router expiry, dhcpcd should try to solicit new (add an eloop similar to lease expiry?)
  • When RA received, update acquired time to "now" because we've seen a new RA.
$ date; journalctl -u dhc* | grep ROUTER | tail -n 2; ip -6 route show ::/0
Fri Jan 24 10:10:41 -06 2025
Jan 24 09:56:34 eth0: executing: /usr/libexec/dhcpcd-run-hooks ROUTERADVERT
Jan 24 10:01:04 eth0: executing: /usr/libexec/dhcpcd-run-hooks ROUTERADVERT
default via fe80::2efa:a2ff:fe90:e275 dev eth0 proto ra metric 1002 expires 1223sec pref medium
$ date; journalctl -u dhc* | grep ROUTER | tail -n 2; ip -6 route show ::/0
Fri Jan 24 10:11:04 -06 2025
Jan 24 10:01:04 eth0: executing: /usr/libexec/dhcpcd-run-hooks ROUTERADVERT
Jan 24 10:10:54 eth0: executing: /usr/libexec/dhcpcd-run-hooks ROUTERADVERT
default via fe80::2efa:a2ff:fe90:e275 dev eth0 proto ra metric 1002 expires 1200sec pref medium

@rsmarples
Copy link
Member

We need to adjust the logic in route.c to always change the route if we have rt_expires set.

@ColinMcInnes
Copy link
Contributor Author

RA spec doesn't define anything about refresh time, the standard is to remove the default route when it expires, and the kernel handles this correctly.

What we're missing is dhcpcd does not send an RS to renew it.

@perkelix
Copy link
Contributor

perkelix commented Jan 24, 2025

An issue that is probably related: dhcpcd assigns the same value to valid_lft and preferred_lft, which makes IPv6 completely drop out when they reach zero. This shouldn't happen if preferred_lft remains at around 80% of valid_lft and a RS is sent as soon as preferred_lft reaches zero.

@ColinMcInnes
Copy link
Contributor Author

I see the issue. We copy the existing route from NL, including the expiry. We only update the expiry when we're writing out a new route.

When we're adding an existing route, we should update the expiry to our new internal value rather than re-use the NL value.

@ColinMcInnes
Copy link
Contributor Author

I see the issue. We copy the existing route from NL, including the expiry. We only update the expiry when we're writing out a new route.

Ok, maybe not, we're loading up the old route to see if it exists, and then copying the route record from internal and back out to NL.

So I think we just need to fix the route lifetime logic?

@ColinMcInnes ColinMcInnes changed the title default RA lifetime and hoplimit not set in route default RA lifetime not set in route Jan 24, 2025
@ColinMcInnes
Copy link
Contributor Author

I think I may have found it. We don't check acquired time when determining if a route has changed, and since the MTU is the same, we skip updating the route.

Having it record and check the acquired time for a route should allow us to determine it's been updated and the new expiry can be pushed out to netlink.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants