]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/route: drop Route object even if we fail to remove the route
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 7 Jan 2024 05:41:56 +0000 (14:41 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 25 Jan 2024 07:43:44 +0000 (16:43 +0900)
If we could not remove a route, then previously the corresponding
Route object was never removed, as it was freed only when we receive
remove notification from the kernel. So, we might confused that the
route still exists and being removed, and might block reconfiguring
the route.

With this change, even if we fail to remove a route, the corresponding
Route object will be freed.

This is the one for routes of 56a995fe8e50b2432ff930ed0431cc70adbe492d.

src/network/networkd-route.c

index 89a96cbda11ceb01d77ed97c8106c6e642752147..147d9cb14fde5a7c40a2791e38cc148b3faf6558 100644 (file)
@@ -526,19 +526,35 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *m)
         return 0;
 }
 
-static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, RemoveRequest *rreq) {
         int r;
 
         assert(m);
+        assert(rreq);
 
-        /* link may be NULL. */
-
-        if (link && IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
+        Manager *manager = ASSERT_PTR(rreq->manager);
+        Route *route = ASSERT_PTR(rreq->userdata);
 
         r = sd_netlink_message_get_errno(m);
-        if (r < 0 && r != -ESRCH)
-                log_link_message_warning_errno(link, m, r, "Could not drop route, ignoring");
+        if (r < 0) {
+                log_message_full_errno(m,
+                                       (r == -ESRCH || /* the route is already removed? */
+                                        (r == -EINVAL && route->nexthop_id != 0) || /* The nexthop is already removed? */
+                                        !route->manager) ? /* already detached? */
+                                       LOG_DEBUG : LOG_WARNING,
+                                       r, "Could not drop route, ignoring");
+
+                if (route->manager) {
+                        /* If the route cannot be removed, then assume the route is already removed. */
+                        log_route_debug(route, "Forgetting", manager);
+
+                        Request *req;
+                        if (route_get_request(manager, route, &req) >= 0)
+                                route_enter_removed(req->userdata);
+
+                        route_detach(route);
+                }
+        }
 
         return 1;
 }
@@ -563,12 +579,9 @@ int route_remove(Route *route, Manager *manager) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "Could not fill netlink message: %m");
 
-        r = netlink_call_async(manager->rtnl, NULL, m, route_remove_handler,
-                               link ? link_netlink_destroy_callback : NULL, link);
+        r = manager_remove_request_add(manager, route, route, manager->rtnl, m, route_remove_handler);
         if (r < 0)
-                return log_link_warning_errno(link, r, "Could not send netlink message: %m");
-
-        link_ref(link);
+                return log_link_warning_errno(link, r, "Could not queue rtnetlink message: %m");
 
         route_enter_removing(route);
         return 0;