]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: make manager_find_uplink() uses stored route information
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 May 2021 18:01:58 +0000 (03:01 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Jun 2021 21:33:27 +0000 (06:33 +0900)
networkd already has all information about routes. It is not necessary
to re-read them by using local_gateways().

This also makes manager_find_uplink() take family.

src/network/networkd-dhcp-server.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-radv.c
src/network/networkd-route.c
src/network/networkd-route.h

index e4af517c20350161388f7798a04f3d95585969d4..3443e498a16c50df45f737422565653a321656d5 100644 (file)
@@ -363,7 +363,7 @@ static int dhcp4_server_configure(Link *link) {
                 else {
                         /* Emission is requested, but nothing explicitly configured. Let's find a suitable upling */
                         if (!acquired_uplink) {
-                                uplink = manager_find_uplink(link->manager, link);
+                                (void) manager_find_uplink(link->manager, AF_INET, link, &uplink);
                                 acquired_uplink = true;
                         }
 
index d4b40432118f7ed9b2856b033e4570cbfa627343..60e6d6f3690e24bc14dba68fbf2f9e5c8fda09ac 100644 (file)
@@ -719,43 +719,6 @@ int manager_enumerate(Manager *m) {
         return 0;
 }
 
-Link* manager_find_uplink(Manager *m, Link *exclude) {
-        _cleanup_free_ struct local_address *gateways = NULL;
-        int n;
-
-        assert(m);
-
-        /* Looks for a suitable "uplink", via black magic: an
-         * interface that is up and where the default route with the
-         * highest priority points to. */
-
-        n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways);
-        if (n < 0) {
-                log_warning_errno(n, "Failed to determine list of default gateways: %m");
-                return NULL;
-        }
-
-        for (int i = 0; i < n; i++) {
-                Link *link;
-
-                link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex));
-                if (!link) {
-                        log_debug("Weird, found a gateway for a link we don't know. Ignoring.");
-                        continue;
-                }
-
-                if (link == exclude)
-                        continue;
-
-                if (link->operstate < LINK_OPERSTATE_ROUTABLE)
-                        continue;
-
-                return link;
-        }
-
-        return NULL;
-}
-
 static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
         const sd_bus_error *e;
         int r;
index 6b9b0697b2197bc99f4f24e046fdd33a205c80fe..c7fea16ab2ff6be1449a66d5ee21550198cd51e3 100644 (file)
@@ -111,8 +111,6 @@ bool manager_should_reload(Manager *m);
 
 int manager_enumerate(Manager *m);
 
-Link* manager_find_uplink(Manager *m, Link *exclude);
-
 int manager_set_hostname(Manager *m, const char *hostname);
 int manager_set_timezone(Manager *m, const char *timezone);
 
index 0eaa4c29c99c5b4231f7cfc417ace20454d1452a..45cfd7a9a7d4929d1d3200f70fccfdd060b6b927 100644 (file)
@@ -646,10 +646,10 @@ static int radv_set_domains(Link *link, Link *uplink) {
 }
 
 int radv_emit_dns(Link *link) {
-        Link *uplink;
+        Link *uplink = NULL;
         int r;
 
-        uplink = manager_find_uplink(link->manager, link);
+        (void) manager_find_uplink(link->manager, AF_INET6, link, &uplink);
 
         r = radv_set_dns(link, uplink);
         if (r < 0)
index 7d93825813f486d842beb328c82e58fb5254dac5..c76cdbedee2306e51fd9a6da4dd467ec55247dc9 100644 (file)
@@ -771,6 +771,65 @@ bool manager_address_is_reachable(Manager *manager, int family, const union in_a
         return false;
 }
 
+static Route *routes_get_default_gateway(Set *routes, int family, Route *gw) {
+        Route *route;
+
+        SET_FOREACH(route, routes) {
+                if (family != AF_UNSPEC && route->family != family)
+                        continue;
+                if (route->dst_prefixlen != 0)
+                        continue;
+                if (route->src_prefixlen != 0)
+                        continue;
+                if (route->table != RT_TABLE_MAIN)
+                        continue;
+                if (route->type != RTN_UNICAST)
+                        continue;
+                if (route->scope != RT_SCOPE_UNIVERSE)
+                        continue;
+                if (!in_addr_is_set(route->gw_family, &route->gw))
+                        continue;
+                if (gw) {
+                        if (route->gw_weight > gw->gw_weight)
+                                continue;
+                        if (route->priority >= gw->priority)
+                                continue;
+                }
+                gw = route;
+        }
+
+        return gw;
+}
+
+int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret) {
+        Route *gw = NULL;
+        Link *link;
+
+        assert(m);
+        assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
+
+        /* Looks for a suitable "uplink", via black magic: an interface that is up and where the
+         * default route with the highest priority points to. */
+
+        HASHMAP_FOREACH(link, m->links) {
+                if (link == exclude)
+                        continue;
+
+                if (link->state != LINK_STATE_CONFIGURED)
+                        continue;
+
+                gw = routes_get_default_gateway(link->routes, family, gw);
+                gw = routes_get_default_gateway(link->routes_foreign, family, gw);
+        }
+
+        if (!gw)
+                return -ENOENT;
+
+        assert(gw->link);
+        *ret = gw->link;
+        return 0;
+}
+
 static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *manager) {
         _cleanup_free_ char *dst = NULL, *src = NULL, *gw_alloc = NULL, *prefsrc = NULL,
                 *table = NULL, *scope = NULL, *proto = NULL;
index 095a07e05de6de44b3e5c5a3bfb3120965d0824c..fa0b3ba0fc9213fc7e30f660ef853d77b6db522b 100644 (file)
@@ -78,6 +78,7 @@ int route_remove(const Route *route, Manager *manager, Link *link);
 
 int link_has_route(Link *link, const Route *route);
 bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address);
+int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret);
 
 int link_drop_routes(Link *link);
 int link_drop_foreign_routes(Link *link);