Skip to content

Releases: pereljon/dynavlan

v0.4.11

Choose a tag to compare

@pereljon pereljon released this 07 Aug 03:28

Consolidates the pre-1.0 gate-4 review hardening (0.4.3 through 0.4.11) into one release. Hardware-validated console-backed on the reference Protectli box (build b0317b6, 14/14 checks PASS): build-identity gate, M8 status dep-gate, H5 box-wide lease timing, M5 pending-delete drain, M6 restart-failure seen-set, P2 kill-mid-apply FIFO-EOF revert, and the L3-30 carrier-pull prune + re-add.

Highlights (full detail in CHANGELOG):

  • P3: order-independent post-apply health check for equal-metric multi-uplink boxes
  • M8: --status reports unavailable + non-zero when a detection tool is missing (no false "no trunk")
  • M6: a total restart failure no longer marks a new subnet "seen" (retries next run; a partial success consumes)
  • M5: a failed post-accept ip link delete is recorded and retried, not orphaned until reboot
  • M4: additions are dropped on a trunk that lost carrier in the detection->apply window
  • H5: the post-accept lease wait is one box-wide deadline, not per-VLAN in series
  • H1: a failed capture method can no longer authorize a boot detection-diff removal
  • M7: VLAN_LIMIT_MODE=fill keeps the lowest numeric IDs
  • H6/M1: interface-name contract (IFNAMSIZ 15-char limit; refuse dotted parents; injective interface key)
  • Removed the reserved-but-unimplemented PER_VLAN_MAC key (postinst migrates old conffiles)
  • Packaging/CI: Debian prerm aborts on a lock timeout; the APT-repo rebuild no longer silently drops packages

v0.4.2

Choose a tag to compare

@pereljon pereljon released this 05 Aug 17:02

Pre-freeze hardening from the v0.4 adversarial review, plus earlier cheap fixes.

Fixed

  • Apply-evidence (C2): removal-only / --reapply no longer accept a netplan try on elapsed time. No-addition changes have no in-kernel signal, so they now use a larger bounded settle floor (APPLY_NOEVIDENCE_SETTLE) sized so the first health sample lands post-apply; netplan try's exit is logged on both paths. Hardware-validated (accept at 18.19s on a genuine carrier-down removal).
  • Config isolation (H2): /etc/dynavlan.conf is now parsed declaratively against an allowlist, never sourced — a config line can no longer execute code or override an internal/safety variable (NETPLAN_FILE, TRY_TIMEOUT, ver, PATH, ...). Unknown/protected keys refuse the run.
  • Routed-mode default-route guard (C1): dynavlan refuses a reconcile that would remove the interface currently serving the default route (routed mode), before any disk change — preventing an unrevertable strand. No-op at the default VLAN_ROUTES=false.
  • --dry-run exit code (M3): now exits non-zero when validation fails.
  • Debian upgrade timer-state (H3): upgrades preserve the operator's enabled/active timer state instead of re-arming a deliberately-disabled timer.
  • Version binding (H7): build-deb.sh refuses to build when the requested version disagrees with the script's ver=.

Added

  • Public APT repository for apt-based install/upgrade.

Full detail: CHANGELOG.md.

v0.4.0

Choose a tag to compare

@pereljon pereljon released this 04 Aug 09:31

Added

  • Carrier-down VLAN removal (FR-41). When an owned trunk's physical link stays carrier-down across a two-sample debounce (BOOT_SETTLE_SECONDS apart) - at boot or on the rescan timer - and the box still has a healthy default route, dynavlan removes all owned VLANs on that trunk through the standard validated + health-gated + auto-reverting apply chain. A carrier-down port cannot pass frames, so this is a full teardown of the trunk's set, not a per-VLAN detection diff. Independent of RESET_ON_BOOT: governed solely by new config key REMOVE_ON_CARRIER_LOSS (default true), so a RESET_ON_BOOT=false box still self-heals a dead trunk. Rescan (previously strictly add-only) gains its first removal path; the settle sleep is incurred only when an owned trunk is actually carrier-down, so the steady-state fast path is unchanged. Narrows the prior preservation invariant: preservation now protects only genuine detection uncertainty (carrier-up, no tags) - carrier-down is authoritative kernel evidence and is no longer blanket-preserved. --dry-run previews a would-be teardown; --status reports carrier state per owned trunk.
  • New pure helpers carrier_removals (the debounce decision) and have_routing (the routing pre-condition). have_routing requires a lowest-metric default route, carrier on its egress iface, AND carrier on at least one physical NIC, so a dead trunk that doubles as the box's own uplink with no redundant route is preserved rather than attempted.
  • Public APT repository (GitHub Pages + reprepro): this re-tag republishes v0.4.0 to trigger the new publish-apt CI job for the first time - no dynavlan script change, ver= stays 0.4.0.

Hardware validation (2026-08-04)

All 6 sub-cases PASS on the Protectli box, console-driven: carrier-pull prune (rescan), re-plug re-add, flap-shorter-than-settle preserve, own-uplink-with-no-redundant-route preserve, --boot prune, post-boot re-add. Full detail in dev/features/dynavlan-tests.md (L3-30).

Full changelog: https://github.com/pereljon/dynavlan/blob/main/CHANGELOG.md#040---2026-08-04

v0.3.0 - restart on newly-appeared IPv4 subnet (FR-40)

Choose a tag to compare

@pereljon pereljon released this 31 Jul 06:05

Restart on a newly-appeared IPv4 subnet (FR-40)

dynavlan now restarts the nominated RESTART_SNAPS/RESTART_SERVICES whenever a new global-IPv4 subnet appears on any interface, not only on a tagged-VLAN change. This closes two gaps:

  • An access port or native-only trunk that leases after boot (no tagged VLAN, so nothing was changing before).
  • The monitoring agent starting before the base interface finishes DHCP at boot (dynavlan's boot run is deliberately not ordered after network-online.target).

Both are the same underlying problem: the agent cares about IPv4 subnets it can scan, not VLAN tags.

Behavior

  • New pure helper ipv4_network keys subnet tokens on the network address, not the host address, so a same-pool DHCP renewal never restarts.
  • A monotonic per-uptime seen-set at /run/dynavlan/seen (wiped on reboot): a flap back onto an already-seen subnet doesn't restart; an empty seen-set at boot restarts once after settle regardless of boot-vs-DHCP ordering.
  • At most one restart per run, deduped against any VLAN-driven restart.
  • --dry-run / --status report the would-restart delta without restarting or writing the seen-set.
  • apply_change (the accept/rollback chain) is unchanged; the growth-check is an additive post-step in main.

Config

  • New key RESTART_ON_NEW_SUBNET (default true). No-op when no restart targets are configured.

Validation

  • Unit suite 139/0; per-task, architect, and whole-branch reviews clean.
  • Hardware-validated on a Protectli box with the real Domotz snap: access-port and boot-race restarts, same-subnet/flap/disappearance no-restart, and read-only --dry-run/--status, across UniFi and Meraki.

Full detail in CHANGELOG.md and docs/dynavlan-PRD.md (FR-40).

v0.2.1

Choose a tag to compare

@pereljon pereljon released this 30 Jul 15:59

What's new in 0.2.0

All-trunks provisioner redesign. dynavlan now provisions VLANs on every carrier-up trunk with detected tags, not one selected trunk. A box with two live trunks gets both provisioned in one unified netplan try. The universal token is now iface.id (e.g. enp1s0.100), so two trunks sharing the same VLAN id provision as distinct interfaces.

--reapply (FR-39). Regenerate and apply the current VLAN set with the running build's config. Use after an upgrade or a config change like VLAN_ROUTES=true.

--version / -V and build identity (FR-38). Every install is stamped with its git commit. Works unprivileged and with a broken config.

Opt-in routed mode (FR-37). VLAN_ROUTES=true accepts DHCP routes at per-VLAN metrics. DNS/NTP stay declined.

Hardware-validated 2026-07-30 on a Protectli/igb dual-trunk appliance with a Meraki switch: dual leasing (L3-29), carrier-pull preserve (L3-30), routed multi-trunk (L3-31), and unified revert (L3-32) all PASS.

0.2.1 fix

  • backend_list_managed_vlans awk assumed link: before id: in netplan get output; netplan 0.107 emits id: first. Found in code review; 3 tests added.

See CHANGELOG.md for the full list of changes, removals, and fixes.