olt: add bulk DHCPv4/DHCPv6 filter edit alongside flood mode
Generalises the OLT bulk tool from flood-mode-only to arbitrary NNI-service
edits. DHCP modes live nested under each NNI entry's Filter object
(Filter.DHCPv4 / Filter.DHCPv6, e.g. "pass" <-> "umt"), confirmed from a
real OLT-CFG paste-back.
- src/mcms-api.js: planFloodChange -> planNniEdit(oltCfg, {tagPattern, flood,
dhcpv4, dhcpv6}); each concern optional. DHCP is value-replacement,
replace-only-when-present (never invents the key; leaves EAPOL/PPPoE/NDP).
Still non-mutating (clones the entry AND the Filter). Returns changes with
per-entry edits[]. summarizeOltNniNetworks surfaces dhcpv4/dhcpv6; new
dhcpModeOfNni helper.
- main.js + web/server.js: executeFloodChange handler passes flood/dhcpv4/
dhcpv6 ops through (channel name kept for wire compat).
- renderer: OLT inspector now has three action dropdowns (Flooding / DHCPv4 /
DHCPv6, defaults flood private->auto + DHCP pass->umt); table shows DHCP
chips + per-service "will change (flood, DHCPv4, …)"; flood-mode filter
defaults to Any so DHCP-on-pass auto-flood OLTs still show; CSV report
lists every per-NNI edit (pon-olt-nni-*.csv).
Verified: node --check; planNniEdit unit-tested against the real fixture +
a pass variant (13/13: no-mutation, EAPOL/PPPoE/NDP preserved,
replace-when-present, flood/DHCP independence); OLT view rendered offscreen
showing correct per-service "will change" markers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
de037c8795
commit
5e3d9271a8
7 changed files with 232 additions and 118 deletions
61
CLAUDE.md
61
CLAUDE.md
|
|
@ -18,7 +18,8 @@ fleet. Top-level **tabs** (Dashboard / ONU / OLT) switch between:
|
|||
- **Dashboard** — read-only network telemetry (see §15).
|
||||
- **ONU** — the fleet table + firmware-upgrade campaign + verify flows
|
||||
(the original purpose: bulk ONU firmware upgrades).
|
||||
- **OLT** — bulk OLT PON flooding-mode changes (private↔auto, see §14).
|
||||
- **OLT** — bulk OLT NNI-service edits: PON flooding mode (private↔auto) and
|
||||
DHCPv4/v6 filter (pass↔umt), see §14.
|
||||
|
||||
Reference deployment: GNXS / Tibit MicroPlug ONUs running Interos Everest
|
||||
(EV051xxR / EV052xxR firmware family) behind Tibit OLTs.
|
||||
|
|
@ -655,48 +656,54 @@ Key procedure citations:
|
|||
|
||||
---
|
||||
|
||||
## 14. OLT PON flooding mode (bulk private↔auto)
|
||||
## 14. OLT NNI-service edits (bulk flood mode + DHCP filter)
|
||||
|
||||
Second bulk feature, added after the firmware upgrader. Lets an operator
|
||||
flip the PON flooding mode of OLT NNI services across many OLTs at once.
|
||||
edit OLT NNI services across many OLTs at once. Two concerns, applied
|
||||
together in one GET→edit→PUT per OLT:
|
||||
|
||||
### The mutation rule (the whole feature in one fact)
|
||||
### The two mutation rules
|
||||
|
||||
On Tibit OLTs, a service's flooding mode is encoded by the **presence or
|
||||
absence of one key** on its `OLT-CFG["NNI Networks"][i]` entry:
|
||||
Both live on each `OLT-CFG["NNI Networks"][i]` entry, both confirmed
|
||||
empirically from operator paste-backs of `s0.c76.c0`:
|
||||
|
||||
- **`PON FLOOD ID` key present** (any value, including `0`) → **private**
|
||||
- **`PON FLOOD ID` key absent** → **auto**
|
||||
1. **Flooding mode** — the **presence/absence of the `PON FLOOD ID` key**:
|
||||
present (any value, incl. `0`) → **private**; absent → **auto**. So
|
||||
private→auto is `delete entry['PON FLOOD ID']`; auto→private is
|
||||
`entry['PON FLOOD ID'] = 0`.
|
||||
2. **DHCP filter mode** — a **value** under the nested `Filter` object:
|
||||
`entry.Filter.DHCPv4` / `entry.Filter.DHCPv6`, e.g. `"pass"` ↔ `"umt"`
|
||||
(siblings `EAPOL`/`PPPoE`/`NDP` are left alone). Value replacement, not
|
||||
key presence. **Replace-only-when-present**: an entry with no `Filter`
|
||||
(or no such key) is skipped, never invented.
|
||||
|
||||
So private→auto is `delete entry['PON FLOOD ID']`; auto→private is
|
||||
`entry['PON FLOOD ID'] = 0`. Everything else on the entry (`TAG MATCH`,
|
||||
`Learning Limit`, …) and the rest of the OLT-CFG is preserved. This was
|
||||
confirmed empirically by diffing two paste-backs of the same OLT
|
||||
(`24:65:e1:cc:af:1e`, NNI `s0.c76.c0`) in private vs auto — the *only*
|
||||
difference was that key.
|
||||
|
||||
The default action ships as: TAG MATCH = `s0.c76.c0`, mode `private` →
|
||||
`auto`. Both directions are wired so a change can be rolled back from the
|
||||
same UI.
|
||||
Everything else on the entry and the rest of the OLT-CFG is preserved.
|
||||
Default actions: TAG MATCH `s0.c76.c0`, flood `private→auto`, DHCPv4/v6
|
||||
`pass→umt`. All directions are wired, so changes roll back from the same UI.
|
||||
|
||||
### Data flow
|
||||
|
||||
```
|
||||
listOlts ─► McmsClient.listAllOltConfigs ─► summarizeOltNniNetworks (pure)
|
||||
executeFloodChange ─► per-OLT: getOltConfig ─► planFloodChange (pure, no-mutate)
|
||||
─► putOltConfig (full-doc PUT)
|
||||
executeFloodChange ─► per-OLT: getOltConfig ─► planNniEdit (pure, no-mutate)
|
||||
(channel name kept for wire compat) ─► putOltConfig (full-doc PUT)
|
||||
```
|
||||
|
||||
- **Pure helpers** live at the bottom of `src/mcms-api.js`:
|
||||
`floodModeOfNni`, `summarizeOltNniNetworks`, `tagPatternToRegex`,
|
||||
`planFloodChange`. `planFloodChange` clones the `NNI Networks` array and
|
||||
never mutates its input — it returns `{ newDoc, changes, unchanged }`.
|
||||
- **Pure helpers** at the bottom of `src/mcms-api.js`: `floodModeOfNni`,
|
||||
`dhcpModeOfNni`, `summarizeOltNniNetworks`, `tagPatternToRegex`,
|
||||
`planNniEdit`. `planNniEdit(oltCfg, { tagPattern, flood, dhcpv4, dhcpv6 })`
|
||||
clones the `NNI Networks` array (and any edited `Filter`) and never mutates
|
||||
its input. Returns `{ newDoc, changes, unchanged }`, where a change is
|
||||
`{ index, tagMatch, edits: [{ type, from, to }] }` — `type` is `'flood'`,
|
||||
`'DHCPv4'`, or `'DHCPv6'`, so one entry can carry several edits.
|
||||
- Each concern is optional (`flood`/`dhcpv4`/`dhcpv6` may be `null`); the UI
|
||||
has three independent action dropdowns.
|
||||
- **TAG MATCH pattern** supports exact strings, `*`/`""` (match all), and
|
||||
`*` globs (e.g. `s0.c76.*`). `tagPatternToRegex` escapes regex metachars
|
||||
then turns `*` into `.*`.
|
||||
- **`fromMode` guard**: only entries currently in `fromMode` are flipped;
|
||||
entries already in the target mode are recorded in `unchanged` (the
|
||||
per-OLT `noop` case), so re-running is idempotent.
|
||||
- **`from` guards**: only entries currently on the `from` mode/value are
|
||||
flipped; entries already at target are left in `unchanged` (the per-OLT
|
||||
`noop` case), so re-running is idempotent.
|
||||
- **Concurrency 3** on the write path (vs 5 for ONU delete, 8 for state
|
||||
fetch) — OLT writes carry far more blast radius.
|
||||
- **PUT-as-replace**, same gotcha as ONU-CFG (§5.7): the handler GETs the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue