summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-11-28 15:20:33 +0100
committerThomas Haller <thaller@redhat.com>2023-11-29 11:24:53 +0100
commitca7cbf6feabd475d5f4b8032f4650a47ef9174ce (patch)
tree3c3f8cd568483894d8df68858d9d70b1649377ae
parent389ac096e3810d56b744065af26ffdb854b72792 (diff)
core: fix nm_netns_ip_route_ecmp_commit() to return regular single-hop routeth/tmp7
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. The proper 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: 5b5ce4268211 ('nm-netns: track ECMP routes')
-rw-r--r--src/core/nm-netns.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c
index 7c279cafc3..e0bd19bbe0 100644
--- a/src/core/nm-netns.c
+++ b/src/core/nm-netns.c
@@ -916,6 +916,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
@@ -924,7 +926,30 @@ 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(route_obj->ip4_route.weight > 0u);
+ nm_assert(NMP_OBJECT_GET_TYPE(route_obj) == NMP_OBJECT_TYPE_IP4_ROUTE);
+
+ route_clone = nmp_object_clone(route_obj, FALSE);
+ nm_platform_ip_route_normalize(AF_INET,
+ NMP_OBJECT_CAST_IP_ROUTE(route_clone),
+ NMP_IP_ROUTE_NORMALIZE_FLAGS_NONE);
+ g_ptr_array_add(*out_singlehop_routes, route_clone);
+
if (changed) {
_LOGT("ecmp-route: single-hop %s",
nmp_object_to_string(route_obj,