*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,
};
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);
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;
}
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));
}
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
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");
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;
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;
/* 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);
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
- uint32_t k;
+ usec_t k;
int r;
assert(filename);
/* 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 {
return 0;
}
- n->cinfo.ifa_prefered = k;
+ n->lifetime_preferred_usec = k;
TAKE_PTR(n);
return 0;
#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;
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;
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 */
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);
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);
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;
void *userdata) {
Network *network = userdata;
- uint32_t k;
assert(filename);
assert(section);
}
/* 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;
}
}
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;
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) {
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;
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;
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;
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;
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;
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;
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;
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)
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;
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;
}
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;
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;
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;
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=" : "");
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;
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);
}
static int dhcp6_address_acquired(Link *link) {
+ usec_t timestamp_usec;
int r;
assert(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;
}
}
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");
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");
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.
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;
}
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);
if (!link->radv)
return 0;
+ now_usec = now(clock_boottime_or_monotonic());
+
r = sd_radv_prefix_new(&p);
if (r < 0)
return r;
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;
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);
#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[]) {