ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
netadapt.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file netadapt.h
6 * @brief Network adaptation decisions: TCP window sizing by free RAM + DHCP->static fallback
7 * (PROTOCORE_ENABLE_NETADAPT).
8 *
9 * Two pure decisions a network manager needs on a memory-constrained, sometimes-headless device:
10 *
11 * - `protocore_netadapt_window()` - size the TCP receive window / RX buffer from the free heap, so a device
12 * with RAM to spare uses a bigger window for throughput while a low-memory one shrinks to stay alive.
13 * Keeps a reserve untouched and clamps to a sane [min, max].
14 *
15 * - `protocore_netadapt_dhcp_fallback()` - decide when to stop waiting on DHCP and configure a static IP, so
16 * a node on a network with no DHCP server still comes up. Triggers once the elapsed wait exceeds the
17 * timeout or the retry budget is spent.
18 *
19 * Pure, zero heap, no stdlib, host-testable; the app applies the results (lwIP window / netif config).
20 */
21
22#ifndef PROTOCORE_NETADAPT_H
23#define PROTOCORE_NETADAPT_H
24
25#include "protocore_config.h" // the entry point: protocore_types.h for the widths
26
27#if PROTOCORE_ENABLE_NETADAPT
28
30
31// This module holds nothing between calls, so it carves no borrow and states none. An entry
32// takes one all the same, and never reads it, so every namespace in the tree is invoked the
33// same way.
34
35/** @brief What window takes: free_heap, reserve, min_win, max_win. */
36typedef struct
37{
38 uint32_t free_heap; ///< current free heap (bytes)
39 uint32_t reserve; ///< heap to leave untouched for everything else (bytes)
40 uint32_t min_win; ///< floor for the returned window (always usable)
41 uint32_t max_win; ///< ceiling for the returned window
42} NetadaptWindowArgs;
43
44/** @brief What dhcp_fallback takes: elapsed_ms, attempts, timeout_ms, ... */
45typedef struct
46{
47 uint32_t elapsed_ms; ///< time since the DHCP attempt started (ms)
48 uint32_t attempts; ///< DHCP attempts made so far
49 uint32_t timeout_ms; ///< per-run wait budget before falling back (ms)
50 uint32_t max_attempts; ///< attempt budget before falling back (0 = ignore the attempt count)
51} NetadaptDhcpFallbackArgs;
52
53/**
54 * @brief Network adaptation decisions: TCP window sizing by free RAM + DHCP->static fallback ...
55 *
56 * A caller sets the members a call takes, invokes it through ::Netadapt with the bytes it runs
57 * out of, and reads the outcome off the same handle.
58 *
59 * Netadapt.window_args.free_heap = ...;
60 * Netadapt.window_args.reserve = ...;
61 * Netadapt.window_args.min_win = ...;
62 * Netadapt.window_args.max_win = ...;
63 * Netadapt.window(work);
64 * // Netadapt.u32 is what the call reports
65 *
66 * @var NetadaptNs::window_args what window takes: free_heap, reserve, min_win, max_win
67 * @var NetadaptNs::dhcp_fallback_args what dhcp_fallback takes: elapsed_ms, attempts, timeout_ms,
68 * @var NetadaptNs::ok true once the elapsed wait exceeds timeout_ms, or (when ...
69 * @var NetadaptNs::u32 a window in [min_win, max_win]: min_win if the heap at/below the ...
70 * @var NetadaptNs::window recommend a TCP receive window / RX buffer size (bytes) from the ...
71 * @var NetadaptNs::dhcp_fallback should we stop waiting on DHCP and switch to the configured static ...
72 *
73 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
74 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
75 * a caller drives every namespace the same way.
76 */
77typedef struct
78{
79 NetadaptWindowArgs window_args;
80 NetadaptDhcpFallbackArgs dhcp_fallback_args;
81 proto_bool ok;
82 uint32_t u32;
83} NetadaptVars;
84
85/** @brief The operands and the outcome. */
86extern NetadaptVars NetadaptV;
87
88/** @brief The entries. */
89typedef struct
90{
91 void (*const window)(uint8_t *work);
92 void (*const dhcp_fallback)(uint8_t *work);
93} NetadaptNs;
94
95// What the table binds, defined once in the .c and taking one parameter each: everything
96// else an entry needs is an operand in NetadaptV or a region of the borrow at a fixed offset.
97void protocore_netadapt_window(uint8_t *work);
98void protocore_netadapt_dhcp_fallback(uint8_t *work);
99
100// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
101// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
102// `Netadapt.window(work)` resolves to a named function and becomes a DIRECT call. An extern table
103// leaves the call indirect and the symbol live at every level, -O2 -flto included.
104static const NetadaptNs Netadapt __attribute__((unused)) = {
105 .window = protocore_netadapt_window,
106 .dhcp_fallback = protocore_netadapt_dhcp_fallback,
107};
108
110
111#endif // PROTOCORE_ENABLE_NETADAPT
112
113#endif // PROTOCORE_NETADAPT_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97