Merge pull request #922 from CyberMind-FR/feat/wan-link-guard-913

Backport WAN link guard package + netplan static fallback (#913)
This commit is contained in:
CyberMind 2026-07-28 20:22:30 +02:00 committed by GitHub
commit b5c67c9151
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 205 additions and 0 deletions

View File

@ -15,6 +15,18 @@ network:
dhcp4-overrides:
use-routes: true
route-metric: 100
# Static fallback so the box is always reachable at 192.168.1.200 even
# when DHCP never leases (issue #913). Kept at a HIGHER route-metric than
# the DHCP route (100) so the lease wins whenever it exists; the static
# default only carries traffic when DHCP is down. This IP belongs on the
# WAN (eth2), never on lan0 — secubox-wan-link-guard strips any parasite
# copy that appears on lan0.
addresses:
- 192.168.1.200/24
routes:
- to: default
via: 192.168.1.254
metric: 200
lan0: {optional: true}
lan1: {optional: true}
lan2: {optional: true}

View File

@ -0,0 +1,12 @@
secubox-wan-link-guard (1.0.0-1~bookworm1) bookworm; urgency=medium
* Initial packaging: backport the live gk2 WAN link guard into source (#913).
Ships /usr/sbin/secubox-wan-link-guard (mvpp2 eth2 pause-off + renegotiate +
lan0 parasite route/addr cleanup, no `ip link down/up`), its .service +
boot/30s .timer, the 10-secubox-eth2-noflowctl.link (flow-control off at
eth2 appearance), and the secubox-eth2-flowctl-off backstop unit.
Tunable via /etc/default/secubox-wan-link-guard. postinst migrates the
pre-dpkg hand-placed copies out of /etc/systemd and /usr/local/sbin so the
packaged units are authoritative.
-- Gerald KERMA <devel@cybermind.fr> Tue, 28 Jul 2026 19:30:00 +0200

View File

@ -0,0 +1,24 @@
Source: secubox-wan-link-guard
Section: net
Priority: optional
Maintainer: Gerald KERMA <devel@cybermind.fr>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.6.2
Package: secubox-wan-link-guard
Architecture: all
Depends: ${misc:Depends}, ethtool, iproute2, iputils-ping
Description: WAN mvpp2 marginal-link guard for SecuBox (MOCHAbin)
Board-specific watchdog for the MOCHAbin (Marvell Armada, mvpp2) WAN port,
which recurrently goes dead on gk2 through three stacked faults: the MAC TX
wedges under upstream flow-control PAUSE frames, gigabit auto-negotiation is
marginal through the intermediate hub, and a parasite default route/duplicate
host IP appears on lan0.
.
Ships a oneshot guard (ethtool pause-off + renegotiate + route/addr cleanup —
never `ip link down/up`, which wedges the comphy), a boot+30s timer, a
systemd .link that disables flow-control the moment eth2 appears, and a
flow-control backstop unit. Tunable via /etc/default/secubox-wan-link-guard.
.
MOCHAbin-only: on other boards eth2/lan0 do not match and the guard is a
no-op. See /usr/share/doc/secubox/FAQ-NETWORK-WAN-RECOVERY.md (ref #913).

View File

@ -0,0 +1,29 @@
#!/bin/bash
set -e
case "$1" in
configure)
# Migration: the guard was first deployed on gk2 by hand, OUTSIDE dpkg
# (units in /etc/systemd/system, script in /usr/local/sbin). Those shadow
# the packaged copies (/etc wins over /usr/lib for systemd; PATH picks
# /usr/local/sbin first) — remove them so the package is authoritative.
for u in secubox-wan-link-guard.service secubox-wan-link-guard.timer secubox-eth2-flowctl-off.service; do
if [ -e "/etc/systemd/system/$u" ]; then
systemctl disable "$u" >/dev/null 2>&1 || true
rm -f "/etc/systemd/system/$u"
fi
done
rm -f /etc/systemd/network/10-secubox-eth2-noflowctl.link
rm -f /usr/local/sbin/secubox-wan-link-guard
systemctl daemon-reload || true
# The periodic guard: enable + start the timer (boot + every 30s). The
# oneshot guard.service is triggered BY the timer; the flowctl backstop
# stays disabled (the .link supersedes it, matching the live board).
systemctl enable --now secubox-wan-link-guard.timer >/dev/null 2>&1 || true
# Apply once now so the flow-control/route fix takes effect without waiting
# for the first timer tick or a reboot (idempotent, safe to re-run).
systemctl start secubox-wan-link-guard.service >/dev/null 2>&1 || true
;;
esac
#DEBHELPER#
exit 0

View File

@ -0,0 +1,24 @@
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_install:
install -d debian/secubox-wan-link-guard/usr/sbin
install -m 755 sbin/secubox-wan-link-guard debian/secubox-wan-link-guard/usr/sbin/secubox-wan-link-guard
# systemd units — placed explicitly in usr/lib/systemd/system. Enable/start
# is handled below (timer) and by postinst; the oneshots are NOT started at
# install time (the guard mutates routing — let the timer/boot drive it).
install -d debian/secubox-wan-link-guard/usr/lib/systemd/system
install -m 644 systemd/secubox-wan-link-guard.service debian/secubox-wan-link-guard/usr/lib/systemd/system/
install -m 644 systemd/secubox-wan-link-guard.timer debian/secubox-wan-link-guard/usr/lib/systemd/system/
install -m 644 systemd/secubox-eth2-flowctl-off.service debian/secubox-wan-link-guard/usr/lib/systemd/system/
# networkd .link (applied by udevd when eth2 appears)
install -d debian/secubox-wan-link-guard/usr/lib/systemd/network
install -m 644 network/10-secubox-eth2-noflowctl.link debian/secubox-wan-link-guard/usr/lib/systemd/network/
override_dh_installsystemd:
# Suppress dh's auto enable/start (it would run the oneshot guard at install
# and enable the flowctl backstop the live board keeps disabled). postinst
# does the precise enabling; #DEBHELPER# still emits daemon-reload + the
# stop-on-remove hooks for all shipped units.
dh_installsystemd --no-enable --no-start

View File

@ -0,0 +1 @@
3.0 (native)

View File

@ -0,0 +1,12 @@
# SecuBox: the mvpp2 eth2 MAC TX wedges when the upstream (Freebox) floods
# flow-control PAUSE frames — good_octets_sent stays at 0 and all unicast dies.
# Confirmed fix 2026-07-28: disable flow-control pause at the .link level so it
# is applied by udevd the moment eth2 appears (covers boot-time DHCP, before the
# guard timer's first tick). See /usr/share/doc/secubox/FAQ-NETWORK-WAN-RECOVERY.md
[Match]
OriginalName=eth2
[Link]
AutoNegotiationFlowControl=no
RXFlowControl=no
TXFlowControl=no

View File

@ -0,0 +1,58 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
# Source-Disclosed License — All rights reserved except as expressly granted.
# See LICENCE-CMSD-1.0.md for terms.
# SecuBox-Deb :: secubox-wan-link-guard
# MOCHAbin (Marvell Armada mvpp2) WAN marginal-link workaround. Three stacked
# problems on gk2 (see /usr/share/doc/secubox/FAQ-NETWORK-WAN-RECOVERY.md):
# (1) the mvpp2 MAC TX wedges when the upstream floods flow-control PAUSE
# frames -> disable pause (idempotent, non-disruptive);
# (2) gigabit auto-negotiation is marginal through the hub -> renegotiate
# (ethtool -r) until the gateway answers again;
# (3) a parasite default route / duplicate host IP appears on lan0 -> drop it
# and force the default via the WAN iface.
#
# NEVER `ip link set <wan> down/up` here: that wedges the comphy and needs a
# cold boot. Recovery uses ONLY ethtool -r / -A and route/addr fixes.
#
# set +e on purpose: every step is best-effort and idempotent; a failing step
# must never abort the recovery sequence.
set +e
# Board defaults (gk2 / mochabin). Override in /etc/default/secubox-wan-link-guard.
IFACE=eth2
GW=192.168.1.254
FALLBACK_ADDR=192.168.1.200/24
PARASITE_IFACE=lan0
RENEGO_TRIES=6
# shellcheck disable=SC1091
[ -r /etc/default/secubox-wan-link-guard ] && . /etc/default/secubox-wan-link-guard
# (1) flow-control pause off (idempotent, non disruptif)
ethtool -A "$IFACE" autoneg off rx off tx off 2>/dev/null
# (3) tuer la route/IP parasite portée par $PARASITE_IFACE + forcer le default via $IFACE
ip route del default dev "$PARASITE_IFACE" 2>/dev/null
ip addr del "$FALLBACK_ADDR" dev "$PARASITE_IFACE" 2>/dev/null
ip route show default | grep -q "dev $IFACE" \
|| ip route replace default via "$GW" dev "$IFACE" 2>/dev/null
# (2) si la gateway ne répond pas -> renégocier jusqu'à accroche
if ! ping -c1 -W2 "$GW" >/dev/null 2>&1; then
t=0
while [ "$t" -lt "$RENEGO_TRIES" ]; do
t=$((t + 1))
ethtool -r "$IFACE" 2>/dev/null
sleep 4
ethtool -A "$IFACE" autoneg off rx off tx off 2>/dev/null
ip route replace default via "$GW" dev "$IFACE" 2>/dev/null
if ping -c1 -W2 "$GW" >/dev/null 2>&1; then
logger -t sbx-wan-guard "link recovered after $t renego"
break
fi
done
fi
exit 0

View File

@ -0,0 +1,13 @@
[Unit]
Description=SecuBox: disable eth2 flow-control pause (mvpp2 MAC TX wedge workaround)
Documentation=file:///usr/share/doc/secubox/FAQ-NETWORK-WAN-RECOVERY.md
After=sys-subsystem-net-devices-eth2.device
Wants=sys-subsystem-net-devices-eth2.device
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ethtool -A eth2 autoneg off rx off tx off
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,11 @@
[Unit]
Description=SecuBox WAN link guard (mvpp2 eth2: pause-off + renegotiate + route)
Documentation=file:///usr/share/doc/secubox/FAQ-NETWORK-WAN-RECOVERY.md
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/secubox-wan-link-guard
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,9 @@
[Unit]
Description=SecuBox WAN link guard — periodic check
[Timer]
OnBootSec=20
OnUnitActiveSec=30
[Install]
WantedBy=timers.target