]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/nexthop: check existing nexthop can be replaced with requested one
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 13 Dec 2023 06:33:13 +0000 (15:33 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Dec 2023 09:58:26 +0000 (18:58 +0900)
src/network/networkd-nexthop.c

index 06831464926f37db31fab21a4ba41cac44c5f5b8..aeb33ae8d603a6d37ccd3f586c649146c33508fb 100644 (file)
@@ -702,6 +702,31 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
         return 0;
 }
 
+static bool nexthop_can_update(const NextHop *assigned_nexthop, const NextHop *requested_nexthop) {
+        assert(assigned_nexthop);
+        assert(assigned_nexthop->manager);
+        assert(requested_nexthop);
+        assert(requested_nexthop->network);
+
+        /* A group nexthop cannot be replaced with a non-group nexthop, and vice versa.
+         * See replace_nexthop_grp() and replace_nexthop_single() in net/ipv4/nexthop.c of the kernel. */
+        if (hashmap_isempty(assigned_nexthop->group) != hashmap_isempty(requested_nexthop->group))
+                return false;
+
+        /* There are several more conditions if we can replace a group nexthop, e.g. hash threshold and
+         * resilience. But, currently we do not support to modify that. Let's add checks for them in the
+         * future when we support to configure them.*/
+
+        /* When a nexthop is replaced with a blackhole nexthop, and a group nexthop has multiple nexthops
+         * including this nexthop, then the kernel refuses to replace the existing nexthop.
+         * So, here, for simplicity, let's unconditionally refuse to replace a non-blackhole nexthop with
+         * a blackhole nexthop. See replace_nexthop() in net/ipv4/nexthop.c of the kernel. */
+        if (!assigned_nexthop->blackhole && requested_nexthop->blackhole)
+                return false;
+
+        return true;
+}
+
 static void link_mark_nexthops(Link *link, bool foreign) {
         NextHop *nexthop;
         Link *other;
@@ -741,8 +766,14 @@ static void link_mark_nexthops(Link *link, bool foreign) {
                 HASHMAP_FOREACH(nexthop, other->network->nexthops_by_section) {
                         NextHop *existing;
 
-                        if (nexthop_get(other, nexthop, &existing) >= 0)
-                                nexthop_unmark(existing);
+                        if (nexthop_get(other, nexthop, &existing) < 0)
+                                continue;
+
+                        if (!nexthop_can_update(existing, nexthop))
+                                continue;
+
+                        /* Found matching static configuration. Keep the existing nexthop. */
+                        nexthop_unmark(existing);
                 }
         }
 }