From d33dc266b3b545b5917c592fb07e0d540b9f5238 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 12 Feb 2026 18:39:59 +0000 Subject: [PATCH] AP_Networking: fix boot loop when backend is null but switch hub is active On boards like ARKV6X (ChibiOS + HAL_USE_MAC), the switch architecture enables AP_NETWORKING_BACKEND_SWITCH with Ethernet switchport, but no backend (PPP/SITL) gets created. This causes null pointer dereferences: 1. announce_address_changes() unconditionally dereferences backend->activeSettings 2. update() calls backend->update() when is_healthy() returns true via hub Also fix two architectural issues: - Enable SWITCHPORT_LWIP for ChibiOS+Ethernet boards (not just gateway clients), so the IP stack works when the old ChibiOS backend is replaced by the switch architecture - Wire get_ip_active/get_netmask_active/get_gateway_active to fall back to the lwIP switchport when backend is null - Call hub->update() from AP_Networking::update() so switch ports (including lwIP) get their periodic update calls Co-authored-by: jschall --- libraries/AP_Networking/AP_Networking.cpp | 54 ++++++++++++++++--- .../AP_Networking/AP_Networking_Config.h | 6 ++- .../AP_Networking_SwitchPort_lwIP.h | 1 + 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/libraries/AP_Networking/AP_Networking.cpp b/libraries/AP_Networking/AP_Networking.cpp index 0a2ad0bc78b607..925c0fa24dc08a 100644 --- a/libraries/AP_Networking/AP_Networking.cpp +++ b/libraries/AP_Networking/AP_Networking.cpp @@ -392,9 +392,18 @@ void AP_Networking::init() */ void AP_Networking::announce_address_changes() { - const auto &as = backend->activeSettings; + uint32_t last_change_ms = 0; - if (as.last_change_ms == 0 || as.last_change_ms == announce_ms) { + if (backend != nullptr) { + last_change_ms = backend->activeSettings.last_change_ms; + } +#if AP_NETWORKING_BACKEND_SWITCHPORT_LWIP + else if (port_lwip != nullptr) { + last_change_ms = port_lwip->get_last_change_ms(); + } +#endif + + if (last_change_ms == 0 || last_change_ms == announce_ms) { // nothing changed and we've already printed it at least once. Nothing to do. return; } @@ -406,7 +415,7 @@ void AP_Networking::announce_address_changes() GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: Gateway %s", SocketAPM::inet_addr_to_str(get_gateway_active(), ipstr, sizeof(ipstr))); #endif - announce_ms = as.last_change_ms; + announce_ms = last_change_ms; } /* @@ -417,7 +426,14 @@ void AP_Networking::update() if (!is_healthy()) { return; } - backend->update(); + if (backend != nullptr) { + backend->update(); + } +#if AP_NETWORKING_BACKEND_SWITCH + if (hub != nullptr) { + hub->update(); + } +#endif #if AP_NETWORKING_CAPTURE_ENABLED // Manage per-port-type packet captures based on NET_CAPMASK #if AP_NETWORKING_BACKEND_SWITCHPORT_LWIP @@ -520,18 +536,42 @@ bool AP_Networking::convert_str_to_macaddr(const char *mac_str, uint8_t addr[6]) // returns the 32bit value of the active IP address that is currently in use uint32_t AP_Networking::get_ip_active() const { - return backend?backend->activeSettings.ip:0; + if (backend != nullptr) { + return backend->activeSettings.ip; + } +#if AP_NETWORKING_BACKEND_SWITCHPORT_LWIP + if (port_lwip != nullptr) { + return port_lwip->get_active_ip(); + } +#endif + return 0; } // returns the 32bit value of the active Netmask that is currently in use uint32_t AP_Networking::get_netmask_active() const { - return backend?backend->activeSettings.nm:0; + if (backend != nullptr) { + return backend->activeSettings.nm; + } +#if AP_NETWORKING_BACKEND_SWITCHPORT_LWIP + if (port_lwip != nullptr) { + return port_lwip->get_active_netmask(); + } +#endif + return 0; } uint32_t AP_Networking::get_gateway_active() const { - return backend?backend->activeSettings.gw:0; + if (backend != nullptr) { + return backend->activeSettings.gw; + } +#if AP_NETWORKING_BACKEND_SWITCHPORT_LWIP + if (port_lwip != nullptr) { + return port_lwip->get_active_gateway(); + } +#endif + return 0; } /* diff --git a/libraries/AP_Networking/AP_Networking_Config.h b/libraries/AP_Networking/AP_Networking_Config.h index d635d4ab798c43..e63cbabc20c5a9 100644 --- a/libraries/AP_Networking/AP_Networking_Config.h +++ b/libraries/AP_Networking/AP_Networking_Config.h @@ -88,10 +88,12 @@ #endif #ifndef AP_NETWORKING_BACKEND_SWITCHPORT_LWIP -// lwIP switchport - for MAC gateway clients, NOT enabled on SITL by default +// lwIP switchport - enabled when switch has Ethernet (replaces old ChibiOS backend) +// or for MAC gateway clients. NOT enabled on SITL by default // (SITL uses native sockets by default for compatibility) #define AP_NETWORKING_BACKEND_SWITCHPORT_LWIP \ - (AP_NETWORKING_LWIP_AVAILABLE && AP_NETWORKING_BACKEND_IS_MAC_GATEWAY_CLIENT) + (AP_NETWORKING_LWIP_AVAILABLE && \ + (AP_NETWORKING_BACKEND_IS_MAC_GATEWAY_CLIENT || AP_NETWORKING_BACKEND_SWITCHPORT_ETHERNET)) #endif #ifndef AP_NETWORKING_BACKEND_SWITCHPORT_MAVLINK_COBS diff --git a/libraries/AP_Networking/AP_Networking_SwitchPort_lwIP.h b/libraries/AP_Networking/AP_Networking_SwitchPort_lwIP.h index 6f28113ba6552a..ac7c9ae3bfc5f8 100644 --- a/libraries/AP_Networking/AP_Networking_SwitchPort_lwIP.h +++ b/libraries/AP_Networking/AP_Networking_SwitchPort_lwIP.h @@ -51,6 +51,7 @@ class AP_Networking_SwitchPort_lwIP : public AP_Networking_SwitchPort uint32_t get_active_ip() const; uint32_t get_active_netmask() const; uint32_t get_active_gateway() const; + uint32_t get_last_change_ms() const { return activeSettings.last_change_ms; } private: AP_Networking_Switch *hub;