}
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;
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 */
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) {
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);
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);
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;
}