]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/nexthop: manage all nexthops by manager
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 12 Dec 2023 18:43:27 +0000 (03:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Dec 2023 09:58:26 +0000 (18:58 +0900)
The kernel manages nexthops by their IDs. Previously networkd manages
nexthops in three ways:
- by the corresponding link, if a nexthop has ifindex,
- by the manager, if a nexthop does not have ifindex,
- by the manager with their IDs.

This unifies the three managements of nexthops into one, and use the
same way as the kernel uses.

This is the one for nexthop already done by
aa9626ee3b96e0d2a9a816b5efd38fd7dc829def for neighbor.

src/network/networkd-json.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-nexthop.c
src/network/networkd-nexthop.h
src/network/networkd-route.c

index eed8d9f7879aa481403b5eaf720f9ebb18077b77..b4defb7091c276734f18d18c46896533be850ccd 100644 (file)
@@ -185,16 +185,20 @@ static int nexthop_build_json(NextHop *n, JsonVariant **ret) {
                                 JSON_BUILD_PAIR_STRING("ConfigState", state)));
 }
 
-static int nexthops_append_json(Set *nexthops, JsonVariant **v) {
+static int nexthops_append_json(Manager *manager, int ifindex, JsonVariant **v) {
         _cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
         NextHop *nexthop;
         int r;
 
+        assert(manager);
         assert(v);
 
-        SET_FOREACH(nexthop, nexthops) {
+        HASHMAP_FOREACH(nexthop, manager->nexthops_by_id) {
                 _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
 
+                if (nexthop->ifindex != ifindex)
+                        continue;
+
                 r = nexthop_build_json(nexthop, &e);
                 if (r < 0)
                         return r;
@@ -1354,7 +1358,7 @@ int link_build_json(Link *link, JsonVariant **ret) {
         if (r < 0)
                 return r;
 
-        r = nexthops_append_json(link->nexthops, &v);
+        r = nexthops_append_json(link->manager, link->ifindex, &v);
         if (r < 0)
                 return r;
 
@@ -1417,7 +1421,7 @@ int manager_build_json(Manager *manager, JsonVariant **ret) {
         if (r < 0)
                 return r;
 
-        r = nexthops_append_json(manager->nexthops, &v);
+        r = nexthops_append_json(manager, /* ifindex = */ 0, &v);
         if (r < 0)
                 return r;
 
index 0162e2acb0308d43b36d4b7cb5d4effe0af54fb0..dd3b448ab25a7d274733c80b166eb99ae24c2964 100644 (file)
@@ -209,7 +209,6 @@ static Link *link_free(Link *link) {
         link_dns_settings_clear(link);
 
         link->routes = set_free(link->routes);
-        link->nexthops = set_free(link->nexthops);
         link->neighbors = set_free(link->neighbors);
         link->addresses = set_free(link->addresses);
         link->qdiscs = set_free(link->qdiscs);
index 7458ea93bd0824d7b8cb651f237f7e75676f4f59..cad9fa8410685fa20b968c66ef34d7623945012a 100644 (file)
@@ -125,7 +125,6 @@ typedef struct Link {
         Set *addresses;
         Set *neighbors;
         Set *routes;
-        Set *nexthops;
         Set *qdiscs;
         Set *tclasses;
 
index 6ee01b28e0703371ccfbc18091ebd6fc2346525f..b162d21aa0f9f91720f2cdc819f6775e3b6f82b9 100644 (file)
@@ -649,7 +649,6 @@ Manager* manager_free(Manager *m) {
          * set_free() must be called after the above sd_netlink_unref(). */
         m->routes = set_free(m->routes);
 
-        m->nexthops = set_free(m->nexthops);
         m->nexthops_by_id = hashmap_free(m->nexthops_by_id);
 
         sd_event_source_unref(m->speed_meter_event_source);
index a4eb7d78afab88d8db57c40d192992b45b8ee2f6..a9827d8a4b4fffea9b61280829b5abc6e40691b6 100644 (file)
@@ -74,9 +74,6 @@ struct Manager {
         /* Manage nexthops by id. */
         Hashmap *nexthops_by_id;
 
-        /* Manager stores nexthops without RTA_OIF attribute. */
-        Set *nexthops;
-
         /* Manager stores routes without RTA_OIF attribute. */
         unsigned route_remove_messages;
         Set *routes;
index dc0e93e587461d2fbe651a5b8a82cb9c4ecd5423..5f2a8282bf28fee6e2ea684279941d4f3d8b4e54 100644 (file)
@@ -29,18 +29,9 @@ NextHop *nexthop_free(NextHop *nexthop) {
 
         config_section_free(nexthop->section);
 
-        if (nexthop->link) {
-                set_remove(nexthop->link->nexthops, nexthop);
-
-                if (nexthop->link->manager && nexthop->id > 0)
-                        hashmap_remove(nexthop->link->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
-        }
-
         if (nexthop->manager) {
-                set_remove(nexthop->manager->nexthops, nexthop);
-
-                if (nexthop->id > 0)
-                        hashmap_remove(nexthop->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
+                assert(nexthop->id > 0);
+                hashmap_remove(nexthop->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
         }
 
         hashmap_free_free(nexthop->group);
@@ -50,6 +41,14 @@ NextHop *nexthop_free(NextHop *nexthop) {
 
 DEFINE_SECTION_CLEANUP_FUNCTIONS(NextHop, nexthop_free);
 
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+                nexthop_hash_ops,
+                void,
+                trivial_hash_func,
+                trivial_compare_func,
+                NextHop,
+                nexthop_free);
+
 static int nexthop_new(NextHop **ret) {
         _cleanup_(nexthop_freep) NextHop *nexthop = NULL;
 
@@ -106,35 +105,54 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
 
 static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
         assert(nexthop);
+        assert(state);
 
-        siphash24_compress(&nexthop->protocol, sizeof(nexthop->protocol), state);
         siphash24_compress(&nexthop->id, sizeof(nexthop->id), state);
-        siphash24_compress(&nexthop->blackhole, sizeof(nexthop->blackhole), state);
-        siphash24_compress(&nexthop->family, sizeof(nexthop->family), state);
+}
 
-        switch (nexthop->family) {
-        case AF_INET:
-        case AF_INET6:
-                siphash24_compress(&nexthop->gw, FAMILY_ADDRESS_SIZE(nexthop->family), state);
+static int nexthop_compare_func(const NextHop *a, const NextHop *b) {
+        assert(a);
+        assert(b);
 
-                break;
-        default:
-                /* treat any other address family as AF_UNSPEC */
-                break;
-        }
+        return CMP(a->id, b->id);
 }
 
-static int nexthop_compare_func(const NextHop *a, const NextHop *b) {
+static int nexthop_compare_full(const NextHop *a, const NextHop *b) {
         int r;
 
+        assert(a);
+        assert(b);
+
+        /* This compares detailed configs, except for ID and ifindex. */
+
         r = CMP(a->protocol, b->protocol);
         if (r != 0)
                 return r;
 
-        r = CMP(a->id, b->id);
+        r = CMP(a->flags, b->flags);
         if (r != 0)
                 return r;
 
+        r = CMP(hashmap_size(a->group), hashmap_size(b->group));
+        if (r != 0)
+                return r;
+
+        if (!hashmap_isempty(a->group)) {
+                struct nexthop_grp *ga;
+
+                HASHMAP_FOREACH(ga, a->group) {
+                        struct nexthop_grp *gb;
+
+                        gb = hashmap_get(b->group, UINT32_TO_PTR(ga->id));
+                        if (!gb)
+                                return CMP(ga, gb);
+
+                        r = CMP(ga->weight, gb->weight);
+                        if (r != 0)
+                                return r;
+                }
+        }
+
         r = CMP(a->blackhole, b->blackhole);
         if (r != 0)
                 return r;
@@ -143,29 +161,15 @@ static int nexthop_compare_func(const NextHop *a, const NextHop *b) {
         if (r != 0)
                 return r;
 
-        if (IN_SET(a->family, AF_INET, AF_INET6))
-                return memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
+        if (IN_SET(a->family, AF_INET, AF_INET6)) {
+                r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
+                if (r != 0)
+                        return r;
+        }
 
         return 0;
 }
 
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
-                nexthop_hash_ops,
-                NextHop,
-                nexthop_hash_func,
-                nexthop_compare_func,
-                nexthop_free);
-
-static bool nexthop_equal(const NextHop *a, const NextHop *b) {
-        if (a == b)
-                return true;
-
-        if (!a || !b)
-                return false;
-
-        return nexthop_compare_func(a, b) == 0;
-}
-
 static int nexthop_dup(const NextHop *src, NextHop **ret) {
         _cleanup_(nexthop_freep) NextHop *dest = NULL;
         struct nexthop_grp *nhg;
@@ -180,7 +184,6 @@ static int nexthop_dup(const NextHop *src, NextHop **ret) {
 
         /* unset all pointers */
         dest->manager = NULL;
-        dest->link = NULL;
         dest->network = NULL;
         dest->section = NULL;
         dest->group = NULL;
@@ -225,45 +228,23 @@ int nexthop_get_by_id(Manager *manager, uint32_t id, NextHop **ret) {
         return 0;
 }
 
-static int nexthop_get(Manager *manager, Link *link, NextHop *in, NextHop **ret) {
+static int nexthop_get(Link *link, const NextHop *in, NextHop **ret) {
         NextHop *nexthop;
-        Set *nexthops;
+        int ifindex;
 
+        assert(link);
+        assert(link->manager);
         assert(in);
 
-        if (nexthop_bound_to_link(in)) {
-                if (!link)
-                        return -ENOENT;
-
-                nexthops = link->nexthops;
-        } else {
-                if (!manager)
-                        return -ENOENT;
-
-                nexthops = manager->nexthops;
-        }
-
-        nexthop = set_get(nexthops, in);
-        if (nexthop) {
-                if (ret)
-                        *ret = nexthop;
-                return 0;
-        }
-
         if (in->id > 0)
-                return -ENOENT;
-
-        /* Also find nexthop configured without ID. */
-        SET_FOREACH(nexthop, nexthops) {
-                uint32_t id;
-                bool found;
+                return nexthop_get_by_id(link->manager, in->id, ret);
 
-                id = nexthop->id;
-                nexthop->id = 0;
-                found = nexthop_equal(nexthop, in);
-                nexthop->id = id;
+        ifindex = nexthop_bound_to_link(in) ? link->ifindex : 0;
 
-                if (!found)
+        HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) {
+                if (nexthop->ifindex != ifindex)
+                        continue;
+                if (nexthop_compare_full(nexthop, in) != 0)
                         continue;
 
                 if (ret)
@@ -274,37 +255,21 @@ static int nexthop_get(Manager *manager, Link *link, NextHop *in, NextHop **ret)
         return -ENOENT;
 }
 
-static int nexthop_add(Manager *manager, Link *link, NextHop *nexthop) {
+static int nexthop_add(Manager *manager, NextHop *nexthop) {
         int r;
 
+        assert(manager);
         assert(nexthop);
         assert(nexthop->id > 0);
 
-        if (nexthop_bound_to_link(nexthop)) {
-                assert(link);
-
-                r = set_ensure_put(&link->nexthops, &nexthop_hash_ops, nexthop);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        return -EEXIST;
-
-                nexthop->link = link;
-
-                manager = link->manager;
-        } else {
-                assert(manager);
-
-                r = set_ensure_put(&manager->nexthops, &nexthop_hash_ops, nexthop);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        return -EEXIST;
-
-                nexthop->manager = manager;
-        }
+        r = hashmap_ensure_put(&manager->nexthops_by_id, &nexthop_hash_ops, UINT32_TO_PTR(nexthop->id), nexthop);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EEXIST;
 
-        return hashmap_ensure_put(&manager->nexthops_by_id, NULL, UINT32_TO_PTR(nexthop->id), nexthop);
+        nexthop->manager = manager;
+        return 0;
 }
 
 static int nexthop_acquire_id(Manager *manager, NextHop *nexthop) {
@@ -350,18 +315,19 @@ static int nexthop_acquire_id(Manager *manager, NextHop *nexthop) {
         return -EBUSY;
 }
 
-static void log_nexthop_debug(const NextHop *nexthop, const char *str, const Link *link) {
+static void log_nexthop_debug(const NextHop *nexthop, const char *str, Manager *manager) {
         _cleanup_free_ char *state = NULL, *group = NULL, *flags = NULL;
         struct nexthop_grp *nhg;
+        Link *link = NULL;
 
         assert(nexthop);
         assert(str);
-
-        /* link may be NULL. */
+        assert(manager);
 
         if (!DEBUG_LOGGING)
                 return;
 
+        (void) link_get_by_index(manager, nexthop->ifindex, &link);
         (void) network_config_state_to_string_alloc(nexthop->state, &state);
         (void) route_flags_to_string_alloc(nexthop->flags, &flags);
 
@@ -395,22 +361,20 @@ static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
 static int nexthop_remove(NextHop *nexthop) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         Manager *manager;
-        Link *link;
+        Link *link = NULL;
         int r;
 
-        assert(nexthop);
-        assert(nexthop->manager || (nexthop->link && nexthop->link->manager));
+        manager = ASSERT_PTR(ASSERT_PTR(nexthop)->manager);
 
         /* link may be NULL. */
-        link = nexthop->link;
-        manager = nexthop->manager ?: nexthop->link->manager;
+        (void) link_get_by_index(manager, nexthop->ifindex, &link);
 
         if (nexthop->id == 0) {
                 log_link_debug(link, "Cannot remove nexthop without valid ID, ignoring.");
                 return 0;
         }
 
-        log_nexthop_debug(nexthop, "Removing", link);
+        log_nexthop_debug(nexthop, "Removing", manager);
 
         r = sd_rtnl_message_new_nexthop(manager->rtnl, &m, RTM_DELNEXTHOP, AF_UNSPEC, RTPROT_UNSPEC);
         if (r < 0)
@@ -444,7 +408,7 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
         assert(link->ifindex > 0);
         assert(req);
 
-        log_nexthop_debug(nexthop, "Configuring", link);
+        log_nexthop_debug(nexthop, "Configuring", link->manager);
 
         r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &m, RTM_NEWNEXTHOP, nexthop->family, nexthop->protocol);
         if (r < 0)
@@ -475,7 +439,9 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
                 if (r < 0)
                         return r;
         } else {
-                r = sd_netlink_message_append_u32(m, NHA_OIF, link->ifindex);
+                assert(nexthop->ifindex == link->ifindex);
+
+                r = sd_netlink_message_append_u32(m, NHA_OIF, nexthop->ifindex);
                 if (r < 0)
                         return r;
 
@@ -525,6 +491,8 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
                 return false;
 
         if (nexthop_bound_to_link(nexthop)) {
+                assert(nexthop->ifindex == link->ifindex);
+
                 /* TODO: fdb nexthop does not require IFF_UP. The conditions below needs to be updated
                  * when fdb nexthop support is added. See rtm_to_nh_config() in net/ipv4/nexthop.c of
                  * kernel. */
@@ -585,7 +553,7 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) {
         assert(nexthop);
         assert(nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN);
 
-        if (nexthop_get(link->manager, link, nexthop, &existing) < 0) {
+        if (nexthop_get(link, nexthop, &existing) < 0) {
                 _cleanup_(nexthop_freep) NextHop *tmp = NULL;
 
                 r = nexthop_dup(nexthop, &tmp);
@@ -596,7 +564,10 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) {
                 if (r < 0)
                         return r;
 
-                r = nexthop_add(link->manager, link, tmp);
+                if (nexthop_bound_to_link(tmp))
+                        tmp->ifindex = link->ifindex;
+
+                r = nexthop_add(link->manager, tmp);
                 if (r < 0)
                         return r;
 
@@ -604,7 +575,7 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) {
         } else
                 existing->source = nexthop->source;
 
-        log_nexthop_debug(existing, "Requesting", link);
+        log_nexthop_debug(existing, "Requesting", link->manager);
         r = link_queue_request_safe(link, REQUEST_TYPE_NEXTHOP,
                                     existing, NULL,
                                     nexthop_hash_func,
@@ -649,14 +620,15 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
         return 0;
 }
 
-static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *except) {
+static void link_mark_nexthops(Link *link, bool foreign) {
         NextHop *nexthop;
-        Link *link;
+        Link *other;
 
-        assert(manager);
+        assert(link);
+        assert(link->manager);
 
         /* First, mark all nexthops. */
-        SET_FOREACH(nexthop, manager->nexthops) {
+        HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) {
                 /* do not touch nexthop created by the kernel */
                 if (nexthop->protocol == RTPROT_KERNEL)
                         continue;
@@ -669,127 +641,58 @@ static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *ex
                 if (!nexthop_exists(nexthop))
                         continue;
 
+                /* Ignore nexthops bound to other links. */
+                if (nexthop->ifindex > 0 && nexthop->ifindex != link->ifindex)
+                        continue;
+
                 nexthop_mark(nexthop);
         }
 
         /* Then, unmark all nexthops requested by active links. */
-        HASHMAP_FOREACH(link, manager->links_by_index) {
-                if (link == except)
+        HASHMAP_FOREACH(other, link->manager->links_by_index) {
+                if (!foreign && other == link)
                         continue;
 
-                if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                if (!IN_SET(other->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
                         continue;
 
-                HASHMAP_FOREACH(nexthop, link->network->nexthops_by_section) {
+                HASHMAP_FOREACH(nexthop, other->network->nexthops_by_section) {
                         NextHop *existing;
 
-                        if (nexthop_get(manager, NULL, nexthop, &existing) >= 0)
+                        if (nexthop_get(other, nexthop, &existing) >= 0)
                                 nexthop_unmark(existing);
                 }
         }
 }
 
-static int manager_drop_marked_nexthops(Manager *manager) {
-        NextHop *nexthop;
-        int r = 0;
-
-        assert(manager);
-
-        SET_FOREACH(nexthop, manager->nexthops) {
-                if (!nexthop_is_marked(nexthop))
-                        continue;
-
-                RET_GATHER(r, nexthop_remove(nexthop));
-        }
-
-        return r;
-}
-
-int link_drop_foreign_nexthops(Link *link) {
+int link_drop_nexthops(Link *link, bool foreign) {
         NextHop *nexthop;
         int r = 0;
 
         assert(link);
         assert(link->manager);
-        assert(link->network);
 
-        /* First, mark all nexthops. */
-        SET_FOREACH(nexthop, link->nexthops) {
-                /* do not touch nexthop created by the kernel */
-                if (nexthop->protocol == RTPROT_KERNEL)
-                        continue;
+        link_mark_nexthops(link, foreign);
 
-                /* Do not remove nexthops we configured. */
-                if (nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN)
-                        continue;
-
-                /* Ignore nexthops not assigned yet or already removed. */
-                if (!nexthop_exists(nexthop))
-                        continue;
-
-                nexthop_mark(nexthop);
-        }
-
-        /* Then, unmark all nexthops requested by active links. */
-        HASHMAP_FOREACH(nexthop, link->network->nexthops_by_section) {
-                NextHop *existing;
-
-                if (nexthop_get(NULL, link, nexthop, &existing) >= 0)
-                        nexthop_unmark(existing);
-        }
-
-        /* Finally, remove all marked rules. */
-        SET_FOREACH(nexthop, link->nexthops) {
+        HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) {
                 if (!nexthop_is_marked(nexthop))
                         continue;
 
                 RET_GATHER(r, nexthop_remove(nexthop));
         }
 
-        manager_mark_nexthops(link->manager, /* foreign = */ true, NULL);
-
-        return RET_GATHER(r, manager_drop_marked_nexthops(link->manager));
-}
-
-int link_drop_managed_nexthops(Link *link) {
-        NextHop *nexthop;
-        int r = 0;
-
-        assert(link);
-        assert(link->manager);
-
-        SET_FOREACH(nexthop, link->nexthops) {
-                /* do not touch nexthop created by the kernel */
-                if (nexthop->protocol == RTPROT_KERNEL)
-                        continue;
-
-                /* Do not touch addresses managed by kernel or other tools. */
-                if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN)
-                        continue;
-
-                /* Ignore nexthops not assigned yet or already removing. */
-                if (!nexthop_exists(nexthop))
-                        continue;
-
-                RET_GATHER(r, nexthop_remove(nexthop));
-        }
-
-        manager_mark_nexthops(link->manager, /* foreign = */ false, link);
-
-        return RET_GATHER(r, manager_drop_marked_nexthops(link->manager));
+        return r;
 }
 
 void link_foreignize_nexthops(Link *link) {
         NextHop *nexthop;
 
         assert(link);
+        assert(link->manager);
 
-        SET_FOREACH(nexthop, link->nexthops)
-                nexthop->source = NETWORK_CONFIG_SOURCE_FOREIGN;
-
-        manager_mark_nexthops(link->manager, /* foreign = */ false, link);
+        link_mark_nexthops(link, /* foreign = */ false);
 
-        SET_FOREACH(nexthop, link->manager->nexthops) {
+        HASHMAP_FOREACH(nexthop, link->manager->nexthops_by_id) {
                 if (!nexthop_is_marked(nexthop))
                         continue;
 
@@ -963,19 +866,21 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
         if (!nexthop_bound_to_link(tmp))
                 link = NULL;
 
-        (void) nexthop_get(m, link, tmp, &nexthop);
+        tmp->ifindex = link ? link->ifindex : 0;
+
+        (void) nexthop_get_by_id(m, tmp->id, &nexthop);
 
         switch (type) {
         case RTM_NEWNEXTHOP:
                 if (nexthop) {
                         nexthop->flags = tmp->flags;
                         nexthop_enter_configured(nexthop);
-                        log_nexthop_debug(tmp, "Received remembered", link);
+                        log_nexthop_debug(tmp, "Received remembered", m);
                 } else {
                         nexthop_enter_configured(tmp);
-                        log_nexthop_debug(tmp, "Remembering", link);
+                        log_nexthop_debug(tmp, "Remembering", m);
 
-                        r = nexthop_add(m, link, tmp);
+                        r = nexthop_add(m, tmp);
                         if (r < 0) {
                                 log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
                                 return 0;
@@ -989,12 +894,12 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
                 if (nexthop) {
                         nexthop_enter_removed(nexthop);
                         if (nexthop->state == 0) {
-                                log_nexthop_debug(nexthop, "Forgetting", link);
+                                log_nexthop_debug(nexthop, "Forgetting", m);
                                 nexthop_free(nexthop);
                         } else
-                                log_nexthop_debug(nexthop, "Removed", link);
+                                log_nexthop_debug(nexthop, "Removed", m);
                 } else
-                        log_nexthop_debug(tmp, "Kernel removed unknown", link);
+                        log_nexthop_debug(tmp, "Kernel removed unknown", m);
                 break;
 
         default:
index 6e5643015b4b2381067f48f399ebcf02cfac6dd8..c1d39e6e8ea9b5115d45ea203491a952969aeaae 100644 (file)
@@ -20,13 +20,12 @@ typedef struct Network Network;
 typedef struct NextHop {
         Network *network;
         Manager *manager;
-        Link *link;
         ConfigSection *section;
         NetworkConfigSource source;
         NetworkConfigState state;
 
         uint8_t protocol;
-
+        int ifindex;
         uint32_t id;
         bool blackhole;
         int family;
@@ -40,8 +39,13 @@ NextHop *nexthop_free(NextHop *nexthop);
 
 void network_drop_invalid_nexthops(Network *network);
 
-int link_drop_managed_nexthops(Link *link);
-int link_drop_foreign_nexthops(Link *link);
+int link_drop_nexthops(Link *link, bool foreign);
+static inline int link_drop_foreign_nexthops(Link *link) {
+        return link_drop_nexthops(link, /* foreign = */ true);
+}
+static inline int link_drop_managed_nexthops(Link *link) {
+        return link_drop_nexthops(link, /* foreign = */ false);
+}
 void link_foreignize_nexthops(Link *link);
 
 int link_request_static_nexthops(Link *link, bool only_ipv4);
index 3cb1f80e5f00b7a096fd5a0dd544460c19e35d1b..c0189ae899a85abab2bd4bec9c8c68fcfa36d458 100644 (file)
@@ -475,7 +475,7 @@ static int route_convert(Manager *manager, const Route *route, ConvertedRoutes *
                                 return r;
 
                         route_apply_nexthop(c->routes[0], nh, UINT8_MAX);
-                        c->links[0] = nh->link;
+                        (void) link_get_by_index(manager, nh->ifindex, c->links);
 
                         *ret = TAKE_PTR(c);
                         return 1;
@@ -498,7 +498,7 @@ static int route_convert(Manager *manager, const Route *route, ConvertedRoutes *
                                 return r;
 
                         route_apply_nexthop(c->routes[i], h, nhg->weight);
-                        c->links[i] = h->link;
+                        (void) link_get_by_index(manager, h->ifindex, c->links + i);
 
                         i++;
                 }