github 2GT-Media-Group-LLC/mikrotik-manager v0.24.9-beta

pre-release3 hours ago

feat(topology): resolve upstream from spanning tree, and audit STP (v0.24.9-beta)

Phase 1 and 2 of the STP plan. Read-only throughout; nothing configures a
device.

Phase 1 — upstream from spanning tree

Neighbour discovery produces an undirected, ambiguous adjacency set. On the
live fleet a single root port resolves to three managed neighbours plus an
unidentified one, and from that alone there is no way to say which is
upstream. It is why the rollout warning added in #135 stayed silent here: it
could not tell, and naming the wrong switch is worse than saying nothing.

Spanning tree already knows. Each bridge reports the port facing the root, the
root it sees, and its distance to it, so:

the upstream is the neighbour on the root port that is in the same STP
domain and closer to the root

Both conditions earn their place. Same domain rules out neighbours on an
unrelated tree; lower cost rules out devices downstream of us that see us on
the same wire.

resolveStpUpstreams() answers per bridge, not per device, because a device
bridging two segments sits at a different depth in each. Where the test leaves
exactly one candidate it resolves; where it leaves none or several it says so.
Verified against the fleet before the code was written and again after:

2GT-NW-BigSwitch -> 2GT-NW-100G resolved (from three candidates)
2GT-NW-MIKROTIK10G-TEST -> — external-root 0x2000.70:A7:41:EF:8F:FB

That second line is the part worth keeping. Its root is a bridge no managed
device owns, so its real upstream is equipment nobody has added — and the
honest answer is "not ours", not the nearest plausible switch.

Consumers:

  • findUpstreamWithinSelection() now defers to it instead of re-deriving the
    relation from port roles. On this fleet it goes from returning nothing to
    correctly naming 2GT-NW-100G.
  • The topology diagram uses the resolved upstream as the parent rather than
    whichever neighbour breadth-first search reached first, with adjacency as
    the fallback and a straggler pass so nothing is dropped.

The rolloutTopology tests were rewritten rather than patched. One of them
asserted that an ambiguous port yields no warning — true of the old heuristic,
and exactly the limitation this removes.

Phase 2 — STP in Config Health

No new collection: DeviceSnapshot already captures bridges and bridge ports
with detail, so every field was on hand.

  • stp-disabled (warning): protocol-mode=none on a bridge with two or more
    active ports. Nothing is wrong while the cabling is correct, which is why
    it needs saying — a second path becomes a forwarding loop with no TTL to
    stop it. Single-port and all-disabled bridges are ignored; they cannot
    loop.
  • stp-legacy-mode (info): classic STP where RSTP would converge in a
    fraction of the time.

Fleet-level observations went to Operations insights instead, because
auditConfig only ever sees one device and cannot know what the rest of the
fleet reports. The external-root insight fires truthfully here today.

Not verified on hardware: both config-health rules are covered by unit tests
only. Making them fire for real would mean turning spanning tree off on a live
switch, which is not a thing to do to prove a warning works.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com


Container image: ghcr.io/2gt-media-group-llc/mikrotik-manager:0.24.9-beta

Documentation: https://2gt-media-group-llc.github.io/mikrotik-manager/

Don't miss a new mikrotik-manager release

NewReleases is sending notifications on new releases.