From: Yu Watanabe Date: Thu, 14 Dec 2023 23:46:28 +0000 (+0900) Subject: network/nexthop: drop conflicting [NextHop] sections X-Git-Tag: v256-rc1~1419^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=015b2432075fe60a94e910a1627cb1509c107cf1;p=thirdparty%2Fsystemd.git network/nexthop: drop conflicting [NextHop] sections --- diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index f721228b857..1bf7b8b46c7 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 4dc9e342ba7..fc0065147aa 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -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; diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index ad63a73161a..7ebeb961529 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -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( diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index c1d39e6e8ea..025307c4606 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -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) {