diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-07 06:41:56 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-25 08:43:44 +0100 |
commit | d529b12a01ff251b0fe631e5ad6dc90f4faad8ce (patch) | |
tree | 95d209a1ed05c63b0e51af8e377ecf29eb71d021 /src/network/networkd-route.c | |
parent | network/route: introduce ref/unref functions for Route object (diff) | |
download | systemd-d529b12a01ff251b0fe631e5ad6dc90f4faad8ce.tar.xz systemd-d529b12a01ff251b0fe631e5ad6dc90f4faad8ce.zip |
network/route: drop Route object even if we fail to remove the route
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.
Diffstat (limited to 'src/network/networkd-route.c')
-rw-r--r-- | src/network/networkd-route.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 89a96cbda1..147d9cb14f 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -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; |