ADR 0043 — OOBI VLAN (No VXLAN) Refactor¶
- Status: Accepted (2026-05-14)
- Date: 2026-05-14
- Deciders: TLSStress.Art project (operator directive locked in
memo
project_oobi_no_vxlan_directive_2026_05_14) - Supersedes (in part): ADR 0019 (OOBI slot allocation — carrier mechanism changes; slot map unchanged), ADR 0036 (HB references to overlay), ADR 0037 (oobi/client source-bind device), ADR 0038 (DSCP marking — preserved verbatim), ADR 0039–0042 (references to the VXLAN overlay updated; behaviour unchanged)
- Targets: v4.0.0 (major breaking change)
Context¶
Before 2026-05-14 the Out-of-Band Infrastructure (OOBI) management plane was carried over a VXLAN overlay with:
- VNI
254254(mnemonic = inner /24 octets.254.254) - UDP port
4789(IANA standard) - Inner addressing
100.127.252.0/24+ IPv6 ULAfd5a:7c5e:a72::/64 - Underlay MTU floor 1550 (1500 inner + 50 VXLAN overhead)
- Carrier VLAN 99 by default (operator-configurable)
- VTEP DaemonSet (
k8s/oobi/30-vtep-daemonset.yaml) creatingvxlan0/oobi0on every node, maintaining a head-end replication (HER) peer FDB read from a ConfigMap
Reasons that posture was chosen originally:
- Customer collision avoidance: the customer's L2 might already use any RFC 1918 carve-out; VXLAN gave us encapsulation independence.
- Slot stability across topologies: the overlay made the inner addressing identical in single-node lab and multi-node production, regardless of physical L2 plan.
- Multicast-free BUM: HER mode let us avoid the underlay needing multicast.
In the 9 months since the overlay shipped (v3.5.0), the actual deployment experience surfaced trade-offs that the operator considered unacceptable:
- Encap/decap overhead in the kernel hot path; even at MTU 1500 inner the underlay needed jumbo to keep wire frames at line rate.
- Operator confusion between OOBI (the management network) and OOBI fabric (the VXLAN overlay) — the two terms drifted apart in the codebase and documentation despite naming the same thing.
- VTEP DaemonSet was an additional moving part: peer list
maintenance, FDB drift detection, an additional namespace
(
oobi-fabric), additional privileges (NET_ADMIN + SYS_ADMIN + hostNetwork). pkg/oobi/canon-verify.shexit codes depended on inner-VTEP kernel state being just right (vxlan0exists with correct VNI, dstport, MTU, ToS, no learning) — flaky across kernel versions.- VXLAN as a test payload against the NGFW DUT (TREX.Art and HyperBridge.Art can generate it as data plane stress) is a perfectly legitimate use case — but having VXLAN simultaneously as management transport AND test payload created semantic confusion in test reports.
The 2026-05-14 operator directive declared:
Não teremos mais Fabric OOBI com VXLAN. Teremos somente OOBI, tradicional, sem VXLAN como overlay. Precisamos ajustar todos os modulos, kernels, runtimes para operar com VLAN. A única exceção que possuirá VXLAN são os elementos que farão túneis VTEP com o NGFW DUT em determinados testes de performance com VXLAN. A rede 100.127.252.0/24 e a VLAN 99 não devem mais existir no projeto.
The directive is captured verbatim in memo
project_oobi_no_vxlan_directive_2026_05_14.
Decision¶
OOBI becomes a traditional 802.1Q VLAN carved out of the management uplink — no overlay. The canonical surface:
| Property | Value | Rationale |
|---|---|---|
| Carrier VLAN ID | 2777 | Replaces previous "VLAN 99"; chosen for low collision probability with customer DUT-VLANs (most networks reserve <1000 + lab spaces 3000+) |
| Host subinterface | oobi0 |
Bring-up: ip link add link eth0 name oobi0 type vlan id 2777. Name is uplink-agnostic (works for eth0, ens3, bond0, etc.) |
| IPv4 subnet | 100.127.252.0/24 |
RFC 6598 CGNAT carve-out; exotic enough to minimise customer collision while remaining administratively scoped |
| IPv4 supernet | 100.127.252.0/22 |
Parent prefix; .253–.255 reserved for HPA expansion + HA replicas + future |
| IPv6 subnet | fd5a:7c5e:a72::/64 |
Preserved verbatim — RFC 4193 ULA was uplink-agnostic and never depended on the overlay |
| MTU | 1500 | Standard Ethernet floor; jumbo (9000) supported when both NICs + switch allow |
| DSCP marking | CS7 mandatory on every OOBI packet | Preserved verbatim from ADR 0038. The removal of VXLAN does NOT relax this — the DSCP bits live in the only IPv4/v6 header now in flight |
| Slot map | unchanged (slot 0–255 → 100.127.252.<slot>) |
The slot map (SlotPW=79, SlotSPANPrimary=230, etc.) is preserved — only the IPv4 prefix changed |
VXLAN does not disappear. It changes role:
- ❌ NOT management transport (was pre-2026-05-14)
- ✅ Test payload generated by TREX.Art and HyperBridge.Art against the DUT, to measure DUT VXLAN inspection capacity in scale. Test payload is emitted on the data plane (VLAN 20 / VLAN 30 / data-plane macvlans), never on the OOBI VLAN.
The expurgo is total: 100.127.252.0/24, VLAN 99 (as OOBI), VXLAN
VNI 254254, and oobi0 interface name must not appear
anywhere in the codebase except as historical comments and
regression-guard test cases.
Topology compatibility matrix¶
| Deployment | OOBI carrier |
|---|---|
| Single-node lab | oobi0 subinterface on the single host; no switch needed; pods receive 100.127.252.x via Multus macvlan |
| Dual-node (UCS-1 + UCS-2 with cross-cable) | Direct link between hosts; each host runs oobi0 subinterface; 802.1Q trunking on the cable |
| Dual/tri/multi-node (UCS + Nexus switch) | Nexus 9000 trunks VLAN 2777 between the UCS ports; standard configuration |
Single-node intra-host transport works without any switch (loopback
in the kernel). The same canonical surface (oobi0 + slot map)
exists across all three topologies.
Consequences¶
Positive¶
- Performance: no encap overhead. Postgres queries, Dashboard → MÓDULOs RPC, agent heartbeats — all gain ~5% throughput without jumbo, more with jumbo.
- Simplicity: VTEP DaemonSet deleted. One less moving part.
- Debuggability:
tcpdump -i oobi0works natively. No need to decapsulate VXLAN headers in capture analysis. - Single-node parity: VXLAN VTEP in single-node was a loopback hack; VLAN subinterface is naturally local.
- Semantic clarity: VXLAN now means "test payload generated by TREX.Art / HyperBridge.Art against the DUT" — no overlap with the management plane.
Negative¶
- Major version bump: any installation on v3.x is incompatible with v4.0+. CHANGELOG records this as a breaking change.
- Documentation drift: 144 files referenced the retired identifiers (10.254.254, VLAN 99, VNI 254254, oobi0). All must be expurgated across 7 PRs in the OOBI-VLAN wave.
- Customer collision risk shifts: now in
100.127.252.0/22(CGNAT carve-out). Acceptable — no customer should be using CGNAT internally; if they are, operator picks a different /22 within 100.64.0.0/10 via CPOS override. - Stale operator workflows: any operator CPOS document
referencing
oobi.canon.vni/oobi.canon.udp_port/oobi.canon.inner_mtuwill hit a clear validation error (we keep them inFORBIDDEN_OOBI_FIELDSas a tripwire).
Implementation plan (7 PRs)¶
| PR | Scope |
|---|---|
| PR-OOBI-VLAN-1 (this commit) | Foundation: pkg/oobi/canon.go + pkg/oobi/client/ defaults + TS mirror + airgap-oobi-canon-verify.sh Check 1 + this ADR + memo |
| PR-OOBI-VLAN-2 | Go libs sweep: pkg/customer-mgmt-receiver/internal/nad/*, pkg/hyperbridge-art/internal/netflow/exporter.go, pkg/flow-art/internal/server/source_bind_*.go, pkg/span-collector/cmd/*, plus 22 Go test files |
| PR-OOBI-VLAN-3 | Infra-as-code: DELETE k8s/oobi/30-vtep-daemonset.yaml + DELETE k8s/vyos-vtep/ + recreate NAD oobi-overlay as macvlan on oobi0 + update 31 k8s/ files + scripts/airgap-oobi-canon-verify.sh Checks 2–4 rewritten |
| PR-OOBI-VLAN-4 | Dashboard TS sweep: 22 TS files (lib/oobi/, lib/lab-staging/, lib/sustainability/, lib/tests/ip-canon) |
| PR-OOBI-VLAN-5 | VXLAN-as-test-payload isolation in TREX.Art + HyperBridge.Art with explicit --vxlan-test-payload-mode flag; documentation that VXLAN here is payload, never transport |
| PR-OOBI-VLAN-6 | Docs sweep: CLAUDE.md + 38 docs + READMEs + ADRs 0036–0042 with "Refactored 2026-05-14" header + CHANGELOG v4.0.0 entry |
| PR-OOBI-VLAN-7 | Smoke validation refeita: P1.1 K8s manifests + P1.2 NetFlow + P1.3 SPAN + P1.4 CMR + PW agent — all on the new 100.127.252.0/22 carve-out |
Compliance¶
airgap-oobi-canon-verify.shCheck 1 enforces the new constants bash ↔ go ↔ ts agreement (this commit).airgap-oobi-canon-verify.shChecks 2–4 enforce runtime state (PR-OOBI-VLAN-3).pkg/oobi/canon_test.go::TestNoVXLANRemnantsregression guard against accidental reintroduction (this commit).dashboard/src/lib/oobi/__tests__/canon.test.tsregression guard matching the Go-side guard (this commit).- CPOS schema rejects mutations to canon fields (post-refactor +
pre-refactor names) —
FORBIDDEN_OOBI_FIELDSindashboard/src/lib/dom/cpos-schema.ts.
References¶
- Memo:
project_oobi_no_vxlan_directive_2026_05_14.md - Memo:
discuss_oobi_immutable_gateway_art_2026_05_10.md(now partially superseded) - ADR 0019: OOBI slot allocation (slot map preserved)
- ADR 0038: Universal DSCP Marking Policy (preserved verbatim)
- CHANGELOG v4.0.0 entry (lands in PR-OOBI-VLAN-6)