summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-nexthop.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-01-15 05:14:46 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-01-16 04:48:50 +0100
commit3cbbe8635a16f096a3b0eff993f7681401535605 (patch)
tree56e1f411fb501c29a7a7ba6d45a81930f96d828d /src/network/networkd-nexthop.c
parentnetwork/nexthop: introduce a reverse map of nexthop group members (diff)
downloadsystemd-3cbbe8635a16f096a3b0eff993f7681401535605.tar.xz
systemd-3cbbe8635a16f096a3b0eff993f7681401535605.zip
network/nexthop: drop dependent nexthops on removal
If a nexthop is removed, dependent nexthops are silently removed by the kernel. Hence, networkd may be confused that nexthops that depends on the nexthop still exist, and may fail to configure other routes or so.
Diffstat (limited to '')
-rw-r--r--src/network/networkd-nexthop.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c
index 49856c483a..cf62e0e82d 100644
--- a/src/network/networkd-nexthop.c
+++ b/src/network/networkd-nexthop.c
@@ -482,6 +482,29 @@ static void log_nexthop_debug(const NextHop *nexthop, const char *str, Manager *
yes_no(nexthop->blackhole), strna(group), strna(flags));
}
+static int nexthop_remove_dependents(NextHop *nexthop, Manager *manager) {
+ int r = 0;
+
+ assert(nexthop);
+ assert(manager);
+
+ /* If a nexthop is removed, the kernel silently removes nexthops that depend on the
+ * removed nexthop. Let's remove them for safety (though, they are already removed in the kernel,
+ * hence that should fail), and forget them. */
+
+ void *id;
+ SET_FOREACH(id, nexthop->nexthops) {
+ NextHop *nh;
+
+ if (nexthop_get_by_id(manager, PTR_TO_UINT32(id), &nh) < 0)
+ continue;
+
+ RET_GATHER(r, nexthop_remove(nh, manager));
+ }
+
+ return r;
+}
+
static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, RemoveRequest *rreq) {
int r;
@@ -497,6 +520,8 @@ static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Remov
(r == -ENOENT || !nexthop->manager) ? LOG_DEBUG : LOG_WARNING,
r, "Could not drop nexthop, ignoring");
+ (void) nexthop_remove_dependents(nexthop, manager);
+
if (nexthop->manager) {
/* If the nexthop cannot be removed, then assume the nexthop is already removed. */
log_nexthop_debug(nexthop, "Forgetting", manager);
@@ -1014,6 +1039,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
if (nexthop) {
nexthop_enter_removed(nexthop);
log_nexthop_debug(nexthop, "Forgetting removed", m);
+ (void) nexthop_remove_dependents(nexthop, m);
nexthop_detach(nexthop);
} else
log_nexthop_debug(&(const NextHop) { .id = id }, "Kernel removed unknown", m);