From f02ba163891bab73a80332b4599a9d73083cb6c2 Mon Sep 17 00:00:00 2001 From: Daniel Dao Date: Mon, 26 Feb 2018 14:33:16 +0000 Subject: [PATCH] setup route expiration in kernel if supported kernel >= 4.5 (with commit https://github.com/torvalds/linux/commit/32bc201e1974976b7d3fea9a9b17bb7392ca6394) supports RTA_EXPIRES netlink attribute to set router lifetime. This simply detect the kernel version (>=4.5) and set the lifetime properly, fallback to expiring route in userspace for kernel that doesnt support it. Signed-off-by: Daniel Dao --- src/basic/missing.h | 4 ++++ src/libsystemd/sd-netlink/netlink-types.c | 6 +++++- src/network/networkd-link.c | 2 +- src/network/networkd-route.c | 9 ++++++++- src/network/networkd-util.c | 21 +++++++++++++++++++++ src/network/networkd-util.h | 2 ++ 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/basic/missing.h b/src/basic/missing.h index 1cc3f08e48..567aea8da9 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -1058,6 +1058,10 @@ struct input_mask { #define RTAX_QUICKACK 15 #endif +#ifndef RTA_EXPIRES +#define RTA_EXPIRES 23 +#endif + #ifndef IPV6_UNICAST_IF #define IPV6_UNICAST_IF 76 #endif diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 0ee7d6f0dc..dcee2d2a27 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -582,7 +582,11 @@ static const NLType rtnl_route_types[] = { RTA_NEWDST, */ [RTA_PREF] = { .type = NETLINK_TYPE_U8 }, - +/* + RTA_ENCAP_TYPE, + RTA_ENCAP, + */ + [RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_route_type_system = { diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 64c45080df..cc9073fac3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2964,7 +2964,7 @@ network_file_fail: if (r < 0) return log_link_error_errno(link, r, "Failed to add route: %m"); - if (lifetime != USEC_INFINITY) { + if (lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime, 0, route_expire_handler, route); if (r < 0) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 70dca5219b..d25be44a10 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -617,6 +617,13 @@ int route_configure( if (r < 0) return log_error_errno(r, "Could not append RTA_PREF attribute: %m"); + if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) { + 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)); + if (r < 0) + return log_error_errno(r, "Could not append RTA_EXPIRES attribute: %m"); + } + r = sd_rtnl_message_route_set_type(req, route->type); if (r < 0) return log_error_errno(r, "Could not set route type: %m"); @@ -674,7 +681,7 @@ int route_configure( /* TODO: drop expiration handling once it can be pushed into the kernel */ route->lifetime = lifetime; - if (route->lifetime != USEC_INFINITY) { + if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), route->lifetime, 0, route_expire_handler, route); if (r < 0) diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index b9c533fcc7..7ea14155b6 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -18,6 +18,7 @@ along with systemd; If not, see . ***/ +#include "condition.h" #include "conf-parser.h" #include "networkd-util.h" #include "parse-util.h" @@ -99,3 +100,23 @@ int config_parse_address_family_boolean_with_kernel( return 0; } + +/* Router lifetime can be set with netlink interface since kernel >= 4.5 + * so for the supported kernel we dont 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); + if (r < 0) + return r; + + cached = r; + } + return cached; +} diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index 69ea93ad08..e8c3399937 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -37,3 +37,5 @@ int config_parse_address_family_boolean_with_kernel(const char* unit, const char const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; + +int kernel_route_expiration_supported(void);