networkd: route - add expiration support

This should really live in the kernel, but the netlink API currently
does not support it. Until support has been added, expire the route
from userspace.
This commit is contained in:
Tom Gundersen 2015-10-26 12:29:37 +01:00
parent f703cc2c57
commit f833694d4f
3 changed files with 65 additions and 7 deletions

View File

@ -26,6 +26,7 @@
#include "alloc-util.h"
#include "bus-util.h"
#include "dhcp-lease-internal.h"
#include "event-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "netlink-util.h"
@ -2227,6 +2228,9 @@ network_file_fail:
return log_oom();
STRV_FOREACH(route_str, routes_strv) {
Route *route;
_cleanup_event_source_unref_ sd_event_source *expire = NULL;
usec_t lifetime;
char *prefixlen_str;
int family;
unsigned char prefixlen, tos, table;
@ -2240,9 +2244,11 @@ network_file_fail:
*prefixlen_str ++ = '\0';
r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu", &prefixlen, &tos, &priority, &table);
if (r != 4) {
log_link_debug(link, "Failed to parse destination prefix length, tos, priority or table %s", prefixlen_str);
r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime);
if (r != 5) {
log_link_debug(link,
"Failed to parse destination prefix length, tos, priority, table or expiration %s",
prefixlen_str);
continue;
}
@ -2252,9 +2258,21 @@ network_file_fail:
continue;
}
r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, NULL);
r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add route: %m");
if (lifetime != USEC_INFINITY) {
r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime,
0, route_expire_handler, route);
if (r < 0)
log_link_warning_errno(link, r, "Could not arm route expiration handler: %m");
}
route->lifetime = lifetime;
sd_event_source_unref(route->expire);
route->expire = expire;
expire = NULL;
}
}
@ -2741,8 +2759,8 @@ int link_save(Link *link) {
if (r < 0)
goto fail;
fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu", space ? " " : "", route_str,
route->dst_prefixlen, route->tos, route->priority, route->table);
fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str,
route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
space = true;
}

View File

@ -21,6 +21,7 @@
#include "alloc-util.h"
#include "conf-parser.h"
#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
#include "networkd-route.h"
@ -41,6 +42,7 @@ int route_new(Route **ret) {
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_UNSPEC;
route->table = RT_TABLE_DEFAULT;
route->lifetime = USEC_INFINITY;
*ret = route;
route = NULL;
@ -101,6 +103,8 @@ void route_free(Route *route) {
set_remove(route->link->routes_foreign, route);
}
sd_event_source_unref(route->expire);
free(route);
}
@ -410,9 +414,24 @@ int route_remove(Route *route, Link *link,
return 0;
}
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
Route *route = userdata;
int r;
assert(route);
r = route_remove(route, route->link, NULL);
if (r < 0)
log_warning_errno(r, "Could not remove route: %m");
return 1;
}
int route_configure(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
_cleanup_event_source_unref_ sd_event_source *expire = NULL;
usec_t lifetime;
int r;
assert(link);
@ -489,10 +508,26 @@ int route_configure(Route *route, Link *link,
link_ref(link);
r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
lifetime = route->lifetime;
r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
if (r < 0)
return log_error_errno(r, "Could not add route: %m");
/* TODO: drop expiration handling once it can be pushed into the kernel */
route->lifetime = lifetime;
if (route->lifetime != USEC_INFINITY) {
r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
route->lifetime, 0, route_expire_handler, route);
if (r < 0)
return log_error_errno(r, "Could not arm expiration timer: %m");
}
sd_event_source_unref(route->expire);
route->expire = expire;
expire = NULL;
return 0;
}

View File

@ -46,6 +46,9 @@ struct Route {
union in_addr_union src;
union in_addr_union prefsrc;
usec_t lifetime;
sd_event_source *expire;
LIST_FIELDS(Route, routes);
};
@ -61,6 +64,8 @@ int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned
int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
void route_drop(Route *route);
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
#define _cleanup_route_free_ _cleanup_(route_freep)