]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/nexthop: drop conflicting [NextHop] sections
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Dec 2023 23:46:28 +0000 (08:46 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 20 Dec 2023 19:22:46 +0000 (04:22 +0900)
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-nexthop.c
src/network/networkd-nexthop.h

index f721228b85700d831f325cc0ff7369557f7ea5ca..1bf7b8b46c7e5f224dabc295d8fd7c504b45dfa7 100644 (file)
@@ -306,7 +306,9 @@ int network_verify(Network *network) {
         if (r < 0)
                 return r; /* network_drop_invalid_addresses() logs internally. */
         network_drop_invalid_routes(network);
-        network_drop_invalid_nexthops(network);
+        r = network_drop_invalid_nexthops(network);
+        if (r < 0)
+                return r;
         network_drop_invalid_bridge_fdb_entries(network);
         network_drop_invalid_bridge_mdb_entries(network);
         r = network_drop_invalid_neighbors(network);
@@ -773,7 +775,7 @@ static Network *network_free(Network *network) {
         set_free_free(network->ipv6_proxy_ndp_addresses);
         ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
         hashmap_free_with_destructor(network->routes_by_section, route_free);
-        hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
+        ordered_hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
         hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free);
         hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free);
         ordered_hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free);
index 4dc9e342ba7d8abe8931948583257950a3bad286..fc0065147aa9ef8f16db419ed804b942135b8330 100644 (file)
@@ -371,7 +371,7 @@ struct Network {
 
         OrderedHashmap *addresses_by_section;
         Hashmap *routes_by_section;
-        Hashmap *nexthops_by_section;
+        OrderedHashmap *nexthops_by_section;
         Hashmap *bridge_fdb_entries_by_section;
         Hashmap *bridge_mdb_entries_by_section;
         OrderedHashmap *neighbors_by_section;
index ad63a73161a58f4150d80c2357de32b7b980c3ac..7ebeb9615299dc511a4cc729a84fbb68180bd18f 100644 (file)
@@ -24,7 +24,7 @@ NextHop *nexthop_free(NextHop *nexthop) {
 
         if (nexthop->network) {
                 assert(nexthop->section);
-                hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
+                ordered_hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
         }
 
         config_section_free(nexthop->section);
@@ -80,7 +80,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
         if (r < 0)
                 return r;
 
-        nexthop = hashmap_get(network->nexthops_by_section, n);
+        nexthop = ordered_hashmap_get(network->nexthops_by_section, n);
         if (nexthop) {
                 *ret = TAKE_PTR(nexthop);
                 return 0;
@@ -95,7 +95,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
         nexthop->section = TAKE_PTR(n);
         nexthop->source = NETWORK_CONFIG_SOURCE_STATIC;
 
-        r = hashmap_ensure_put(&network->nexthops_by_section, &config_section_hash_ops, nexthop->section, nexthop);
+        r = ordered_hashmap_ensure_put(&network->nexthops_by_section, &config_section_hash_ops, nexthop->section, nexthop);
         if (r < 0)
                 return r;
 
@@ -363,7 +363,7 @@ static int nexthop_acquire_id(Manager *manager, NextHop *nexthop) {
         ORDERED_HASHMAP_FOREACH(network, manager->networks) {
                 NextHop *tmp;
 
-                HASHMAP_FOREACH(tmp, network->nexthops_by_section) {
+                ORDERED_HASHMAP_FOREACH(tmp, network->nexthops_by_section) {
                         if (tmp->id == 0)
                                 continue;
 
@@ -678,7 +678,7 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
 
         link->static_nexthops_configured = false;
 
-        HASHMAP_FOREACH(nh, link->network->nexthops_by_section) {
+        ORDERED_HASHMAP_FOREACH(nh, link->network->nexthops_by_section) {
                 if (only_ipv4 && nh->family != AF_INET)
                         continue;
 
@@ -759,7 +759,7 @@ static void link_mark_nexthops(Link *link, bool foreign) {
                 if (!IN_SET(other->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
                         continue;
 
-                HASHMAP_FOREACH(nexthop, other->network->nexthops_by_section) {
+                ORDERED_HASHMAP_FOREACH(nexthop, other->network->nexthops_by_section) {
                         NextHop *existing;
 
                         if (nexthop_get(other, nexthop, &existing) < 0)
@@ -1063,14 +1063,41 @@ static int nexthop_section_verify(NextHop *nh) {
         return 0;
 }
 
-void network_drop_invalid_nexthops(Network *network) {
+int network_drop_invalid_nexthops(Network *network) {
+        _cleanup_hashmap_free_ Hashmap *nexthops = NULL;
         NextHop *nh;
+        int r;
 
         assert(network);
 
-        HASHMAP_FOREACH(nh, network->nexthops_by_section)
-                if (nexthop_section_verify(nh) < 0)
+        ORDERED_HASHMAP_FOREACH(nh, network->nexthops_by_section) {
+                if (nexthop_section_verify(nh) < 0) {
                         nexthop_free(nh);
+                        continue;
+                }
+
+                if (nh->id == 0)
+                        continue;
+
+                /* Always use the setting specified later. So, remove the previously assigned setting. */
+                NextHop *dup = hashmap_remove(nexthops, UINT32_TO_PTR(nh->id));
+                if (dup) {
+                        log_warning("%s: Duplicated nexthop settings for ID %"PRIu32" is specified at line %u and %u, "
+                                    "dropping the nexthop setting specified at line %u.",
+                                    dup->section->filename,
+                                    nh->id, nh->section->line,
+                                    dup->section->line, dup->section->line);
+                        /* nexthop_free() will drop the nexthop from nexthops_by_section. */
+                        nexthop_free(dup);
+                }
+
+                r = hashmap_ensure_put(&nexthops, NULL, UINT32_TO_PTR(nh->id), nh);
+                if (r < 0)
+                        return log_oom();
+                assert(r > 0);
+        }
+
+        return 0;
 }
 
 int config_parse_nexthop_id(
index c1d39e6e8ea9b5115d45ea203491a952969aeaae..025307c4606af8d247d4ec8f2224f991c80ec7c2 100644 (file)
@@ -37,7 +37,7 @@ typedef struct NextHop {
 
 NextHop *nexthop_free(NextHop *nexthop);
 
-void network_drop_invalid_nexthops(Network *network);
+int network_drop_invalid_nexthops(Network *network);
 
 int link_drop_nexthops(Link *link, bool foreign);
 static inline int link_drop_foreign_nexthops(Link *link) {