Network Timeout
Overview
Zephyr’s network infrastructure mostly uses the millisecond-resolution uptime clock to track timeouts, with both deadlines and durations measured with 32-bit unsigned values. The 32-bit value rolls over at 49 days 17 hours 2 minutes 47.296 seconds.
Timeout processing is often affected by latency, so that the time at which the
timeout is checked may be some time after it should have expired. Handling
this correctly without arbitrary expectations of maximum latency requires that
the maximum delay that can be directly represented be a 31-bit non-negative
number (INT32_MAX
), which overflows at 24 days 20 hours 31 minutes 23.648
seconds.
Most network timeouts are shorter than the delay rollover, but a few protocols allow for delays that are represented as unsigned 32-bit values counting seconds, which corresponds to a 42-bit millisecond count.
The net_timeout API provides a generic timeout mechanism to correctly track the remaining time for these extended-duration timeouts.
Use
The simplest use of this API is:
Configure a network timeout using
net_timeout_set()
.Use
net_timeout_evaluate()
to determine how long it is until the timeout occurs. Schedule a timeout to occur after this delay.When the timeout callback is invoked, use
net_timeout_evaluate()
again to determine whether the timeout has completed, or whether there is additional time remaining. If the latter, reschedule the callback.While the timeout is running, use
net_timeout_remaining()
to get the number of seconds until the timeout expires. This may be used to explicitly update the timeout, which should be done by canceling any pending callback and restarting from step 1 with the new timeout.
The net_timeout
contains a sys_snode_t
that allows multiple
timeout instances to be aggregated to share a single kernel timer element.
The application must use net_timeout_evaluate()
on all instances to
determine the next timeout event to occur.
net_timeout_deadline()
may be used to reconstruct the full-precision
deadline of the timeout. This exists primarily for testing but may have use
in some applications, as it does allow a millisecond-resolution calculation of
remaining time.
API Reference
- group net_timeout
Network long timeout primitives and helpers.
Defines
-
NET_TIMEOUT_MAX_VALUE
Divisor used to support ms resolution timeouts.
Because delays are processed in work queues which are not invoked synchronously with clock changes we need to be able to detect timeouts after they occur, which requires comparing “deadline” to “now” with enough “slop” to handle any observable latency due to “now” advancing past “deadline”.
The simplest solution is to use the native conversion of the well-defined 32-bit unsigned difference to a 32-bit signed difference, which caps the maximum delay at INT32_MAX. This is compatible with the standard mechanism for detecting completion of deadlines that do not overflow their representation.
Functions
-
void net_timeout_set(struct net_timeout *timeout, uint32_t lifetime, uint32_t now)
Configure a network timeout structure.
- Parameters:
timeout – a pointer to the timeout state.
lifetime – the duration of the timeout in seconds.
now – the time at which the timeout started counting down, in milliseconds. This is generally a captured value of k_uptime_get_32().
-
int64_t net_timeout_deadline(const struct net_timeout *timeout, int64_t now)
Return the 64-bit system time at which the timeout will complete.
Note
Correct behavior requires invocation of net_timeout_evaluate() at its specified intervals.
- Parameters:
timeout – state a pointer to the timeout state, initialized by net_timeout_set() and maintained by net_timeout_evaluate().
now – the full-precision value of k_uptime_get() relative to which the deadline will be calculated.
- Returns:
the value of k_uptime_get() at which the timeout will expire.
-
uint32_t net_timeout_remaining(const struct net_timeout *timeout, uint32_t now)
Calculate the remaining time to the timeout in whole seconds.
Note
This function rounds the remaining time down, i.e. if the timeout will occur in 3500 milliseconds the value 3 will be returned.
Note
Correct behavior requires invocation of net_timeout_evaluate() at its specified intervals.
- Parameters:
timeout – a pointer to the timeout state
now – the time relative to which the estimate of remaining time should be calculated. This should be recently captured value from k_uptime_get_32().
- Return values:
0 – if the timeout has completed.
positive – the remaining duration of the timeout, in seconds.
-
uint32_t net_timeout_evaluate(struct net_timeout *timeout, uint32_t now)
Update state to reflect elapsed time and get new delay.
This function must be invoked periodically to (1) apply the effect of elapsed time on what remains of a total delay that exceeded the maximum representable delay, and (2) determine that either the timeout has completed or that the infrastructure must wait a certain period before checking again for completion.
- Parameters:
timeout – a pointer to the timeout state
now – the time relative to which the estimate of remaining time should be calculated. This should be recently captured value from k_uptime_get_32().
- Return values:
0 – if the timeout has completed
positive – the maximum delay until the state of this timeout should be re-evaluated, in milliseconds.
-
struct net_timeout
- #include <net_timeout.h>
Generic struct for handling network timeouts.
Except for the linking node, all access to state from these objects must go through the defined API.
Public Members
-
sys_snode_t node
Used to link multiple timeouts that share a common timer infrastructure.
For examples a set of related timers may use a single delayed work structure, which is always scheduled at the shortest time to a timeout event.
-
uint32_t timer_start
Time at which the timer was last set.
This usually corresponds to the low 32 bits of k_uptime_get().
-
uint32_t timer_timeout
Portion of remaining timeout that does not exceed NET_TIMEOUT_MAX_VALUE.
This value is updated in parallel with timer_start and wrap_counter by net_timeout_evaluate().
-
uint32_t wrap_counter
Timer wrap count.
This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that have yet to pass. It is also updated along with timer_start and wrap_counter by net_timeout_evaluate().
-
sys_snode_t node
-
NET_TIMEOUT_MAX_VALUE