From 737cb5d424e397901a5ad979907a084f770dd8d4 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Thu, 22 Dec 2022 11:36:58 +0100 Subject: [PATCH] nm-netns: add onlink routes for ECMP routes When adding a static route, kernel enforce that the gateway is reachable. To solve this, NetworkManager generates onlink routes for each static route. As ECMP routes does not follow the same logic than singlehop routes, we need to add the onlink route for each hop of ECMP routes once merged. NML3Cfg will take ownership of the onlink route added and will purge it when it is not needed anymore. --- src/core/nm-netns.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index f8693e2ce7..0b775ce268 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -771,6 +771,8 @@ _netns_ip_route_ecmp_update_mh(NMNetns *self, const NMPObject *obj = mhrts_add->pdata[i]; nm_auto_nmpobj const NMPObject *obj_old = NULL; gpointer unused; + const NMPlatformIP4Route *route_src; + guint j; if (g_hash_table_steal_extended(priv->ecmp_routes, obj, @@ -783,6 +785,35 @@ _netns_ip_route_ecmp_update_mh(NMNetns *self, if (!g_hash_table_add(priv->ecmp_routes, (gpointer) nmp_object_ref(obj))) nm_assert_not_reached(); + /* for each nexthop we need to configure the onlink route for the gateway */ + route_src = NMP_OBJECT_CAST_IP4_ROUTE(obj); + for (j = 0; j < route_src->n_nexthops; j++) { + NMPObject *new_onlink_obj; + NMPlatformIP4Route *new_onlink_route; + in_addr_t gateway; + int ifindex; + + new_onlink_obj = nmp_object_clone(obj, TRUE); + new_onlink_route = NMP_OBJECT_CAST_IP4_ROUTE(new_onlink_obj); + if (j == 0) { + gateway = route_src->gateway; + ifindex = route_src->ifindex; + } else { + gateway = obj->_ip4_route.extra_nexthops[j - 1].gateway; + ifindex = obj->_ip4_route.extra_nexthops[j - 1].ifindex; + } + + new_onlink_route->network = gateway; + new_onlink_route->plen = 32; + new_onlink_route->gateway = 0; + new_onlink_route->ifindex = ifindex; + new_onlink_route->weight = 0; + new_onlink_route->n_nexthops = 0; + + /* we configure the onlink route and l3cfg will take the ownership and remove it if not needed */ + nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, new_onlink_obj); + } + nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, obj); } }