From: Yu Watanabe Date: Mon, 11 Nov 2024 04:00:10 +0000 (+0900) Subject: network/nexthop: also forget IPv4 nexthops when an interface went down X-Git-Tag: v257-rc2~39^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=688f166972916b5cfc9287055582ac1aeef3d486;p=thirdparty%2Fsystemd.git network/nexthop: also forget IPv4 nexthops when an interface went down Similar to the previous commit, but for nexthop. --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ea09753dc51..082c7d1c38f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1895,6 +1895,7 @@ static int link_admin_state_up(Link *link) { static int link_admin_state_down(Link *link) { assert(link); + link_forget_nexthops(link); link_forget_routes(link); if (!link->network) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 94df608222f..0d6f881ca05 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -917,6 +917,61 @@ int link_drop_nexthops(Link *link, bool only_static) { return r; } +static void nexthop_forget_one(NextHop *nexthop) { + assert(nexthop); + assert(nexthop->manager); + + Request *req; + if (nexthop_get_request_by_id(nexthop->manager, nexthop->id, &req) >= 0) + route_enter_removed(req->userdata); + + nexthop_enter_removed(nexthop); + log_nexthop_debug(nexthop, "Forgetting silently removed", nexthop->manager); + nexthop_forget_dependents(nexthop, nexthop->manager); + nexthop_detach(nexthop); +} + +void link_forget_nexthops(Link *link) { + assert(link); + assert(link->manager); + assert(link->ifindex > 0); + assert(!FLAGS_SET(link->flags, IFF_UP)); + + /* See comments in link_forget_routes(). */ + + /* Remove all IPv4 nexthops. */ + NextHop *nexthop; + HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) { + if (nexthop->ifindex != link->ifindex) + continue; + if (nexthop->family != AF_INET) + continue; + + nexthop_forget_one(nexthop); + } + + /* Remove all group nexthops their all members are removed in the above. */ + HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) { + if (hashmap_isempty(nexthop->group)) + continue; + + /* Update group members. */ + struct nexthop_grp *nhg; + HASHMAP_FOREACH(nhg, nexthop->group) { + if (nexthop_get_by_id(nexthop->manager, nhg->id, NULL) >= 0) + continue; + + assert_se(hashmap_remove(nexthop->group, UINT32_TO_PTR(nhg->id)) == nhg); + free(nhg); + } + + if (!hashmap_isempty(nexthop->group)) + continue; /* At least one group member still exists. */ + + nexthop_forget_one(nexthop); + } +} + static int nexthop_update_group(NextHop *nexthop, sd_netlink_message *message) { _cleanup_hashmap_free_free_ Hashmap *h = NULL; _cleanup_free_ struct nexthop_grp *group = NULL; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index b6184503f4f..de3f64c3749 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -60,6 +60,7 @@ static inline int link_drop_unmanaged_nexthops(Link *link) { static inline int link_drop_static_nexthops(Link *link) { return link_drop_nexthops(link, /* only_static = */ true); } +void link_forget_nexthops(Link *link); int link_request_static_nexthops(Link *link, bool only_ipv4);