1 /*
2  * Copyright (c) 2023 Zephyr Project
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Representation of nanosecond resolution elapsed time and timestamps in
10  * the network stack.
11  *
12  * Inspired by
13  * https://github.com/torvalds/linux/blob/master/include/linux/ktime.h and
14  * https://github.com/torvalds/linux/blob/master/[tools/]include/linux/time64.h
15  *
16  * @defgroup net_time Network time representation.
17  * @since 3.5
18  * @version 0.1.0
19  * @ingroup networking
20  * @{
21  */
22 
23 #ifndef ZEPHYR_INCLUDE_NET_NET_TIME_H_
24 #define ZEPHYR_INCLUDE_NET_NET_TIME_H_
25 
26 /* Include required for NSEC_PER_* constants. */
27 #include <zephyr/sys_clock.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /**
34  * @brief Any occurrence of net_time_t specifies a concept of nanosecond
35  * resolution scalar time span, future (positive) or past (negative) relative
36  * time or absolute timestamp referred to some local network uptime reference
37  * clock that does not wrap during uptime and is - in a certain, well-defined
38  * sense - common to all local network interfaces, sometimes even to remote
39  * interfaces on the same network.
40  *
41  * This type is EXPERIMENTAL. Usage is currently restricted to representation of
42  * time within the network subsystem.
43  *
44  * @details Timed network protocols (PTP, TDMA, ...) usually require several
45  * local or remote interfaces to share a common notion of elapsed time within
46  * well-defined tolerances. Network uptime therefore differs from time
47  * represented by a single hardware counter peripheral in that it will need to
48  * be represented in several distinct hardware peripherals with different
49  * frequencies, accuracy and precision. To co-operate, these hardware counters
50  * will have to be "syntonized" or "disciplined" (i.e. frequency and phase
51  * locked) with respect to a common local or remote network reference time
52  * signal. Be aware that while syntonized clocks share the same frequency and
53  * phase, they do not usually share the same epoch (zero-point).
54  *
55  * This also explains why network time, if represented as a cycle value of some
56  * specific hardware counter, will never be "precise" but only can be "good
57  * enough" with respect to the tolerances (resolution, drift, jitter) required
58  * by a given network protocol. All counter peripherals involved in a timed
59  * network protocol must comply with these tolerances.
60  *
61  * Please use specific cycle/tick counter values rather than net_time_t whenever
62  * possible especially when referring to the kernel system clock or values of
63  * any single counter peripheral.
64  *
65  * net_time_t cannot represent general clocks referred to an arbitrary epoch as
66  * it only covers roughly +/- ~290 years. It also cannot be used to represent
67  * time according to a more complex timescale (e.g. including leap seconds, time
68  * adjustments, complex calendars or time zones). In these cases you may use
69  * @ref timespec (C11, POSIX.1-2001), @ref timeval (POSIX.1-2001) or broken down
70  * time as in @ref tm (C90). The advantage of net_time_t over these structured
71  * time representations is lower memory footprint, faster and simpler scalar
72  * arithmetic and easier conversion from/to low-level hardware counter values.
73  * Also net_time_t can be used in the network stack as well as in applications
74  * while POSIX concepts cannot. Converting net_time_t from/to structured time
75  * representations is possible in a limited way but - except for @ref timespec -
76  * requires concepts that must be implemented by higher-level APIs. Utility
77  * functions converting from/to @ref timespec will be provided as part of the
78  * net_time_t API as and when needed.
79  *
80  * If you want to represent more coarse grained scalar time in network
81  * applications, use @ref time_t (C99, POSIX.1-2001) which is specified to
82  * represent seconds or @ref suseconds_t (POSIX.1-2001) for microsecond
83  * resolution. Kernel @ref k_ticks_t and cycles (both specific to Zephyr) have
84  * an unspecified resolution but are useful to represent kernel timer values and
85  * implement high resolution spinning.
86  *
87  * If you need even finer grained time resolution, you may want to look at
88  * (g)PTP concepts, see @ref net_ptp_extended_time.
89  *
90  * The reason why we don't use int64_t directly to represent scalar nanosecond
91  * resolution times in the network stack is that it has been shown in the past
92  * that fields using generic type will often not be used correctly (e.g. with
93  * the wrong resolution or to represent underspecified concepts of time with
94  * unclear syntonization semantics).
95  *
96  * Any API that exposes or consumes net_time_t values SHALL ensure that it
97  * maintains the specified contract including all protocol specific tolerances
98  * and therefore clients can rely on common semantics of this type. This makes
99  * times coming from different hardware peripherals and even from different
100  * network nodes comparable within well-defined limits and therefore net_time_t
101  * is the ideal intermediate building block for timed network protocols.
102  */
103 typedef int64_t net_time_t;
104 
105 /** The largest positive time value that can be represented by net_time_t */
106 #define NET_TIME_MAX INT64_MAX
107 
108 /** The smallest negative time value that can be represented by net_time_t */
109 #define NET_TIME_MIN INT64_MIN
110 
111 /** The largest positive number of seconds that can be safely represented by net_time_t */
112 #define NET_TIME_SEC_MAX (NET_TIME_MAX / NSEC_PER_SEC)
113 
114 /** The smallest negative number of seconds that can be safely represented by net_time_t */
115 #define NET_TIME_SEC_MIN (NET_TIME_MIN / NSEC_PER_SEC)
116 
117 #ifdef __cplusplus
118 }
119 #endif
120 
121 /**
122  * @}
123  */
124 
125 #endif /* ZEPHYR_INCLUDE_NET_NET_TIME_H_ */
126