From 54b21fa9ffd3f87a01868b66167f77fc4a30389e Mon Sep 17 00:00:00 2001 From: Michal Date: Tue, 18 Aug 2026 01:10:50 +0100 Subject: [PATCH] fix(migration): poll for WAN health instead of sampling once at 25s A real cutover attempt reported failure and reverted a configuration that may well have been fine. The health check waited a fixed 25 seconds and then judged: [switch] committed. Waiting 25s for PPPoE and services to settle... [switch] FAIL pppoe0 has an address 25s is far too short for a WAN. PPPoE alone is PADI/PADO/PADR/PADS followed by LCP, authentication and IPCP -- routinely 15-30s on its own. Both lines had also just been released by the USG seconds earlier, and ISPs commonly hold the previous session and MAC binding for minutes before leasing to the "same" CPE again, which is exactly what a cloned MAC looks like from their side. The one thing the design could not tolerate was being impatient, and it was. Now polls every 15s up to HEALTH_BUDGET (default 180s), reporting progress, and stops early the moment everything is healthy. The budget deliberately finishes long before commit-confirm fires -- 180s against a 10 minute timer leaves 420s of margin -- so the decision to confirm or revert stays ours rather than being made by the timer. Also recorded while chasing this: the earlier claim that VLANs 51/53 are not trunked to the firewalls was WRONG, and the UniFi port settings disprove it -- those LAG ports are Native VLAN Management (1) with Tagged VLAN Management set to Allow All. My evidence never supported the claim: a passive RX count cannot distinguish an absent VLAN from a quiet one, because switches do not flood unicast, and the active DHCP probe used a random MAC that an ISP binding to its registered CPE would ignore regardless. Both observations fit a perfectly healthy trunk. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DMVzWZgiKW2wquf5z8S1yH --- migration/vyos-unifi-switch | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/migration/vyos-unifi-switch b/migration/vyos-unifi-switch index c4e1d67..945ceed 100755 --- a/migration/vyos-unifi-switch +++ b/migration/vyos-unifi-switch @@ -224,8 +224,32 @@ to_vyos() { fi rm -f "$tmp" - say "committed. Waiting 25s for PPPoE and services to settle..." - sleep 25 + # Poll, do not sample once. + # + # A cutover attempt failed here on a fixed 25s wait. That is far too short for + # a WAN: PPPoE is PADI/PADO/PADR/PADS then LCP, auth and IPCP, routinely 15-30s + # by itself, and both lines had just been released by the USG seconds earlier. + # ISPs commonly hold the previous session and MAC binding for minutes before + # leasing to the "same" CPE again -- which is precisely what a cloned MAC looks + # like to them. One sample at 25s reported a healthy setup as broken and + # reverted it. + # + # There is still a deadline, because commit-confirm is running: stop well + # before it so the decision is ours rather than the timer's. + local budget="${HEALTH_BUDGET:-180}" waited=0 step=15 + say "committed. Polling health for up to ${budget}s (commit-confirm has ${CONFIRM_MINUTES} min)..." + while :; do + sleep "$step"; waited=$(( waited + step )) + if health_checks >/dev/null 2>&1; then + say "healthy after ${waited}s" + break + fi + if [ "$waited" -ge "$budget" ]; then + say "still unhealthy after ${waited}s -- final check:" + break + fi + say " not healthy yet at ${waited}s, still waiting..." + done say "health checks:" if health_checks; then