DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
link_manager.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file link_manager.h
6 * @brief Multi-interface egress selection + graceful escalation/failover (DETWS_ENABLE_LINK_MANAGER).
7 *
8 * Once a device has more than one network interface (a wired Ethernet PHY brought up alongside WiFi STA,
9 * plus maybe a softAP), something has to decide which one carries traffic and when to switch: escalate to
10 * the wired link when it comes up (usually faster / more reliable), and fail over to WiFi when it drops.
11 * The stack owns the routes and `det_net_egress()` reports the live one; this is the *policy* that drives
12 * it - a small table of interfaces (each a kind + priority + up/down) with a deterministic "best link
13 * that is up" selection, plus change detection so the app only reconfigures on an actual transition.
14 *
15 * Pure, no heap, no stdlib, host-testable. The real PHY bring-up (esp_eth) and the netif reconfigure are
16 * the app's; this just says which interface should be active.
17 */
18
19#ifndef DETERMINISTICESPASYNCWEBSERVER_LINK_MANAGER_H
20#define DETERMINISTICESPASYNCWEBSERVER_LINK_MANAGER_H
21
22#include "ServerConfig.h"
23#include <stddef.h>
24#include <stdint.h>
25
26#if DETWS_ENABLE_LINK_MANAGER
27
28/** @brief Interface kind (informational; selection is by priority). Stored in a uint8_t field and
29 * compared, so integer constants in a namespacing struct - cast-free. */
30struct LinkKind
31{
32 static constexpr uint8_t LINK_KIND_ETH = 0; ///< wired Ethernet PHY.
33 static constexpr uint8_t LINK_KIND_WIFI_STA = 1; ///< WiFi station.
34 static constexpr uint8_t LINK_KIND_WIFI_AP = 2; ///< WiFi softAP.
35 static constexpr uint8_t LINK_KIND_OTHER = 3;
36};
37
38/** @brief One managed interface. */
39struct LinkIface
40{
41 uint8_t kind; ///< LINK_KIND_*.
42 uint8_t priority; ///< higher wins when up (ties break to the lower index).
43 bool up; ///< link currently up.
44};
45
46/** @brief The link-manager state over a caller-owned interface table. */
47struct LinkManager
48{
49 LinkIface *ifaces;
50 size_t n;
51 int active; ///< index of the active egress, or -1 if none is up.
52};
53
54/** @brief Initialize over caller storage and compute the initial active egress. */
55void detws_link_init(LinkManager *m, LinkIface *ifaces, size_t n);
56
57/** @brief Best interface that is up (highest priority, lower index breaks ties). @return index or -1. */
58int detws_link_select(const LinkManager *m);
59
60/** @brief The current active egress index (-1 if none). */
61int detws_link_active(const LinkManager *m);
62
63/**
64 * @brief Set an interface's up/down state and recompute the active egress.
65 * @param from (may be null) the previous active index.
66 * @param to (may be null) the new active index.
67 * @return true if the active egress changed (escalation or failover happened).
68 */
69bool detws_link_set(LinkManager *m, size_t idx, bool up, int *from, int *to);
70
71#endif // DETWS_ENABLE_LINK_MANAGER
72#endif // DETERMINISTICESPASYNCWEBSERVER_LINK_MANAGER_H
User-facing configuration for DeterministicESPAsyncWebServer.