mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-06 19:50:36 +01:00
core: fix nm_netns_ip_route_ecmp_commit() to return regular single-hop route
nm_netns_ip_route_ecmp_commit() returns the ECMP routes that didn't find a merge-partner. It expects NML3Cfg to configure such routes in platform. Note that these routes have a positive "weight", which was used for tracking the ECMP information in NML3Cfg and NMNetns. But in kernel, single-hop routes don't have a weight. All routes in NMPlatform will have a zero weight. While it somewhat works to call nm_platform_ip_route_add() with a single-hop route of non-zero weight, the result will be a different(!) route. This means for example that nm_platform_ip_route_sync() will search the NMPlatform cache for whether the routes exist, but in the cache single-hop routes with positive weight never exist. Previously this happened and nm_platform_ip_route_sync() would not delete those routes when it should. It's also important because NML3Cfg tracks the object states of routes that it wants to configure, vs routes in kernel (NMPlatform cache). The route in kernel has a weight of zero. The route we want to configure must also have a weight of zero. The solution is that nm_netns_ip_route_ecmp_commit() does not tell NML3Cfg to add a route, that cannot be added. Instead, it must first normalize the weight to zero, to have a "regular" single-hop route. Fixes:5b5ce42682('nm-netns: track ECMP routes') (cherry picked from commit7a748ae556)
This commit is contained in:
parent
4600a811fb
commit
a39b897759
1 changed files with 24 additions and 1 deletions
|
|
@ -910,6 +910,8 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self,
|
|||
}
|
||||
|
||||
if (route->n_nexthops <= 1) {
|
||||
NMPObject *route_clone;
|
||||
|
||||
/* This is a single hop route. Return it to the caller. */
|
||||
if (!*out_singlehop_routes) {
|
||||
/* Note that the returned array does not own a reference. This
|
||||
|
|
@ -918,7 +920,28 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self,
|
|||
*out_singlehop_routes =
|
||||
g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
|
||||
}
|
||||
g_ptr_array_add(*out_singlehop_routes, (gpointer) nmp_object_ref(route_obj));
|
||||
|
||||
/* We have here a IPv4 single-hop route. For internal tracking purposes,
|
||||
* this route has a positive "weight" (which was used to mark it as a candidate
|
||||
* for ECMP merging). Now we want to return this route to NML3Cfg and add it
|
||||
* as regular single-hop routes.
|
||||
*
|
||||
* A single-hop route in kernel always has a "weight" of zero. This route
|
||||
* cannot be added as-is. Well, if we would, then the result would be
|
||||
* a different(!) route (with a zero "weight").
|
||||
*
|
||||
* Anticipate that and normalize the route now to be a regular single-hop
|
||||
* route (with weight zero). nm_platform_ip_route_normalize() does that.
|
||||
* We really want to return a regular route here, not the route with a positive
|
||||
* weight that exists for internal tracking purposes.
|
||||
*/
|
||||
nm_assert(NMP_OBJECT_GET_TYPE(route_obj) == NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||
nm_assert(route_obj->ip4_route.weight > 0u);
|
||||
|
||||
route_clone = nmp_object_clone(route_obj, FALSE);
|
||||
nm_platform_ip_route_normalize(AF_INET, NMP_OBJECT_CAST_IP_ROUTE(route_clone));
|
||||
g_ptr_array_add(*out_singlehop_routes, route_clone);
|
||||
|
||||
if (changed) {
|
||||
_LOGT("ecmp-route: single-hop %s",
|
||||
nmp_object_to_string(route_obj,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue