Skip to content

segments the web interface will actually list - #12

Merged
salatmaster merged 2 commits into
mainfrom
feat/ui-visible-segments
Aug 7, 2026
Merged

segments the web interface will actually list#12
salatmaster merged 2 commits into
mainfrom
feat/ui-visible-segments

Conversation

@salatmaster

Copy link
Copy Markdown
Owner

A bridge with an address, NAT and a Wi-Fi binding gives an isolated network that carries traffic perfectly and never appears in the web interface. It gets reported as "it works but I cannot see it", which is much harder to diagnose after the fact than before.

What the router calls a segment is VLAN-backed. Three steps are missing from the obvious sequence: a GigabitEthernet0/VlanN subinterface, that VLAN trunked over every switch port, and the subinterface bridged in. The router then computes iseg itself, and that block is what the web interface reads.

What is here

keenetic-segments carries the whole sequence: the discovery reads that find free identifiers, the build, the verification, and the teardown.

create_segment does it in one call. It allocates a free bridge, VLAN id, subnet, DHCP pool and Wi-Fi key, applies every step, and verifies against iseg rather than against the return value, because the router answers a wrong field name with {} and no error. A failure anywhere rolls the whole thing back and names anything it could not undo. list_segments reports uiVisible per bridge; delete_segment removes the VLAN from every port, which is the step that gets forgotten by hand.

Verified on hardware

Built and torn down on a KN-1811 running 5.1.3, driven through the built server over stdio rather than around it.

create_segment { name: "probe", ssid: "…", psk: "…" }
  uiVisible: true
  verifiedBy: iseg.vlan=3, iseg.vlan-port=1,2,3,4,5
  include:    GigabitEthernet0/Vlan3, WifiMaster0/AccessPoint2, WifiMaster1/AccessPoint2

ports before  access=1 trunk=[2]
ports during  access=1 trunk=[2,3]
ports after   access=1 trunk=[2]

switchport trunk vlan really is additive: the home network and the existing guest segment on those same ports were never disturbed. That was the one step with real risk to a router someone is using, and it is measured now rather than assumed. The teardown left no subinterface, pool or Wi-Fi entry behind.

Three things the live run corrected:

  • Bridge0 carries an address and an empty iseg, because the home network is untagged rather than a VLAN. The check that correctly finds every other invisible bridge called the home segment invisible. It is reported as home now.
  • A segment with no Wi-Fi does not appear under /access-points, and that is not a fault: the page lists Wi-Fi networks, and the include WifiMaster*/AccessPoint lines only appear once mws wlan binds to the bridge. The skill shows the two config blocks side by side, because the first thing anyone will report is that the segment is missing from a page it was never going to be on.
  • The leak detector caught a DHCP range copied out of the real router into a fixture, and then the address written into its own comment while explaining the exemption.

Deliberately not done

Nothing is ever saved: a segment is gone on reboot until save_config runs, which makes it cheap to build one, look at it and change your mind. delete_segment leaves any routing policy alone, because policies are shared and removing one with its segment can break another.

245 tests, typecheck and build clean.

A bridge with an address, NAT and a Wi-Fi binding gives an isolated network
that carries traffic perfectly and never appears under /access-points or in the
segment list. It is reported as "it works but I cannot see it", which is much
harder to diagnose after the fact than before.

What the web interface calls a segment is VLAN-backed. Three steps are missing
from the obvious sequence: a GigabitEthernet0/VlanN subinterface, that VLAN
trunked over every switch port, and the subinterface bridged in. The router
then computes `iseg` itself - vlan, port, vlan-port - and that block is what
the web interface reads. Nothing sets those fields by hand.

The keenetic-segments skill carries the whole sequence, including the discovery
reads that find free identifiers and the teardown. `create_segment` does it in
one call: it allocates a free bridge, VLAN id, subnet, pool and Wi-Fi key,
applies every step, and verifies against `iseg` rather than against the return
value, because the router answers a wrong field name with `{}` and no error. A
failure anywhere rolls the whole thing back and says what it could not undo.

Two things this deliberately does not do. It never saves: a segment is gone on
reboot until save_config runs, which makes it cheap to build one, look at it in
the web interface and change your mind. And delete_segment leaves any routing
policy alone, because policies are shared and removing one with its segment can
break another.

`switchport trunk vlan` is additive - it does not disturb the port's access
vid - so trunking every port leaves the home network on those ports untouched.
Ports are discovered rather than assumed: five is a KN-1811, not a Keenetic.

The leak detector caught two things worth keeping: a DHCP range copied out of
the real router into a fixture, and then the address I wrote into its own
comment while explaining the exemption.
Built a segment on a KN-1811 running 5.1.3, looked at it, and tore it down.
Three things came out of that.

`switchport trunk vlan` is additive in practice and not only on paper: the
ports went from access=1 trunk=[2] to access=1 trunk=[2,3] and back, so the
home network and the existing guest segment on those same ports were never
disturbed. That was the one step in this whole sequence with any real risk to
a router someone is currently using, and it is now measured rather than
assumed.

Bridge0 carries an address and an empty `iseg`, because the home network is the
untagged one rather than a VLAN. The test that correctly identifies every other
invisible bridge called the home segment invisible. It is now reported as
`home` and never as missing.

A segment with no Wi-Fi does not appear under /access-points, and that is not a
fault. The page lists Wi-Fi networks; the two `include WifiMaster*/AccessPoint`
lines only appear when `mws wlan` binds to the bridge. The skill says so now,
with the two config blocks side by side, because the first thing anyone will
report is that the segment is missing from a page it was never going to be on.

.gitignore now covers scratch-* as well as scratch/. Eight throwaway probes
written against the live router sat next to the tracked files during this, and
that is exactly where a captured address or key gets committed by accident.
@salatmaster
salatmaster merged commit abb2487 into main Aug 7, 2026
4 checks passed
@salatmaster
salatmaster deleted the feat/ui-visible-segments branch August 7, 2026 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant