]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/nexthop: also forget IPv4 nexthops when an interface went down
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Nov 2024 04:00:10 +0000 (13:00 +0900)
committerLuca Boccassi <bluca@debian.org>
Mon, 11 Nov 2024 13:59:41 +0000 (13:59 +0000)
Similar to the previous commit, but for nexthop.

src/network/networkd-link.c
src/network/networkd-nexthop.c
src/network/networkd-nexthop.h

index ea09753dc5196a2383ac233d95cd5074c6f2d361..082c7d1c38f379db7bca45752e8501ff84ce1cae 100644 (file)
@@ -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)
index 94df608222fa7e303df7387634f2823af5548907..0d6f881ca0559b48c36b08883d502e653fb6bceb 100644 (file)
@@ -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;
index b6184503f4f7160f8f21199abc0832c8b20fb529..de3f64c37492c0666dddf1f3db1656999bd82dc8 100644 (file)
@@ -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);