From: Yu Watanabe Date: Thu, 4 Feb 2021 14:13:08 +0000 (+0900) Subject: network: configure nexthop before routes that requires gateway X-Git-Tag: v248-rc1~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f345918d8d2a50a7bd071cf2ed864ac5cc909467;p=thirdparty%2Fsystemd.git network: configure nexthop before routes that requires gateway This is a preparation for later commits. When RTA_NH_ID is set to a route, then the corresponding nexthop must be exist. --- diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 64bbac0b497..2aaddccf176 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -251,9 +251,12 @@ static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) } if (link->nexthop_messages == 0) { - log_link_debug(link, "Nexthop set"); + log_link_debug(link, "Nexthops set"); link->static_nexthops_configured = true; - link_check_ready(link); + /* Now all nexthops are configured. Let's configure remaining routes. */ + r = link_set_routes_with_gateway(link); + if (r < 0) + link_enter_failed(link); } return 1; @@ -307,7 +310,7 @@ static int nexthop_configure(const NextHop *nexthop, Link *link) { return r; } -int link_set_nexthop(Link *link) { +int link_set_nexthops(Link *link) { enum { PHASE_ID, /* First phase: Nexthops with ID */ PHASE_WITHOUT_ID, /* Second phase: Nexthops without ID */ @@ -340,13 +343,14 @@ int link_set_nexthop(Link *link) { if (link->nexthop_messages == 0) { link->static_nexthops_configured = true; - link_check_ready(link); - } else { - log_link_debug(link, "Setting nexthop"); - link_set_state(link, LINK_STATE_CONFIGURING); + /* Finaly, configure routes with gateways. */ + return link_set_routes_with_gateway(link); } - return 1; + log_link_debug(link, "Setting nexthops"); + link_set_state(link, LINK_STATE_CONFIGURING); + + return 0; } int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 3e5fbf028fb..80af1e1feeb 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -33,7 +33,7 @@ NextHop *nexthop_free(NextHop *nexthop); void network_drop_invalid_nexthops(Network *network); -int link_set_nexthop(Link *link); +int link_set_nexthops(Link *link); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index e21c456b0af..bf0e35b7dad 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1193,7 +1193,7 @@ int route_configure( return k; } -static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int route_handler_with_gateway(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); @@ -1206,29 +1206,115 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not set route"); + log_link_message_warning_errno(link, m, r, "Could not set route with gateway"); link_enter_failed(link); return 1; } if (link->route_messages == 0) { - log_link_debug(link, "Routes set"); + log_link_debug(link, "Routes with gateway set"); link->static_routes_configured = true; - link_set_nexthop(link); + link_check_ready(link); } return 1; } -int link_set_routes(Link *link) { - enum { - PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */ - PHASE_GATEWAY, /* Second phase: Routes with a gateway */ - _PHASE_MAX - } phase; +static int route_handler_without_gateway(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->route_messages > 0); + + link->route_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not set route without gateway"); + link_enter_failed(link); + return 1; + } + + if (link->route_messages == 0) { + log_link_debug(link, "Routes set without gateway"); + /* Now, we can talk to gateways, let's configure nexthops. */ + r = link_set_nexthops(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +static bool route_has_gateway(const Route *route) { + assert(route); + + if (in_addr_is_set(route->gw_family, &route->gw)) + return true; + + if (!ordered_set_isempty(route->multipath_routes)) + return true; + + return false; +} + +static int link_set_routes_internal(Link *link, bool with_gateway) { Route *rt; int r; + assert(link); + assert(link->network); + + HASHMAP_FOREACH(rt, link->network->routes_by_section) { + if (rt->gateway_from_dhcp_or_ra) + continue; + + if (route_has_gateway(rt) != with_gateway) + continue; + + r = route_configure(rt, link, with_gateway ? route_handler_with_gateway : route_handler_without_gateway, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set routes: %m"); + + link->route_messages++; + } + + return 0; +} + +int link_set_routes_with_gateway(Link *link) { + int r; + + assert(link); + assert(link->network); + + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + /* During configuring addresses, the link lost its carrier. As networkd is dropping + * the addresses now, let's not configure the routes either. */ + return 0; + + /* Finaly, add routes that needs a gateway. */ + r = link_set_routes_internal(link, true); + if (r < 0) + return r; + + if (link->route_messages == 0) { + link->static_routes_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting routes with gateway"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +int link_set_routes(Link *link) { + int r; + assert(link); assert(link->network); assert(link->state != _LINK_STATE_INVALID); @@ -1252,29 +1338,17 @@ int link_set_routes(Link *link) { if (r < 0) return r; - /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ - for (phase = 0; phase < _PHASE_MAX; phase++) - HASHMAP_FOREACH(rt, link->network->routes_by_section) { - if (rt->gateway_from_dhcp_or_ra) - continue; - - if ((!in_addr_is_set(rt->gw_family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY)) - continue; - - r = route_configure(rt, link, route_handler, NULL); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set routes: %m"); + /* First, add the routes that enable us to talk to gateways. */ + r = link_set_routes_internal(link, false); + if (r < 0) + return r; - link->route_messages++; - } + if (link->route_messages == 0) + /* If no route is configured, then configure nexthops. */ + return link_set_nexthops(link); - if (link->route_messages == 0) { - link->static_routes_configured = true; - link_set_nexthop(link); - } else { - log_link_debug(link, "Setting routes"); - link_set_state(link, LINK_STATE_CONFIGURING); - } + log_link_debug(link, "Setting routes without gateway"); + link_set_state(link, LINK_STATE_CONFIGURING); return 0; } diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 3f93aa6b570..92ef00e31f7 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -74,6 +74,7 @@ int route_configure(const Route *route, Link *link, link_netlink_message_handler int route_remove(const Route *route, Manager *manager, Link *link, link_netlink_message_handler_t callback); int link_set_routes(Link *link); +int link_set_routes_with_gateway(Link *link); int link_drop_routes(Link *link); int link_drop_foreign_routes(Link *link);