diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index b8b03f6d3b..d8f9a2c053 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -176,8 +176,7 @@ int dhcp_pd_remove(Link *link, bool only_marked) { link_remove_dhcp_pd_subnet_prefix(link, &route->dst.in6); - RET_GATHER(ret, route_remove(route)); - route_cancel_request(route, link); + RET_GATHER(ret, route_remove_and_cancel(route, link->manager)); } } else { Address *address; @@ -612,9 +611,7 @@ void dhcp_pd_prefix_lost(Link *uplink) { .address = route->dst })) continue; - (void) route_remove(route); - - route_cancel_request(route, uplink); + (void) route_remove_and_cancel(route, uplink->manager); } set_clear(uplink->dhcp_pd_prefixes); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index be7abcf6f3..1a1836cf66 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -256,8 +256,7 @@ static int dhcp4_remove_address_and_routes(Link *link, bool only_marked) { if (only_marked && !route_is_marked(route)) continue; - RET_GATHER(ret, route_remove(route)); - route_cancel_request(route, link); + RET_GATHER(ret, route_remove_and_cancel(route, link->manager)); } SET_FOREACH(address, link->addresses) { diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 26ed034bbe..eb1420be5c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -62,8 +62,7 @@ static int dhcp6_remove(Link *link, bool only_marked) { if (only_marked && !route_is_marked(route)) continue; - RET_GATHER(ret, route_remove(route)); - route_cancel_request(route, link); + RET_GATHER(ret, route_remove_and_cancel(route, link->manager)); } SET_FOREACH(address, link->addresses) { diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 7186187fd8..488c8c0294 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1173,7 +1173,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (route->lifetime_usec >= timestamp_usec) continue; /* the route is still valid */ - r = route_remove_and_drop(route); + r = route_remove_and_cancel(route, link->manager); if (r < 0) RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC route, ignoring: %m")); } diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 3a33769f8b..efb121cb82 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -510,13 +510,13 @@ static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *l return 1; } -int route_remove(Route *route) { +int route_remove(Route *route, Manager *manager) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; Link *link = NULL; int r; assert(route); - Manager *manager = ASSERT_PTR(route->manager); + assert(manager); log_route_debug(route, "Removing", manager); @@ -541,17 +541,27 @@ int route_remove(Route *route) { return 0; } -int route_remove_and_drop(Route *route) { - if (!route) - return 0; +int route_remove_and_cancel(Route *route, Manager *manager) { + bool waiting = false; + Request *req; - route_cancel_request(route, NULL); + assert(route); + assert(manager); - if (route_exists(route)) - return route_remove(route); + /* If the route is remembered by the manager, then use the remembered object. */ + (void) route_get(manager, route, &route); - if (route->state == 0) - route_free(route); + /* Cancel the request for the route. If the request is already called but we have not received the + * notification about the request, then explicitly remove the route. */ + if (route_get_request(manager, route, &req) >= 0) { + waiting = req->waiting_reply; + request_detach(req); + route_cancel_requesting(route); + } + + /* If we know that the route will come or already exists, remove it. */ + if (waiting || (route->manager && route_exists(route))) + return route_remove(route, manager); return 0; } @@ -562,7 +572,7 @@ static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdat assert(route->manager); - r = route_remove(route); + r = route_remove(route, route->manager); if (r < 0) { Link *link = NULL; (void) route_get_link(route->manager, route, &link); @@ -944,20 +954,6 @@ int link_request_static_routes(Link *link, bool only_ipv4) { return 0; } -void route_cancel_request(Route *route, Link *link) { - assert(route); - Manager *manager = ASSERT_PTR(route->manager ?: ASSERT_PTR(link)->manager); - - if (!route_is_requesting(route)) - return; - - Request *req; - if (route_get_request(manager, route, &req) >= 0) - request_detach(req); - - route_cancel_requesting(route); -} - static int process_route_one( Manager *manager, uint16_t type, @@ -1376,7 +1372,7 @@ int link_drop_routes(Link *link, bool foreign) { if (!route_is_marked(route)) continue; - RET_GATHER(r, route_remove(route)); + RET_GATHER(r, route_remove(route, link->manager)); } return r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 090bf34a61..51a06dd0f1 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -88,8 +88,8 @@ int route_new_static(Network *network, const char *filename, unsigned section_li int route_dup(const Route *src, const RouteNextHop *nh, Route **ret); int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, Route *route, const char *error_msg); -int route_remove(Route *route); -int route_remove_and_drop(Route *route); +int route_remove(Route *route, Manager *manager); +int route_remove_and_cancel(Route *route, Manager *manager); int route_get(Manager *manager, const Route *route, Route **ret); @@ -102,7 +102,6 @@ static inline int link_drop_foreign_routes(Link *link) { } int link_foreignize_routes(Link *link); -void route_cancel_request(Route *route, Link *link); int link_request_route( Link *link, const Route *route,