From 91fc5135e644ec08cc6e983ade1488de02fc34c8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 21 Oct 2021 00:22:49 +0900 Subject: [PATCH 1/4] network: route: rename lifetime -> lifetime_usec --- src/network/networkd-dhcp6.c | 4 +-- src/network/networkd-ndisc.c | 48 +++++++++++++++++++----------------- src/network/networkd-route.c | 12 ++++----- src/network/networkd-route.h | 5 +++- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 2bbad4edbb..be3238337c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -310,7 +310,7 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, use route->dst_prefixlen = 64; route->protocol = RTPROT_DHCP; route->priority = link->network->dhcp6_pd_route_metric; - route->lifetime = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); if (route_get(NULL, link, route, &existing) < 0) link->dhcp6_pd_configured = false; @@ -778,7 +778,7 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad route->type = RTN_UNREACHABLE; route->protocol = RTPROT_DHCP; route->priority = DHCP_ROUTE_METRIC; - route->lifetime = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); if (route_get(link->manager, NULL, route, &existing) < 0) link->dhcp6_configured = false; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 956cc27380..5430821a2f 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -291,23 +291,29 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { _cleanup_(route_freep) Route *route = NULL; + usec_t lifetime_usec, timestamp_usec; struct in6_addr gateway; - uint32_t mtu = 0; + uint16_t lifetime_sec; unsigned preference; - uint16_t lifetime; - usec_t time_now; + uint32_t mtu = 0; int r; assert(link); assert(rt); - r = sd_ndisc_router_get_lifetime(rt, &lifetime); + r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m"); - if (lifetime == 0) /* not a default router */ + if (lifetime_sec == 0) /* not a default router */ return 0; + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + + lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + r = sd_ndisc_router_get_address(rt, &gateway); if (r < 0) return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); @@ -327,10 +333,6 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m"); - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); - if (link->network->ipv6_accept_ra_use_mtu) { r = sd_ndisc_router_get_mtu(rt, &mtu); if (r < 0 && r != -ENODATA) @@ -345,7 +347,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route->pref = preference; route->gw_family = AF_INET6; route->gw.in6 = gateway; - route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); + route->lifetime_usec = lifetime_usec; route->mtu = mtu; r = ndisc_request_route(TAKE_PTR(route), link, rt); @@ -367,7 +369,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route->gw.in6 = gateway; if (!route->pref_set) route->pref = preference; - route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); + route->lifetime_usec = lifetime_usec; if (route->mtu == 0) route->mtu = mtu; @@ -472,15 +474,15 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { _cleanup_(route_freep) Route *route = NULL; - usec_t time_now; - uint32_t lifetime; + usec_t timestamp_usec; + uint32_t lifetime_sec; unsigned prefixlen; int r; assert(link); assert(rt); - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -488,7 +490,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix length: %m"); - r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime); + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); @@ -499,7 +501,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { route->family = AF_INET6; route->flags = RTM_F_PREFIX; route->dst_prefixlen = prefixlen; - route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); + route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6); if (r < 0) @@ -514,19 +516,19 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { _cleanup_(route_freep) Route *route = NULL; - struct in6_addr gateway, dst; - uint32_t lifetime; unsigned preference, prefixlen; - usec_t time_now; + struct in6_addr gateway, dst; + uint32_t lifetime_sec; + usec_t timestamp_usec; int r; assert(link); - r = sd_ndisc_router_route_get_lifetime(rt, &lifetime); + r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m"); - if (lifetime == 0) + if (lifetime_sec == 0) return 0; r = sd_ndisc_router_route_get_address(rt, &dst); @@ -568,7 +570,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m"); - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -582,7 +584,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { route->gw_family = AF_INET6; route->dst.in6 = dst; route->dst_prefixlen = prefixlen; - route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); + route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 29e4b2b609..4dc6ecda62 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -186,7 +186,7 @@ int route_new(Route **ret) { .protocol = RTPROT_UNSPEC, .type = RTN_UNICAST, .table = RT_TABLE_MAIN, - .lifetime = USEC_INFINITY, + .lifetime_usec = USEC_INFINITY, .quickack = -1, .fast_open_no_cookie = -1, .gateway_onlink = -1, @@ -1240,7 +1240,7 @@ static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo manager = route->manager ?: route->link->manager; - if (route->lifetime == USEC_INFINITY) + if (route->lifetime_usec == USEC_INFINITY) return 0; if (cacheinfo && cacheinfo->rta_expires != 0) @@ -1248,7 +1248,7 @@ static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo return 0; r = event_reset_time(manager->event, &route->expire, clock_boottime_or_monotonic(), - route->lifetime, 0, route_expire_handler, route, 0, "route-expiration", true); + route->lifetime_usec, 0, route_expire_handler, route, 0, "route-expiration", true); if (r < 0) return r; @@ -1392,9 +1392,9 @@ static int route_configure( if (r < 0) return r; - if (route->lifetime != USEC_INFINITY) { + if (route->lifetime_usec != USEC_INFINITY) { r = sd_netlink_message_append_u32(req, RTA_EXPIRES, - MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX)); + MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, 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"); } @@ -3039,7 +3039,7 @@ static int route_section_verify(Route *route, Network *network) { return -EINVAL; /* Currently, we do not support static route with finite lifetime. */ - assert(route->lifetime == USEC_INFINITY); + assert(route->lifetime_usec == USEC_INFINITY); if (route->gateway_from_dhcp_or_ra) { if (route->gw_family == AF_UNSPEC) { diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 3e817de3ac..612d7d2809 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -61,7 +61,10 @@ typedef struct Route { union in_addr_union prefsrc; OrderedSet *multipath_routes; - usec_t lifetime; + /* This is an absolute point in time, and NOT a timespan/duration. + * Must be specified with clock_boottime_or_monotonic(). */ + usec_t lifetime_usec; + /* Used when kernel does not support RTA_EXPIRES attribute. */ sd_event_source *expire; } Route; From 09845af54b12de55f5678f8c2b4cd0d7a976dc1a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 21 Oct 2021 20:43:57 +0900 Subject: [PATCH 2/4] network: ndisc: add missing lifetime check --- src/network/networkd-ndisc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 5430821a2f..9ea4bf6557 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -482,6 +482,13 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { assert(link); assert(rt); + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); + + if (lifetime_sec == 0) + return 0; + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -490,10 +497,6 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix length: %m"); - r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); - r = route_new(&route); if (r < 0) return log_oom(); From 03ccc4b423b8659d3724829930fc511c420277f4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 21 Oct 2021 20:50:12 +0900 Subject: [PATCH 3/4] network: ndisc: rename valid_until -> lifetime_usec --- src/network/networkd-ndisc.c | 44 ++++++++++++++++++++---------------- src/network/networkd-ndisc.h | 8 +++++-- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 9ea4bf6557..9e3da746e3 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -612,10 +612,10 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( free); static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - uint32_t lifetime; + usec_t lifetime_usec, timestamp_usec; + uint32_t lifetime_sec; const struct in6_addr *a; struct in6_addr router; - usec_t time_now; bool updated = false; int n, r; @@ -626,21 +626,23 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); - r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime); + r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m"); + if (lifetime_sec == 0) + return 0; + + lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + n = sd_ndisc_router_rdnss_get_addresses(rt, &a); if (n < 0) return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); - if (lifetime == 0) - return 0; - if (n >= (int) NDISC_RDNSS_MAX) { log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX); n = NDISC_RDNSS_MAX; @@ -656,7 +658,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { if (rdnss) { rdnss->marked = false; rdnss->router = router; - rdnss->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC); + rdnss->lifetime_usec = lifetime_usec; continue; } @@ -667,7 +669,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { *x = (NDiscRDNSS) { .address = a[j], .router = router, - .valid_until = usec_add(time_now, lifetime * USEC_PER_SEC), + .lifetime_usec = lifetime_usec, }; r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x)); @@ -701,9 +703,9 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { _cleanup_strv_free_ char **l = NULL; + usec_t lifetime_usec, timestamp_usec; struct in6_addr router; - uint32_t lifetime; - usec_t time_now; + uint32_t lifetime_sec; bool updated = false; char **j; int r; @@ -715,21 +717,23 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); - r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime); + r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m"); + if (lifetime_sec == 0) + return 0; + + lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + r = sd_ndisc_router_dnssl_get_domains(rt, &l); if (r < 0) return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); - if (lifetime == 0) - return 0; - if (strv_length(l) >= NDISC_DNSSL_MAX) { log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX); STRV_FOREACH(j, l + NDISC_DNSSL_MAX) @@ -750,12 +754,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { if (dnssl) { dnssl->marked = false; dnssl->router = router; - dnssl->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC); + dnssl->lifetime_usec = lifetime_usec; continue; } s->router = router; - s->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC); + s->lifetime_usec = lifetime_usec; r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s)); if (r < 0) @@ -1047,11 +1051,11 @@ void ndisc_vacuum(Link *link) { time_now = now(clock_boottime_or_monotonic()); SET_FOREACH(r, link->ndisc_rdnss) - if (r->valid_until < time_now) + if (r->lifetime_usec < time_now) free(set_remove(link->ndisc_rdnss, r)); SET_FOREACH(d, link->ndisc_dnssl) - if (d->valid_until < time_now) + if (d->lifetime_usec < time_now) free(set_remove(link->ndisc_dnssl, d)); } diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index ed50ebbf9a..acb97a892e 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -19,7 +19,9 @@ typedef struct NDiscRDNSS { /* Used when GC'ing old DNS servers when configuration changes. */ bool marked; struct in6_addr router; - usec_t valid_until; + /* This is an absolute point in time, and NOT a timespan/duration. + * Must be specified with clock_boottime_or_monotonic(). */ + usec_t lifetime_usec; struct in6_addr address; } NDiscRDNSS; @@ -27,7 +29,9 @@ typedef struct NDiscDNSSL { /* Used when GC'ing old domains when configuration changes. */ bool marked; struct in6_addr router; - usec_t valid_until; + /* This is an absolute point in time, and NOT a timespan/duration. + * Must be specified with clock_boottime_or_monotonic(). */ + usec_t lifetime_usec; /* The domain name follows immediately. */ } NDiscDNSSL; From 16bc8635d551f73cdd9cf5c9d452f3ad9c34e9e4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 21 Oct 2021 02:21:59 +0900 Subject: [PATCH 4/4] network: address: use usec_t for handling lifetime This drops stuct ifa_cacheinfo from Address, and store lifetime with usec_t. Why? Now, all requests of address configurations are once stored in the request queue, and will be processed when it is ready. So, the timestamp value passed to the kernel must be evaluated on configure. This also fixes the following two issues. - Time values in struct ifa_cacheinfo are stored in uint32_t. So, the validity check of the address configured by NDisc may fail on long running systems. - If a system uses DHCPv6PD, when an interface may appear or be reconfigured later, then the lifetime value may be inappropriate. We need to adjust the lifetime with the current time and the timestamp of the lease. --- src/network/networkd-address.c | 66 ++++++++++++++++----- src/network/networkd-address.h | 11 ++-- src/network/networkd-dhcp4.c | 22 +++---- src/network/networkd-dhcp6.c | 91 ++++++++++++++++------------- src/network/networkd-ndisc.c | 27 +++++---- src/network/networkd-radv.c | 11 ++-- src/network/networkd-radv.h | 2 +- src/network/test-networkd-address.c | 17 ++++-- 8 files changed, 152 insertions(+), 95 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 33afdb0335..78e011a855 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -67,8 +67,8 @@ int address_new(Address **ret) { *address = (Address) { .family = AF_UNSPEC, .scope = RT_SCOPE_UNIVERSE, - .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME, - .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME, + .lifetime_valid_usec = USEC_INFINITY, + .lifetime_preferred_usec = USEC_INFINITY, .set_broadcast = -1, .duplicate_address_detection = ADDRESS_FAMILY_IPV6, }; @@ -224,6 +224,41 @@ static bool address_may_set_broadcast(const Address *a, const Link *link) { return !streq_ptr(link->kind, "wireguard"); } +static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cacheinfo *cinfo) { + usec_t now_usec; + + assert(a); + assert(cinfo); + + now_usec = now(clock_boottime_or_monotonic()); + + *cinfo = (struct ifa_cacheinfo) { + .ifa_valid = MIN(usec_sub_unsigned(a->lifetime_valid_usec, now_usec) / USEC_PER_SEC, UINT32_MAX), + .ifa_prefered = MIN(usec_sub_unsigned(a->lifetime_preferred_usec, now_usec) / USEC_PER_SEC, UINT32_MAX), + }; + + return cinfo; +} + +static void address_set_lifetime(Address *a, const struct ifa_cacheinfo *cinfo) { + usec_t now_usec; + + assert(a); + assert(cinfo); + + now_usec = now(clock_boottime_or_monotonic()); + + if (cinfo->ifa_valid == UINT32_MAX) + a->lifetime_valid_usec = USEC_INFINITY; + else + a->lifetime_valid_usec = usec_add(cinfo->ifa_valid * USEC_PER_SEC, now_usec); + + if (cinfo->ifa_prefered == UINT32_MAX) + a->lifetime_preferred_usec = USEC_INFINITY; + else + a->lifetime_preferred_usec = usec_add(cinfo->ifa_prefered * USEC_PER_SEC, now_usec); +} + static uint32_t address_prefix(const Address *a) { assert(a); @@ -553,16 +588,16 @@ int manager_has_address(Manager *manager, int family, const union in_addr_union return false; } -const char* format_lifetime(char *buf, size_t l, uint32_t lifetime) { +const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) { assert(buf); assert(l > 4); - if (lifetime == CACHE_INFO_INFINITY_LIFE_TIME) + if (lifetime_usec == USEC_INFINITY) return "forever"; sprintf(buf, "for "); /* format_timespan() never fails */ - assert_se(format_timespan(buf + 4, l - 4, lifetime * USEC_PER_SEC, USEC_PER_SEC)); + assert_se(format_timespan(buf + 4, l - 4, usec_sub_unsigned(lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC)); return buf; } @@ -586,8 +621,8 @@ static void log_address_debug(const Address *address, const char *str, const Lin log_link_debug(link, "%s %s address (%s): %s%s%s/%u (valid %s, preferred %s), flags: %s", str, strna(network_config_source_to_string(address->source)), strna(state), strnull(addr), peer ? " peer " : "", strempty(peer), address->prefixlen, - FORMAT_LIFETIME(address->cinfo.ifa_valid), - FORMAT_LIFETIME(address->cinfo.ifa_prefered), + FORMAT_LIFETIME(address->lifetime_valid_usec), + FORMAT_LIFETIME(address->lifetime_preferred_usec), strna(flags_str)); } @@ -684,7 +719,7 @@ bool link_address_is_dynamic(const Link *link, const Address *address) { assert(link); assert(address); - if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) + if (address->lifetime_preferred_usec != USEC_INFINITY) return true; /* Even when the address is leased from a DHCP server, networkd assign the address @@ -983,7 +1018,8 @@ static int address_configure( return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m"); } - r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo); + r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, + address_set_cinfo(address, &(struct ifa_cacheinfo) {})); if (r < 0) return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); @@ -1192,6 +1228,7 @@ int request_process_address(Request *req) { int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(address_freep) Address *tmp = NULL; + struct ifa_cacheinfo cinfo; Link *link = NULL; uint16_t type; Address *address = NULL; @@ -1326,7 +1363,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, assert_not_reached(); } - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &tmp->cinfo); + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); return 0; @@ -1340,10 +1377,11 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, /* update flags and etc. */ address->flags = tmp->flags; address->scope = tmp->scope; - address->cinfo = tmp->cinfo; + address_set_lifetime(address, &cinfo); address_enter_configured(address); log_address_debug(address, "Received updated", link); } else { + address_set_lifetime(tmp, &cinfo); address_enter_configured(tmp); log_address_debug(tmp, "Received new", link); @@ -1602,7 +1640,7 @@ int config_parse_lifetime( Network *network = userdata; _cleanup_(address_free_or_set_invalidp) Address *n = NULL; - uint32_t k; + usec_t k; int r; assert(filename); @@ -1622,7 +1660,7 @@ int config_parse_lifetime( /* We accept only "forever", "infinity", empty, or "0". */ if (STR_IN_SET(rvalue, "forever", "infinity", "")) - k = CACHE_INFO_INFINITY_LIFE_TIME; + k = USEC_INFINITY; else if (streq(rvalue, "0")) k = 0; else { @@ -1631,7 +1669,7 @@ int config_parse_lifetime( return 0; } - n->cinfo.ifa_prefered = k; + n->lifetime_preferred_usec = k; TAKE_PTR(n); return 0; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 20e957ccaf..75edfd70dc 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -11,8 +11,7 @@ #include "in-addr-util.h" #include "networkd-link.h" #include "networkd-util.h" - -#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU +#include "time-util.h" typedef struct Address Address; typedef struct Manager Manager; @@ -37,11 +36,15 @@ struct Address { int set_broadcast; struct in_addr broadcast; - struct ifa_cacheinfo cinfo; union in_addr_union in_addr; union in_addr_union in_addr_peer; + /* These are absolute points in time, and NOT timespans/durations. + * Must be specified with clock_boottime_or_monotonic(). */ + usec_t lifetime_valid_usec; + usec_t lifetime_preferred_usec; + bool scope_set:1; bool ip_masquerade_done:1; AddressFamily duplicate_address_detection; @@ -51,7 +54,7 @@ struct Address { address_ready_callback_t callback; }; -const char* format_lifetime(char *buf, size_t l, uint32_t lifetime) _warn_unused_result_; +const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) _warn_unused_result_; /* Note: the lifetime of the compound literal is the immediately surrounding block, * see C11 §6.5.2.5, and * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */ diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index a8d6498423..1ee0052a75 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -841,10 +841,10 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * static int dhcp4_request_address(Link *link, bool announce) { _cleanup_(address_freep) Address *addr = NULL; - uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; struct in_addr address, netmask, server; unsigned prefixlen; Address *existing; + usec_t lifetime_usec; int r; assert(link); @@ -864,10 +864,15 @@ static int dhcp4_request_address(Link *link, bool announce) { return log_link_debug_errno(link, r, "DHCP error: failed to get DHCP server IP address: %m"); if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { - r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); + uint32_t lifetime_sec; + + r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime_sec); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); - } + + lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now(clock_boottime_or_monotonic())); + } else + lifetime_usec = USEC_INFINITY; prefixlen = in4_addr_netmask_to_prefixlen(&netmask); @@ -908,8 +913,8 @@ static int dhcp4_request_address(Link *link, bool announce) { addr->provider.in = server; addr->family = AF_INET; addr->in_addr.in.s_addr = address.s_addr; - addr->cinfo.ifa_prefered = lifetime; - addr->cinfo.ifa_valid = lifetime; + addr->lifetime_preferred_usec = lifetime_usec; + addr->lifetime_valid_usec = lifetime_usec; addr->prefixlen = prefixlen; if (prefixlen <= 30) addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; @@ -1698,7 +1703,6 @@ int config_parse_dhcp_fallback_lease_lifetime( void *userdata) { Network *network = userdata; - uint32_t k; assert(filename); assert(section); @@ -1712,15 +1716,13 @@ int config_parse_dhcp_fallback_lease_lifetime( } /* We accept only "forever" or "infinity". */ - if (STR_IN_SET(rvalue, "forever", "infinity")) - k = CACHE_INFO_INFINITY_LIFE_TIME; - else { + if (!STR_IN_SET(rvalue, "forever", "infinity")) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid LeaseLifetime= value, ignoring: %s", rvalue); return 0; } - network->dhcp_fallback_lease_lifetime = k; + network->dhcp_fallback_lease_lifetime = UINT32_MAX; return 0; } diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index be3238337c..1cd779fe37 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -44,7 +44,7 @@ bool link_dhcp6_pd_is_enabled(Link *link) { } static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { - uint32_t lifetime_preferred, lifetime_valid; + uint32_t lifetime_preferred_sec, lifetime_valid_sec; struct in6_addr pd_prefix; uint8_t pd_prefix_len; @@ -53,7 +53,7 @@ static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { sd_dhcp6_lease_reset_pd_prefix_iter(lease); - return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred, &lifetime_valid) >= 0; + return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred_sec, &lifetime_valid_sec) >= 0; } static void link_remove_dhcp6_pd_prefix(Link *link, const struct in6_addr *prefix) { @@ -288,7 +288,7 @@ static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link return 1; } -static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t timestamp_usec, uint32_t lifetime_sec) { +static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) { _cleanup_(route_freep) Route *route = NULL; Route *existing; int r; @@ -310,7 +310,7 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, use route->dst_prefixlen = 64; route->protocol = RTPROT_DHCP; route->priority = link->network->dhcp6_pd_route_metric; - route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = lifetime_usec; if (route_get(NULL, link, route, &existing) < 0) link->dhcp6_pd_configured = false; @@ -360,15 +360,15 @@ static void log_dhcp6_pd_address(Link *link, const Address *address) { log_link_full(link, log_level, "DHCPv6-PD address %s (valid %s, preferred %s)", strna(buffer), - FORMAT_LIFETIME(address->cinfo.ifa_valid), - FORMAT_LIFETIME(address->cinfo.ifa_prefered)); + FORMAT_LIFETIME(address->lifetime_valid_usec), + FORMAT_LIFETIME(address->lifetime_preferred_usec)); } static int dhcp6_pd_request_address( Link *link, const struct in6_addr *prefix, - uint32_t lifetime_preferred, - uint32_t lifetime_valid) { + usec_t lifetime_preferred_usec, + usec_t lifetime_valid_usec) { _cleanup_set_free_ Set *addresses = NULL; struct in6_addr *a; @@ -397,8 +397,8 @@ static int dhcp6_pd_request_address( address->family = AF_INET6; address->in_addr.in6 = *a; address->prefixlen = 64; - address->cinfo.ifa_prefered = lifetime_preferred; - address->cinfo.ifa_valid = lifetime_valid; + address->lifetime_preferred_usec = lifetime_preferred_usec; + address->lifetime_valid_usec = lifetime_valid_usec; SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address); address->route_metric = link->network->dhcp6_pd_route_metric; @@ -421,9 +421,8 @@ static int dhcp6_pd_request_address( static int dhcp6_pd_assign_prefix( Link *link, const struct in6_addr *prefix, - usec_t timestamp_usec, - uint32_t lifetime_preferred, - uint32_t lifetime_valid) { + usec_t lifetime_preferred_usec, + usec_t lifetime_valid_usec) { int r; @@ -432,16 +431,16 @@ static int dhcp6_pd_assign_prefix( assert(prefix); if (link->network->dhcp6_pd_announce) { - r = radv_add_prefix(link, prefix, 64, lifetime_preferred, lifetime_valid); + r = radv_add_prefix(link, prefix, 64, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) return r; } - r = dhcp6_pd_request_route(link, prefix, timestamp_usec, lifetime_valid); + r = dhcp6_pd_request_route(link, prefix, lifetime_valid_usec); if (r < 0) return r; - r = dhcp6_pd_request_address(link, prefix, lifetime_preferred, lifetime_valid); + r = dhcp6_pd_request_address(link, prefix, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) return r; @@ -529,9 +528,8 @@ static int dhcp6_pd_prefix_distribute( Link *dhcp6_link, const struct in6_addr *pd_prefix, uint8_t pd_prefix_len, - usec_t timestamp_usec, - uint32_t lifetime_preferred, - uint32_t lifetime_valid, + usec_t lifetime_preferred_usec, + usec_t lifetime_valid_usec, bool assign_preferred_subnet_id) { Link *link; @@ -563,7 +561,7 @@ static int dhcp6_pd_prefix_distribute( continue; (void) in6_addr_prefix_to_string(&assigned_prefix, 64, &buf); - r = dhcp6_pd_assign_prefix(link, &assigned_prefix, timestamp_usec, lifetime_preferred, lifetime_valid); + r = dhcp6_pd_assign_prefix(link, &assigned_prefix, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) { log_link_warning_errno(link, r, "Failed to assign/update prefix %s: %m", strna(buf)); if (link == dhcp6_link) @@ -749,7 +747,7 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li return 1; } -static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t timestamp_usec, uint32_t lifetime_sec) { +static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t lifetime_usec) { _cleanup_(route_freep) Route *route = NULL; _cleanup_free_ char *buf = NULL; Route *existing; @@ -778,7 +776,7 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad route->type = RTN_UNREACHABLE; route->protocol = RTPROT_DHCP; route->priority = DHCP_ROUTE_METRIC; - route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = lifetime_usec; if (route_get(link->manager, NULL, route, &existing) < 0) link->dhcp6_configured = false; @@ -852,22 +850,26 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { } for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) { - uint32_t lifetime_preferred, lifetime_valid; + uint32_t lifetime_preferred_sec, lifetime_valid_sec; + usec_t lifetime_preferred_usec, lifetime_valid_usec; struct in6_addr pd_prefix; uint8_t pd_prefix_len; r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len, - &lifetime_preferred, &lifetime_valid); + &lifetime_preferred_sec, &lifetime_valid_sec); if (r < 0) break; + lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); + lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); + r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len); if (r < 0) return r; if (r == 0) continue; - r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, timestamp_usec, lifetime_valid); + r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec); if (r < 0) return r; @@ -899,9 +901,8 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { r = dhcp6_pd_prefix_distribute(dhcp6_link, &pd_prefix, pd_prefix_len, - timestamp_usec, - lifetime_preferred, - lifetime_valid, + lifetime_preferred_usec, + lifetime_valid_usec, true); if (r < 0) return r; @@ -909,9 +910,8 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { r = dhcp6_pd_prefix_distribute(dhcp6_link, &pd_prefix, pd_prefix_len, - timestamp_usec, - lifetime_preferred, - lifetime_valid, + lifetime_preferred_usec, + lifetime_valid_usec, false); if (r < 0) return r; @@ -976,8 +976,8 @@ static void log_dhcp6_address(Link *link, const Address *address) { log_link_warning(link, "DHCPv6 address %s/%u (valid %s, preferred %s) conflicts the address %s/%u%s.", strna(buffer), address->prefixlen, - FORMAT_LIFETIME(address->cinfo.ifa_valid), - FORMAT_LIFETIME(address->cinfo.ifa_prefered), + FORMAT_LIFETIME(address->lifetime_valid_usec), + FORMAT_LIFETIME(address->lifetime_preferred_usec), strna(buffer), existing->prefixlen, by_ndisc ? " assigned by NDisc. Please try to use or update IPv6Token= setting " "to change the address generated by NDISC, or disable UseAutonomousPrefix=" : ""); @@ -986,15 +986,15 @@ static void log_dhcp6_address(Link *link, const Address *address) { simple_log: log_link_full(link, log_level, "DHCPv6 address %s/%u (valid %s, preferred %s)", strna(buffer), address->prefixlen, - FORMAT_LIFETIME(address->cinfo.ifa_valid), - FORMAT_LIFETIME(address->cinfo.ifa_prefered)); + FORMAT_LIFETIME(address->lifetime_valid_usec), + FORMAT_LIFETIME(address->lifetime_preferred_usec)); } static int dhcp6_request_address( Link *link, const struct in6_addr *ip6_addr, - uint32_t lifetime_preferred, - uint32_t lifetime_valid) { + usec_t lifetime_preferred_usec, + usec_t lifetime_valid_usec) { _cleanup_(address_freep) Address *addr = NULL; Address *existing; @@ -1009,8 +1009,8 @@ static int dhcp6_request_address( addr->in_addr.in6 = *ip6_addr; addr->flags = IFA_F_NOPREFIXROUTE; addr->prefixlen = 128; - addr->cinfo.ifa_prefered = lifetime_preferred; - addr->cinfo.ifa_valid = lifetime_valid; + addr->lifetime_preferred_usec = lifetime_preferred_usec; + addr->lifetime_valid_usec = lifetime_valid_usec; log_dhcp6_address(link, addr); @@ -1032,6 +1032,7 @@ static int dhcp6_request_address( } static int dhcp6_address_acquired(Link *link) { + usec_t timestamp_usec; int r; assert(link); @@ -1041,15 +1042,21 @@ static int dhcp6_address_acquired(Link *link) { if (!link->network->dhcp6_use_address) return 0; + r = sd_dhcp6_lease_get_timestamp(link->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get timestamp of DHCPv6 lease: %m"); + for (sd_dhcp6_lease_reset_address_iter(link->dhcp6_lease);;) { - uint32_t lifetime_preferred, lifetime_valid; + uint32_t lifetime_preferred_sec, lifetime_valid_sec; struct in6_addr ip6_addr; - r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr, &lifetime_preferred, &lifetime_valid); + r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr, &lifetime_preferred_sec, &lifetime_valid_sec); if (r < 0) break; - r = dhcp6_request_address(link, &ip6_addr, lifetime_preferred, lifetime_valid); + r = dhcp6_request_address(link, &ip6_addr, + usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec), + usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec)); if (r < 0) return r; } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 9e3da746e3..2bcb25daad 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -382,19 +382,17 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { } static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { - uint32_t lifetime_valid, lifetime_preferred; + uint32_t lifetime_valid_sec, lifetime_preferred_sec; + usec_t lifetime_valid_usec, lifetime_preferred_usec, timestamp_usec; _cleanup_set_free_ Set *addresses = NULL; struct in6_addr prefix, *a; unsigned prefixlen; - usec_t time_now; int r; assert(link); assert(rt); - /* Do not use clock_boottime_or_monotonic() here, as the kernel internally manages cstamp and - * tstamp with jiffies, and it is not increased while the system is suspended. */ - r = sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &time_now); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -415,23 +413,26 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r return 0; } - r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid); + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); - if (lifetime_valid == 0) { + if (lifetime_valid_sec == 0) { log_link_debug(link, "Ignoring prefix as its valid lifetime is zero."); return 0; } - r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred); + r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); /* The preferred lifetime is never greater than the valid lifetime */ - if (lifetime_preferred > lifetime_valid) + if (lifetime_preferred_sec > lifetime_valid_sec) return 0; + lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); + lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); + r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses); if (r < 0) return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m"); @@ -448,8 +449,8 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r address->in_addr.in6 = *a; address->prefixlen = prefixlen; address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; - address->cinfo.ifa_valid = lifetime_valid; - address->cinfo.ifa_prefered = lifetime_preferred; + address->lifetime_valid_usec = lifetime_valid_usec; + address->lifetime_preferred_usec = lifetime_preferred_usec; /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events. @@ -458,9 +459,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r if (r > 0) { /* If the address is already assigned, but not valid anymore, then refuse to * update the address, and it will be removed. */ - if (e->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME && - usec_add(e->cinfo.tstamp / 100 * USEC_PER_SEC, - e->cinfo.ifa_valid * USEC_PER_SEC) < time_now) + if (e->lifetime_valid_usec < timestamp_usec) continue; } diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 73e9bce52a..c3a4ca6a3a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -629,10 +629,11 @@ int radv_add_prefix( Link *link, const struct in6_addr *prefix, uint8_t prefix_len, - uint32_t lifetime_preferred, - uint32_t lifetime_valid) { + usec_t lifetime_preferred_usec, + usec_t lifetime_valid_usec) { _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL; + usec_t now_usec; int r; assert(link); @@ -640,6 +641,8 @@ int radv_add_prefix( if (!link->radv) return 0; + now_usec = now(clock_boottime_or_monotonic()); + r = sd_radv_prefix_new(&p); if (r < 0) return r; @@ -648,11 +651,11 @@ int radv_add_prefix( if (r < 0) return r; - r = sd_radv_prefix_set_preferred_lifetime(p, lifetime_preferred); + r = sd_radv_prefix_set_preferred_lifetime(p, usec_sub_unsigned(lifetime_preferred_usec, now_usec) / USEC_PER_SEC); if (r < 0) return r; - r = sd_radv_prefix_set_valid_lifetime(p, lifetime_valid); + r = sd_radv_prefix_set_valid_lifetime(p, usec_sub_unsigned(lifetime_valid_usec, now_usec) / USEC_PER_SEC); if (r < 0) return r; diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index d51fe323dc..6fd27ef39e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -64,7 +64,7 @@ int link_request_radv_addresses(Link *link); int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, - uint32_t lifetime_preferred, uint32_t lifetime_valid); + usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec); int request_process_radv(Request *req); int link_request_radv(Link *link); diff --git a/src/network/test-networkd-address.c b/src/network/test-networkd-address.c index 7c1d65a433..564c76f848 100644 --- a/src/network/test-networkd-address.c +++ b/src/network/test-networkd-address.c @@ -2,21 +2,26 @@ #include "networkd-address.h" #include "tests.h" +#include "time-util.h" -static void test_FORMAT_LIFETIME_one(uint32_t lifetime, const char *expected) { +static void test_FORMAT_LIFETIME_one(usec_t lifetime, const char *expected) { const char *t = FORMAT_LIFETIME(lifetime); - log_debug("%"PRIu32 " → \"%s\" (expected \"%s\")", lifetime, t, expected); + log_debug(USEC_FMT " → \"%s\" (expected \"%s\")", lifetime, t, expected); assert_se(streq(t, expected)); } static void test_FORMAT_LIFETIME(void) { + usec_t now_usec; + log_info("/* %s */", __func__); - test_FORMAT_LIFETIME_one(0, "for 0"); - test_FORMAT_LIFETIME_one(1, "for 1s"); - test_FORMAT_LIFETIME_one(3 * (USEC_PER_WEEK/USEC_PER_SEC), "for 3w"); - test_FORMAT_LIFETIME_one(CACHE_INFO_INFINITY_LIFE_TIME, "forever"); + now_usec = now(CLOCK_MONOTONIC); + + test_FORMAT_LIFETIME_one(now_usec, "for 0"); + test_FORMAT_LIFETIME_one(usec_add(now_usec, 2 * USEC_PER_SEC - 1), "for 1s"); + test_FORMAT_LIFETIME_one(usec_add(now_usec, 3 * USEC_PER_WEEK + USEC_PER_SEC - 1), "for 3w"); + test_FORMAT_LIFETIME_one(USEC_INFINITY, "forever"); } int main(int argc, char *argv[]) {