-
Notifications
You must be signed in to change notification settings - Fork 313
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
route: fix IPv6 ecmp route deleted nexthop matching #382
Conversation
The output were from some strategically places debug prints at the top of I did not touch adding a nexthop, since I didn't observe this case while testing/debugging, and I was unsure if it is fixable, since we would be then potentially adding a nexthop with no associated weight (since new "added" route isn't a multipath route?). All added nexthops had routes with all nexthops in new, so I'm not even sure if this is a case that can happen (anymore). |
I don't find this reference. Do you have a better one? I think it should be just Note that there are many problems with caching of the routes in libnl3. In general, and specifically to IPv6 ECMP routes. Anyway, the patch doesn't make it worse, so ok! Thank you. |
It also would warrant a code comment, about why those are ignored. |
43da423
to
8b0008b
Compare
Oops, looks like I copied the wrong commit hash. Updated with the correct one.
These are currently non-accessible in Regardless, I agree it needs a comment explaining the reasoning.
Do you have any specific issues in mind? I'm open to taking a stab at them, since I'm currently working on trying to work with IPv6 ECMP routes, so knowing about the issues (and maybe even fixing them) would be nice. |
Ah right. But arguably, a code comment also suffices explaining what the
for one, that the identity operator of routes is wrong. See for example Then, handling Finally, as you have noticed, IPv6 ECMP routes are represented quite oddly on the rtnetlink API. In NetworkManger's cache, a IPv6 route is always a singlehop route. The twist is only that a single All in all, it is IMO not possible to maintain a consistent cache based on the current events from kernel. NetworkManager gets it mostly right, by triggering expensive sync-all. It also probably won't fail badly in face of a cache inconsistancy. Patch welcome. But it will require a large effort. |
also, there are cases where kernel will remove a route and not send a RTM_DELROUTE event. Because the user is supposed to understand that from circumstantial events. NetworkManager doesn't want to to do that (make such circumstantial decisions based on potentially invalid cache content). Instead, in such cases it also triggers a re-sync (here. But that doesn't really work for libnl, because the libnl cache is about routes only. Somehow a even for addresses would trigger a resync for the route cache. |
I'll add a comment explaining it. Though I feel moving the But if we do that, it should be done for all objects, not just nexthops.
Ah, that indeed sounds like a lot of work.
Right, I already noticed that deleting a nexthop created via the nexthop API will silently delete all (non-ECMP) routes using it. To fix that, we would need to allow nexthop updates to update the route cache. And probably similar triggers for other events that causes silent route deletion. So far our main use case (for ECMP routes) is listening to netlink and apply routes created by FRR to a switch ASIC, and FRR is nice enough to delete routes before deleting nexthops, for which the current implementation is sufficient. |
True, but IMO that is more of an API ugliness of the compare functions. I don't think that all ATTR flags should become public API. It's partly because |
Oh, I wasn't aware that changes to nexthops can cause (silent) changes to the routes. That's seems bad. NetworkManager doesn't watch the nexthops and would miss such changes. Oh well... |
When the kernel sends a ECMP route update with just the deleted nexthop, the nexthop will have no associated weight, and its flags may indicate that it is dead: route_update: RTM_DELROUTE new route: inet6 default table main type unicast <DEAD,> scope global priority 0x400 protocol 0x9 nexthop via fe80::b226:28ff:fe62:8841 dev port4 <dead,> old route: inet6 default table main type unicast scope global priority 0x400 protocol 0x9 nexthop via fe80::b226:28ff:fe62:8841 dev port4 weight 0 <> nexthop via fe80::fa8e:a1ff:fee0:8344 dev port49 weight 0 <> nexthop via fe80::b226:28ff:fe62:d400 dev port3 weight 0 <> nexthop via fe80::fa8e:a1ff:fee0:8349 dev port54 weight 0 <> Since we are comparing the nexthops strictly with all attributes, we can never match the deleted nexthop. This causes libnl to fail to remove the deleted nexthop from the route, and consequently send out a nop-update and a desync of the route in the cache and in the kernel. Fix this by ignoring NH_ATTR_FLAGS (0x1) and NH_ATTR_WEIGHT (0x2) when comparing nexthops to properly match the deleted one. Fixes: 29b7137 ("route cache: Fix handling of ipv6 multipath routes") Signed-off-by: Jonas Gorski <[email protected]>
8b0008b
to
07d80fc
Compare
Added a comment, and changed the
IIRC this only applies to IPv4, not IPv6, but if you create a nexthop, then add a route via this nexthop (via nhid), then delete the nexthop, you will get a netlink notification about then nexthop being deleted, but not the route itself.
There's another place where having access to the ATTR flags would be benefical: when using the callbacks for cache changes, libnl passes a diff bitmask to the callback on |
Yes, I am not saying it's useless. But it would mean to expose (and commit) to quite a large new API (all the attributes), which limits future changes. It's high effort to expose this, and to maintain. Unless there is a strong request, better don't... |
When the kernel sends a ECMP route update with just the deleted nexthop, the nexthop will have no associated weight, and its flags may indicate that it is dead: route_update: RTM_DELROUTE new route: inet6 default table main type unicast <DEAD,> scope global priority 0x400 protocol 0x9 nexthop via fe80::b226:28ff:fe62:8841 dev port4 <dead,> old route: inet6 default table main type unicast scope global priority 0x400 protocol 0x9 nexthop via fe80::b226:28ff:fe62:8841 dev port4 weight 0 <> nexthop via fe80::fa8e:a1ff:fee0:8344 dev port49 weight 0 <> nexthop via fe80::b226:28ff:fe62:d400 dev port3 weight 0 <> nexthop via fe80::fa8e:a1ff:fee0:8349 dev port54 weight 0 <> Since we are comparing the nexthops strictly with all attributes, we can never match the deleted nexthop. This causes libnl to fail to remove the deleted nexthop from the route, and consequently send out a nop-update and a desync of the route in the cache and in the kernel. Fix this by ignoring NH_ATTR_FLAGS (0x1) and NH_ATTR_WEIGHT (0x2) when comparing nexthops to properly match the deleted one. Fixes: 29b7137 ("route cache: Fix handling of ipv6 multipath routes") Signed-off-by: Jonas Gorski <[email protected]> #382
Right, so if I would propose doing it, I would only do so with an actual user. Our product currently does all the comparisons itself, and would profit from having access to the meaning of the diff, but we currently don't have the resources for the rather large conversion to change this without an actual gain in functionality, just efficiency. |
merged. Thank you!!! |
It might not be that much effort. Just move the defines to public headers, and give them a consistent, good name. E.g. |
When the kernel sends a ECMP route update with just the deleted nexthop, the nexthop will have no associated weight, and its flags may indicate that it is dead:
Since we are comparing the nexthops strictly with all attributes, we can never match the deleted nexthop. This causes libnl to fail to remove the deleted nexthop from the route, and consequently send out a nop-update and a desync of the route in the cache and in the kernel.
Fix this by ignoring
NH_ATTR_FLAGS
(0x1
) andNH_ATTR_WEIGHT
(0x2
) when comparing nexthops to properly match the deleted one.Fixes: 29b7137 ("route cache: Fix handling of ipv6 multipath routes")