1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-22 13:33:56 +03:00

Merge pull request #21035 from yuwata/network-route-fix-lifetime

network: route: drop kernel version check
This commit is contained in:
Yu Watanabe 2021-10-20 01:48:44 +09:00 committed by GitHub
commit a2ca8c54cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 38 deletions

View File

@ -5,6 +5,7 @@
#include <linux/nexthop.h>
#include "alloc-util.h"
#include "event-util.h"
#include "netlink-util.h"
#include "networkd-address.h"
#include "networkd-ipv4ll.h"
@ -1230,10 +1231,9 @@ static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdat
return 1;
}
static int route_setup_timer(Route *route) {
static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo) {
Manager *manager;
/* TODO: drop expiration handling once it can be pushed into the kernel */
int r;
assert(route);
assert(route->manager || (route->link && route->link->manager));
@ -1243,13 +1243,16 @@ static int route_setup_timer(Route *route) {
if (route->lifetime == USEC_INFINITY)
return 0;
if (kernel_route_expiration_supported())
if (cacheinfo && cacheinfo->rta_expires != 0)
/* Assume that non-zero rta_expires means kernel will handle the route expiration. */
return 0;
sd_event_source_disable_unref(route->expire);
r = event_reset_time(manager->event, &route->expire, clock_boottime_or_monotonic(),
route->lifetime, 0, route_expire_handler, route, 0, "route-expiration", true);
if (r < 0)
return r;
return sd_event_add_time(manager->event, &route->expire, clock_boottime_or_monotonic(),
route->lifetime, 0, route_expire_handler, route);
return 1;
}
static int append_nexthop_one(const Link *link, const Route *route, const MultipathRoute *m, struct rtattr **rta, size_t offset) {
@ -1389,9 +1392,9 @@ static int route_configure(
if (r < 0)
return r;
if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
if (route->lifetime != USEC_INFINITY) {
r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
}
@ -1730,10 +1733,6 @@ int request_process_route(Request *req) {
existing->provider = converted->routes[i]->provider;
}
}
} else {
r = route_setup_timer(route);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to setup timer for route: %m");
}
r = route_configure(route, link, req->netlink_handler);
@ -1753,7 +1752,13 @@ int request_process_route(Request *req) {
return 1;
}
static int process_route_one(Manager *manager, Link *link, uint16_t type, Route *in) {
static int process_route_one(
Manager *manager,
Link *link,
uint16_t type,
Route *in,
const struct rta_cacheinfo *cacheinfo) {
_cleanup_(route_freep) Route *tmp = in;
Route *route = NULL;
int r;
@ -1772,6 +1777,12 @@ static int process_route_one(Manager *manager, Link *link, uint16_t type, Route
route_enter_configured(route);
log_route_debug(route, "Received remembered", link, manager);
r = route_setup_timer(route, cacheinfo);
if (r < 0)
log_link_warning_errno(link, r, "Failed to configure expiration timer for route, ignoring: %m");
if (r > 0)
log_route_debug(route, "Configured expiration timer for", link, manager);
} else if (!manager->manage_foreign_routes) {
route_enter_configured(tmp);
log_route_debug(tmp, "Ignoring received", link, manager);
@ -1816,6 +1827,8 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
_cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL;
_cleanup_(route_freep) Route *tmp = NULL;
_cleanup_free_ void *rta_multipath = NULL;
struct rta_cacheinfo cacheinfo;
bool has_cacheinfo;
Link *link = NULL;
uint32_t ifindex;
uint16_t type;
@ -2012,6 +2025,13 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
}
}
r = sd_netlink_message_read(message, RTA_CACHEINFO, sizeof(cacheinfo), &cacheinfo);
if (r < 0 && r != -ENODATA) {
log_link_warning_errno(link, r, "rtnl: failed to read RTA_CACHEINFO attribute, ignoring: %m");
return 0;
}
has_cacheinfo = r >= 0;
/* IPv6 routes with reject type are always assigned to the loopback interface. See kernel's
* fib6_nh_init() in net/ipv6/route.c. However, we'd like to manage them by Manager. Hence, set
* link to NULL here. */
@ -2019,7 +2039,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
link = NULL;
if (!route_needs_convert(tmp))
return process_route_one(m, link, type, TAKE_PTR(tmp));
return process_route_one(m, link, type, TAKE_PTR(tmp), has_cacheinfo ? &cacheinfo : NULL);
r = route_convert(m, tmp, &converted);
if (r < 0) {
@ -2031,7 +2051,11 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
assert(converted);
for (size_t i = 0; i < converted->n; i++)
(void) process_route_one(m, converted->links[i] ?: link, type, TAKE_PTR(converted->routes[i]));
(void) process_route_one(m,
converted->links[i] ?: link,
type,
TAKE_PTR(converted->routes[i]),
has_cacheinfo ? &cacheinfo : NULL);
return 1;
}

View File

@ -242,26 +242,6 @@ int config_parse_mud_url(
return free_and_replace(*url, unescaped);
}
/* Router lifetime can be set with netlink interface since kernel >= 4.5
* so for the supported kernel we don't need to expire routes in userspace */
int kernel_route_expiration_supported(void) {
static int cached = -1;
int r;
if (cached < 0) {
Condition c = {
.type = CONDITION_KERNEL_VERSION,
.parameter = (char *) ">= 4.5"
};
r = condition_test(&c, NULL);
if (r < 0)
return r;
cached = r;
}
return cached;
}
static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
siphash24_compress_string(c->filename, state);
siphash24_compress(&c->line, sizeof(c->line), state);

View File

@ -140,8 +140,6 @@ AddressFamily dhcp_deprecated_address_family_from_string(const char *s) _pure_;
const char *dhcp_lease_server_type_to_string(sd_dhcp_lease_server_type_t t) _const_;
sd_dhcp_lease_server_type_t dhcp_lease_server_type_from_string(const char *s) _pure_;
int kernel_route_expiration_supported(void);
static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
return mfree(cs);
}