]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: configure nexthop before routes that requires gateway
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 4 Feb 2021 14:13:08 +0000 (23:13 +0900)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 19 Feb 2021 07:34:12 +0000 (08:34 +0100)
This is a preparation for later commits. When RTA_NH_ID is set to a
route, then the corresponding nexthop must be exist.

src/network/networkd-nexthop.c
src/network/networkd-nexthop.h
src/network/networkd-route.c
src/network/networkd-route.h

index 64bbac0b497cb7ab11c1a04696f6783117fc0f26..2aaddccf1769e2a53900ebdbf2ee906cdaabb854 100644 (file)
@@ -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) {
index 3e5fbf028fb47b0111d9eb05448dc89055df80d6..80af1e1feeb012d14a86d856bbcada3d4c11d073 100644 (file)
@@ -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);
 
index e21c456b0afc013944275318ca50f5b994b30b47..bf0e35b7dada3039ec452856857325a65dea795e 100644 (file)
@@ -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;
 }
index 3f93aa6b57084e676515266b6c113a65128ca943..92ef00e31f7984688188aa67e3da75122db02d11 100644 (file)
@@ -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);