network/route: forget IPv4 non-local routes when an interface went down
When an interface went down, IPv4 non-local routes are removed by the kernel without any notifications. Let's forget the routes in that case. Fixes #35047.
This commit is contained in:
committed by
Luca Boccassi
parent
fd2ea787bd
commit
6954c38cf8
@@ -1895,6 +1895,8 @@ static int link_admin_state_up(Link *link) {
|
||||
static int link_admin_state_down(Link *link) {
|
||||
assert(link);
|
||||
|
||||
link_forget_routes(link);
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/ipv6_route.h>
|
||||
#include <linux/nexthop.h>
|
||||
|
||||
@@ -1540,6 +1541,37 @@ int link_drop_routes(Link *link, bool only_static) {
|
||||
return r;
|
||||
}
|
||||
|
||||
void link_forget_routes(Link *link) {
|
||||
assert(link);
|
||||
assert(link->ifindex > 0);
|
||||
assert(!FLAGS_SET(link->flags, IFF_UP));
|
||||
|
||||
/* When an interface went down, IPv4 non-local routes bound to the interface are silently removed by
|
||||
* the kernel, without any notifications. Let's forget them in that case. Otherwise, when the link
|
||||
* goes up later, the configuration order of routes may be confused by the nonexistent routes.
|
||||
* See issue #35047. */
|
||||
|
||||
Route *route;
|
||||
SET_FOREACH(route, link->manager->routes) {
|
||||
// TODO: handle multipath routes
|
||||
if (route->nexthop.ifindex != link->ifindex)
|
||||
continue;
|
||||
if (route->family != AF_INET)
|
||||
continue;
|
||||
// TODO: check RTN_NAT and RTN_XRESOLVE
|
||||
if (!IN_SET(route->type, RTN_UNICAST, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST))
|
||||
continue;
|
||||
|
||||
Request *req;
|
||||
if (route_get_request(link->manager, route, &req) >= 0)
|
||||
route_enter_removed(req->userdata);
|
||||
|
||||
route_enter_removed(route);
|
||||
log_route_debug(route, "Forgetting silently removed", link->manager);
|
||||
route_detach(route);
|
||||
}
|
||||
}
|
||||
|
||||
int network_add_ipv4ll_route(Network *network) {
|
||||
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
|
||||
unsigned section_line;
|
||||
|
||||
@@ -111,6 +111,7 @@ static inline int link_drop_static_routes(Link *link) {
|
||||
static inline int link_drop_unmanaged_routes(Link *link) {
|
||||
return link_drop_routes(link, false);
|
||||
}
|
||||
void link_forget_routes(Link *link);
|
||||
|
||||
int link_request_route(
|
||||
Link *link,
|
||||
|
||||
Reference in New Issue
Block a user