diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index cf62e0e82dc..67eba509d33 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -97,6 +97,7 @@ static NextHop* nexthop_free(NextHop *nexthop) { config_section_free(nexthop->section); hashmap_free_free(nexthop->group); set_free(nexthop->nexthops); + set_free(nexthop->routes); return mfree(nexthop); } diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 74b23bd7720..9ce36c6cd9b 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -41,8 +41,9 @@ typedef struct NextHop { /* Only used in conf parser and nexthop_section_verify(). */ int onlink; - /* For managing nexthops that depend on this nexthop. */ + /* For managing routes and nexthops that depend on this nexthop. */ Set *nexthops; + Set *routes; } NextHop; NextHop* nexthop_ref(NextHop *nexthop); diff --git a/src/network/networkd-route-nexthop.c b/src/network/networkd-route-nexthop.c index 8ccd4e66e87..f7a2201b6b0 100644 --- a/src/network/networkd-route-nexthop.c +++ b/src/network/networkd-route-nexthop.c @@ -5,6 +5,7 @@ #include "alloc-util.h" #include "extract-word.h" #include "netlink-util.h" +#include "networkd-manager.h" #include "networkd-network.h" #include "networkd-nexthop.h" #include "networkd-route.h" @@ -13,6 +14,48 @@ #include "parse-util.h" #include "string-util.h" +void route_detach_from_nexthop(Route *route) { + NextHop *nh; + + assert(route); + assert(route->manager); + + if (route->nexthop_id == 0) + return; + + if (nexthop_get_by_id(route->manager, route->nexthop_id, &nh) < 0) + return; + + route_unref(set_remove(nh->routes, route)); +} + +void route_attach_to_nexthop(Route *route) { + NextHop *nh; + int r; + + assert(route); + assert(route->manager); + + if (route->nexthop_id == 0) + return; + + r = nexthop_get_by_id(route->manager, route->nexthop_id, &nh); + if (r < 0) { + if (route->manager->manage_foreign_nexthops) + log_debug_errno(r, "Route has unknown nexthop ID (%"PRIu32"), ignoring.", + route->nexthop_id); + return; + } + + r = set_ensure_put(&nh->routes, &route_hash_ops_unref, route); + if (r < 0) + return (void) log_debug_errno(r, "Failed to save route to nexthop, ignoring: %m"); + if (r == 0) + return (void) log_debug("Duplicated route assigned to nexthop, ignoring."); + + route_ref(route); +} + static void route_nexthop_done(RouteNextHop *nh) { assert(nh); diff --git a/src/network/networkd-route-nexthop.h b/src/network/networkd-route-nexthop.h index 5e4602d3cd3..f9a147839db 100644 --- a/src/network/networkd-route-nexthop.h +++ b/src/network/networkd-route-nexthop.h @@ -26,6 +26,9 @@ typedef struct RouteNextHop { #define ROUTE_NEXTHOP_NULL ((const RouteNextHop) {}) +void route_detach_from_nexthop(Route *route); +void route_attach_to_nexthop(Route *route); + RouteNextHop* route_nexthop_free(RouteNextHop *nh); DEFINE_TRIVIAL_CLEANUP_FUNC(RouteNextHop*, route_nexthop_free); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 147d9cb14fd..80e20a286b0 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -33,6 +33,7 @@ static Route* route_detach_impl(Route *route) { } if (route->manager) { + route_detach_from_nexthop(route); set_remove(route->manager->routes, route); route->manager = NULL; return route; @@ -220,6 +221,13 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( route_compare_func, route_detach); +DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( + route_hash_ops_unref, + Route, + route_hash_func, + route_compare_func, + route_unref); + DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( route_section_hash_ops, ConfigSection, diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 004295e5998..c5c2693ac4f 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -81,6 +81,7 @@ struct Route { }; extern const struct hash_ops route_hash_ops; +extern const struct hash_ops route_hash_ops_unref; Route* route_ref(Route *route); Route* route_unref(Route *route);