From f060da45d53c7c7e05b1af4607a521531f39de6a Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 16 Mar 2022 03:25:30 +0100 Subject: [PATCH] [CORE] time: Add APIs to manage NTP 32-bit timestamps (#1439) These will be further needed in PFCP in the future, as well as in other Diameter based interfaces (such as Gy). Let's put all implementation details in APIs so that devs don't need to care about those details every time. --- lib/core/ogs-time.c | 34 ++++++++++++++++++++++++++++++++++ lib/core/ogs-time.h | 5 +++++ lib/pfcp/context.c | 17 +---------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/lib/core/ogs-time.c b/lib/core/ogs-time.c index d6e8b35e3..bb94e6a53 100644 --- a/lib/core/ogs-time.c +++ b/lib/core/ogs-time.c @@ -167,6 +167,40 @@ int ogs_time_from_gmt(ogs_time_t *t, struct tm *tm, int tm_usec) return status; } +/* RFC 5905 A.1.1, A.4 + * PFCP entity uses NTP timestamp(1900), but Open5GS uses UNIX(1970). + * + * One is the offset between the two epochs. + * Unix uses an epoch located at 1/1/1970-00:00h (UTC) and + * NTP uses 1/1/1900-00:00h. This leads to an offset equivalent + * to 70 years in seconds (there are 17 leap years + * between the two dates so the offset is + * + * (70*365 + 17)*86400 = 2208988800 + * + * to be substracted from NTP time to get Unix struct timeval. + */ +uint32_t ogs_time_ntp32_now(void) +{ + int rc; + struct timeval tv; + + rc = ogs_gettimeofday(&tv); + ogs_assert(rc == 0); + + return ogs_time_to_ntp32(tv.tv_sec * OGS_USEC_PER_SEC + tv.tv_usec); +} +ogs_time_t ogs_time_from_ntp32(uint32_t ntp_timestamp) +{ + if (ntp_timestamp < OGS_1970_1900_SEC_DIFF) + return 0; + return (ntp_timestamp - OGS_1970_1900_SEC_DIFF) * OGS_USEC_PER_SEC; +} +uint32_t ogs_time_to_ntp32(ogs_time_t time) +{ + return (time / OGS_USEC_PER_SEC) + OGS_1970_1900_SEC_DIFF; +} + int ogs_timezone(void) { #if defined(_WIN32) diff --git a/lib/core/ogs-time.h b/lib/core/ogs-time.h index 033ebe9f2..0257f1966 100644 --- a/lib/core/ogs-time.h +++ b/lib/core/ogs-time.h @@ -99,6 +99,11 @@ ogs_time_t ogs_time_now(void); /* This returns GMT */ int ogs_time_from_lt(ogs_time_t *t, struct tm *tm, int tm_usec); int ogs_time_from_gmt(ogs_time_t *t, struct tm *tm, int tm_usec); +#define OGS_1970_1900_SEC_DIFF 2208988800UL /* 1970 - 1900 in seconds */ +uint32_t ogs_time_ntp32_now(void); /* This returns NTP timestamp (1900) */ +ogs_time_t ogs_time_from_ntp32(uint32_t ntp_timestamp); +uint32_t ogs_time_to_ntp32(ogs_time_t time); + /** @return number of microseconds since an arbitrary point */ ogs_time_t ogs_get_monotonic_time(void); /** @return the GMT offset in seconds */ diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 661f1d28e..66b88bc24 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -39,27 +39,12 @@ static OGS_POOL(ogs_pfcp_rule_pool, ogs_pfcp_rule_t); void ogs_pfcp_context_init(void) { - struct timeval tv; ogs_assert(context_initialized == 0); /* Initialize SMF context */ memset(&self, 0, sizeof(ogs_pfcp_context_t)); - /* - * PFCP entity uses NTP timestamp(1900), but Open5GS uses UNIX(1970). - * - * One is the offset between the two epochs. - * Unix uses an epoch located at 1/1/1970-00:00h (UTC) and - * NTP uses 1/1/1900-00:00h. This leads to an offset equivalent - * to 70 years in seconds (there are 17 leap years - * between the two dates so the offset is - * - * (70*365 + 17)*86400 = 2208988800 - * - * to be substracted from NTP time to get Unix struct timeval. - */ - ogs_gettimeofday(&tv); - self.pfcp_started = tv.tv_sec + 2208988800; + self.pfcp_started = ogs_time_ntp32_now(); ogs_log_install_domain(&__ogs_pfcp_domain, "pfcp", ogs_core()->log.level);