From: Yu Watanabe Date: Wed, 6 Sep 2023 18:13:39 +0000 (+0900) Subject: libsystemd-network: introduce several helper functions to handle time values X-Git-Tag: v255-rc1~479^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ca515c961b4bcc3e3f703fa6ccd308d755fc7edf;p=thirdparty%2Fsystemd.git libsystemd-network: introduce several helper functions to handle time values These will be used in later commits. --- diff --git a/src/libsystemd-network/network-common.c b/src/libsystemd-network/network-common.c index b8b4ecdaae4..be77d7e0a6e 100644 --- a/src/libsystemd-network/network-common.c +++ b/src/libsystemd-network/network-common.c @@ -2,6 +2,7 @@ #include "format-util.h" #include "network-common.h" +#include "unaligned.h" int get_ifname(int ifindex, char **ifname) { assert(ifname); @@ -13,3 +14,82 @@ int get_ifname(int ifindex, char **ifname) { return format_ifname_alloc(ifindex, ifname); } + +usec_t unaligned_be32_sec_to_usec(const void *p, bool max_as_infinity) { + uint32_t s = unaligned_read_be32(ASSERT_PTR(p)); + + if (s == UINT32_MAX && max_as_infinity) + return USEC_INFINITY; + + return s * USEC_PER_SEC; +} + +usec_t be32_sec_to_usec(be32_t t, bool max_as_infinity) { + uint32_t s = be32toh(t); + + if (s == UINT32_MAX && max_as_infinity) + return USEC_INFINITY; + + return s * USEC_PER_SEC; +} + +usec_t be32_msec_to_usec(be32_t t, bool max_as_infinity) { + uint32_t s = be32toh(t); + + if (s == UINT32_MAX && max_as_infinity) + return USEC_INFINITY; + + return s * USEC_PER_MSEC; +} + +usec_t be16_sec_to_usec(be16_t t, bool max_as_infinity) { + uint16_t s = be16toh(t); + + if (s == UINT16_MAX && max_as_infinity) + return USEC_INFINITY; + + return s * USEC_PER_SEC; +} + +be32_t usec_to_be32_sec(usec_t t) { + if (t == USEC_INFINITY) + /* Some settings, e.g. a lifetime of an address, UINT32_MAX is handled as infinity. so let's + * map USEC_INFINITY to UINT32_MAX. */ + return htobe32(UINT32_MAX); + + if (t >= (UINT32_MAX - 1) * USEC_PER_SEC) + /* Finite but too large. Let's use the largest (or off-by-one from the largest) finite value. */ + return htobe32(UINT32_MAX - 1); + + return htobe32((uint32_t) DIV_ROUND_UP(t, USEC_PER_SEC)); +} + +be32_t usec_to_be32_msec(usec_t t) { + if (t == USEC_INFINITY) + return htobe32(UINT32_MAX); + + if (t >= (UINT32_MAX - 1) * USEC_PER_MSEC) + return htobe32(UINT32_MAX - 1); + + return htobe32((uint32_t) DIV_ROUND_UP(t, USEC_PER_MSEC)); +} + +be16_t usec_to_be16_sec(usec_t t) { + if (t == USEC_INFINITY) + return htobe16(UINT16_MAX); + + if (t >= (UINT16_MAX - 1) * USEC_PER_SEC) + return htobe16(UINT16_MAX - 1); + + return htobe16((uint16_t) DIV_ROUND_UP(t, USEC_PER_SEC)); +} + +usec_t time_span_to_stamp(usec_t span, usec_t base) { + /* Typically, 0 lifetime (timespan) indicates the corresponding configuration (address or so) must be + * dropped. So, when the timespan is zero, here we return 0 rather than 'base'. This makes the caller + * easily understand that the configuration needs to be dropped immediately. */ + if (span == 0) + return 0; + + return usec_add(base, span); +} diff --git a/src/libsystemd-network/network-common.h b/src/libsystemd-network/network-common.h index 2b0e3b56076..cf3d1e01304 100644 --- a/src/libsystemd-network/network-common.h +++ b/src/libsystemd-network/network-common.h @@ -2,6 +2,8 @@ #pragma once #include "log-link.h" +#include "sparse-endian.h" +#include "time-util.h" #define log_interface_prefix_full_errno_zerook(prefix, type, val, error, fmt, ...) \ ({ \ @@ -28,3 +30,12 @@ }) int get_ifname(int ifindex, char **ifname); + +usec_t unaligned_be32_sec_to_usec(const void *p, bool max_as_infinity); +usec_t be32_sec_to_usec(be32_t t, bool max_as_infinity); +usec_t be32_msec_to_usec(be32_t t, bool max_as_infinity); +usec_t be16_sec_to_usec(be16_t t, bool max_as_infinity); +be32_t usec_to_be32_sec(usec_t t); +be32_t usec_to_be32_msec(usec_t t); +be16_t usec_to_be16_sec(usec_t t); +usec_t time_span_to_stamp(usec_t span, usec_t base); diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index a35311efb99..1226781637e 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -126,18 +126,6 @@ static bool router_lifetime_is_valid(usec_t lifetime_usec) { lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC); } -static be32_t usec_to_be32_sec(usec_t usec) { - if (usec == USEC_INFINITY) - /* UINT32_MAX is handled as infinity. */ - return htobe32(UINT32_MAX); - - if (usec >= UINT32_MAX * USEC_PER_SEC) - /* Finite but too large. Let's use the largest finite value. */ - return htobe32(UINT32_MAX - 1); - - return htobe32(usec / USEC_PER_SEC); -} - static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) { struct sockaddr_in6 dst_addr = { .sin6_family = AF_INET6,