Skip to content

Commit

Permalink
net: introduce scalar nanosecond time representation
Browse files Browse the repository at this point in the history
Introduces a well-defined intermediate concept of syntonized scalar
nanosecond resolution time with overflow protection above low-level
counters/cycles/ticks and below higher level time abstractions
(timescales, calenders, etc.).

The rationale of this type has been extensively documented and
contrasted to already existing time representations to ensure that it
fills a well defined gap without overlap.

This change prepares for later changes in this change set that will
unify the usage of time across the network subsystem (RX/TX timestamps,
timed TX, CSL, scheduled reception windows, (g)PTP integration, etc.).

The type is EXPERIMENTAL and named net_time_t while it is not used in a
larger clock subsystems, the details of which are still being discussed
(see zephyrproject-rtos#60400 for details).

See
zephyrproject-rtos#19030 (comment)
for its embedding in a larger clock subsystem architecture relevant to
the network stack, IEEE 802.15.4 and the POSIX roadmap.

Signed-off-by: Florian Grandel <[email protected]>
  • Loading branch information
fg-cfh authored and kunoh committed Aug 7, 2023
1 parent 16a23f7 commit 1dd7262
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions include/zephyr/net/net_time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2023 Zephyr Project
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief Representation of nanosecond resolution elapsed time and timestamps in
* the network stack.
*
* Inspired by
* https://github.com/torvalds/linux/blob/master/include/linux/ktime.h and
* https://github.com/torvalds/linux/blob/master/[tools/]include/linux/time64.h
*/

#ifndef ZEPHYR_INCLUDE_NET_NET_TIME_H_
#define ZEPHYR_INCLUDE_NET_NET_TIME_H_

/* Include required for NSEC_PER_* constants. */
#include "zephyr/sys_clock.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Any occurrence of net_time_t specifies a concept of nanosecond
* resolution scalar time span, future (positive) or past (negative) relative
* time or absolute timestamp referred to some local network uptime reference
* clock that does not wrap during uptime and is - in a certain, well-defined
* sense - common to all local network interfaces, sometimes even to remote
* interfaces on the same network.
*
* This type is EXPERIMENTAL. Usage is currently restricted to representation of
* time within the network subsystem.
*
* @details Timed network protocols (PTP, TDMA, ...) usually require several
* local or remote interfaces to share a common notion of elapsed time within
* well-defined tolerances. Network uptime therefore differs from time
* represented by a single hardware counter peripheral in that it will need to
* be represented in several distinct hardware peripherals with different
* frequencies, accuracy and precision. To co-operate, these hardware counters
* will have to be "syntonized" or "disciplined" (i.e. frequency and phase
* locked) with respect to a common local or remote network reference time
* signal. Be aware that while syntonized clocks share the same frequency and
* phase, they do not usually share the same epoch (zero-point).
*
* This also explains why network time, if represented as a cycle value of some
* specific hardware counter, will never be "precise" but only can be "good
* enough" with respect to the tolerances (resolution, drift, jitter) required
* by a given network protocol. All counter peripherals involved in a timed
* network protocol must comply with these tolerances.
*
* Please use specific cycle/tick counter values rather than net_time_t whenever
* possible especially when referring to the kernel system clock or values of
* any single counter peripheral.
*
* net_time_t cannot represent general clocks referred to an arbitrary epoch as
* it only covers roughly +/- ~290 years. It also cannot be used to represent
* time according to a more complex timescale (e.g. including leap seconds, time
* adjustments, complex calendars or time zones). In these cases you may use
* @ref timespec (C11, POSIX.1-2001), @ref timeval (POSIX.1-2001) or broken down
* time as in @ref tm (C90). The advantage of net_time_t over these structured
* time representations is lower memory footprint, faster and simpler scalar
* arithmetics and easier conversion from/to low-level hardware counter values.
* Also net_time_t can be used in the network stack as well as in applications
* while POSIX concepts cannot. Converting net_time_t from/to structured time
* representations is possible in a limited way but - except for @ref timespec -
* requires concepts that must be implemented by higher-level APIs. Utility
* functions converting from/to @ref timespec will be provided as part of the
* net_time_t API as and when needed.
*
* If you want to represent more coarse grained scalar time in network
* applications, use @ref time_t (C99, POSIX.1-2001) which is specified to
* represent seconds or @ref suseconds_t (POSIX.1-2001) for microsecond
* resolution. Kernel @ref k_ticks_t and cycles (both specific to Zephyr) have
* an unspecified resolution but are useful to represent kernel timer values and
* implement high resolution spinning.
*
* If you need even finer grained time resolution, you may want to look at
* (g)PTP concepts, see @ref net_ptp_extended_time.
*
* The reason why we don't use int64_t directly to represent scalar nanosecond
* resolution times in the network stack is that it has been shown in the past
* that fields using generic type will often not be used correctly (e.g. with
* the wrong resolution or to represent underspecified concepts of time with
* unclear syntonization semantics).
*
* Any API that exposes or consumes net_time_t values SHALL ensure that it
* maintains the specified contract including all protocol specific tolerances
* and therefore clients can rely on common semantics of this type. This makes
* times coming from different hardware peripherals and even from different
* network nodes comparable within well-defined limits and therefore net_time_t
* is the ideal intermediate building block for timed network protocols.
*/
typedef int64_t net_time_t;

/** The largest positive time value that can be represented by net_time_t */
#define NET_TIME_MAX INT64_MAX

/** The smallest negative time value that can be represented by net_time_t */
#define NET_TIME_MIN INT64_MIN

/** The largest positive number of seconds that can be safely represented by net_time_t */
#define NET_TIME_SEC_MAX (NET_TIME_MAX / NSEC_PER_SEC)

/** The smallest negative number of seconds that can be safely represented by net_time_t */
#define NET_TIME_SEC_MIN (NET_TIME_MIN / NSEC_PER_SEC)

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_NET_NET_TIME_H_ */

0 comments on commit 1dd7262

Please sign in to comment.