Newer
Older
openstack-caracal-dc-dc / docs / dc-dc-netem-and-ula-gua-proposal.md

Proposed netem parameters + ULA/GUA generation guidance (2026-07-10)

Addresses tooling gap register items #4(d) and #11: the two D-100/D-101 sub-items still genuinely "leaning," not ruled, even after Stage 0 closed the big decisions. This document does NOT rule either -- it presents a concrete recommendation for #4(d) (present options, get a ruling, per this repo's own discipline for anything touching an ADOPTED-but-not-fully- specified decision) and, for #11's literal-generation half, exact commands the OPERATOR runs to produce a real value (this document does not generate or invent the actual ULA/48 itself -- that is explicitly the operator's/ NetBox's job per D-101's own text).


Part 1 -- Proposed tc netem parameters (D-100 sub-item #4(d))

Current state: docs/dc-dc-buildout-design.md Section 6 states only a qualitative lean: "same-metro dark fiber (low single-digit ms, jumbo- capable)." No specific latency/jitter/loss/rate numbers are ruled. opentofu/modules/netem-link (built 2026-07-09) is ready to apply real parameters the moment they're decided -- this is the one missing input.

Proposal (for operator ratification, not silently applied):

Parameter Proposed value Rationale
Latency 1ms (each direction) Same-metro dark fiber circuits (single city, no long-haul) typically show sub-millisecond one-way propagation delay for distances under ~50km (fiber propagation is ~5us/km) -- 1ms per direction (2ms RTT) is a deliberately conservative round number that accounts for real-world switching/equipment overhead beyond pure propagation, while staying solidly within the buildout design's own "low single-digit ms" lean.
Jitter 0.2ms A small, non-zero jitter keeps the simulation honest (a perfectly flat-latency link is unrealistic even on dedicated fiber) without dominating the 1ms base latency -- roughly 20%, a common rule-of-thumb ratio for stable dedicated circuits (as opposed to shared/internet-transit links, which would warrant a much larger jitter fraction).
Loss 0.01% Dark fiber with modern optical equipment is very low-loss; this is a nonzero-but-negligible value so packet-loss-handling code paths are still technically exercised during the drill, without meaningfully affecting throughput-sensitive tests (Ceph replication, radosgw sync).
Rate Not capped (no rate netem param) The buildout design's own lean explicitly says "jumbo-capable" -- same-metro dark fiber circuits are typically provisioned well above what this test environment's actual traffic will generate (VR1 is a virtual rehearsal on one physical host, not a real multi-site deployment) -- an artificial rate cap would constrain the TEST more than a real Roosevelt link would constrain PRODUCTION, which is backwards for a rehearsal whose value is proving the failover mechanism works, not proving it works under bandwidth starvation. If the operator wants to also rehearse a bandwidth-constrained scenario, that is a SEPARATE, deliberate test configuration, not this default.

Resulting tc netem invocation shape (for reference; modules/netem- link's netem_args variable takes this as a string):

delay 1ms 0.2ms loss 0.01%

This is a recommendation, not a ruling. Per this repo's standing discipline (present options for anything not yet ADOPTED, never silently decide), the operator should explicitly ratify this table (accept as-is, or adjust) before modules/netem-link is actually instantiated with real values in Stage 3's runbook. Once ratified, this should be recorded as a D-100 amendment (a new "Sub-item RULED" line in docs/design-decisions.md D-100's entry, following the exact pattern D-100's other redline items already got at Stage 0 ratification) -- not left as a standalone doc. Re-tune when a specific Roosevelt inter-DC target is known (buildout design's own stated intent) -- this proposal is a VR1 rehearsal default, not a permanent value.


Part 2 -- ULA/GUA/DC2-supernet generation guidance (D-101, gap #11 + gap #3's data half)

What this section does NOT do: generate the org ULA /48, obtain the real per-DC GUA carve, or assign DC2's supernet. D-101's own text is explicit that these are NetBox-authoritative, populated via the extended import pipeline -- not hardcoded in any decision, and not something this session (or any Claude session) should invent, guess, or pre-select on the operator's behalf. What follows is the exact, safe MECHANISM for the operator to produce each real value themselves, so that step is a two- minute copy-paste rather than a research task when they're ready to do it.

2.1 -- Org ULA /48 (RFC 4193)

RFC 4193 requires the 40-bit Global ID be "randomly generated" for statistical uniqueness across organizations -- a cryptographically random 40 bits satisfies this directly (this is also what every independent RFC-4193-compliant ULA generator tool checked during tonight's research actually does under the hood, not a shortcut invented here):

printf 'fd%s::/48\n' "$(openssl rand -hex 5 | sed 's/\(..\)\(..\)\(..\)\(..\)\(..\)/\1\2:\3\4\5/')"

Run this ONCE, by the operator, on a real machine -- the output is the real ORG_ULA_48 value netbox/dc-dc-prefixes-import.py (DOCFIX-152) requires. Record it in NetBox as the IPAM apex (D-101's own requirement), not just as an environment variable -- this is a permanent organizational identifier, not a per-session value.

2.2 -- Per-DC GUA carve (from ARIN 2602:f3e2::/32 region-0 /36)

This is NOT something to generate randomly -- D-101's own text names this as ALREADY a real, existing ARIN allocation ("GUA (ARIN 2602:f3e2::/32, region-0 /36)"), meaning the org already holds this block from a real Internet numbering authority. The per-DC carve within it (which /40 or /44 goes to DC1 vs. DC2) is an INTERNAL allocation decision within an already- owned block, not a new external assignment -- this can be decided by whoever administers that ARIN allocation for this organization, following whatever internal IPAM convention they already use for carving GUA space (e.g. sequential /40s: DC1 = 2602:f3e2:1000::/40, DC2 = 2602:f3e2:2000::/40, matching the example addresses already used in netbox/dc-dc-prefixes-import.py's own docstring and README -- those are ILLUSTRATIVE examples in this repo, not yet a real assignment; confirm with whoever holds the ARIN allocation before treating any specific /40 as final).

2.3 -- DC2's v4 supernet

This is a NetBox IPAM assignment task, not a generation task -- DC2 needs a real, non-overlapping v4 supernet (at least a /19, per netbox/dc-dc- prefixes-import.py's own DC2_MIN_SUPERNET_PREFIXLEN check) chosen from whatever address space this organization has available and not already in use by DC1, Office1, client VPN ranges (D-074), or any other real allocation. This is a real IPAM decision requiring visibility into the FULL address inventory, which this session does not have -- assign it via NetBox directly, following whatever process this organization already uses for carving new supernets.

2.4 -- Once all three exist

Run netbox/dc-dc-prefixes-import.py --dc dc1 (needs only ORG_ULA_48 and DC_GUA_PREFIX from 2.1/2.2) and --dc dc2 (additionally needs DC2_V4_SUPERNET from 2.3) for real, closing the DATA half of tooling gap

#3 -- the mechanism has been ready since DOCFIX-152; only these three real inputs were ever missing.


Summary: what this closes vs. leaves open

CLOSES: gap #4(d) now has a concrete, reasoned proposal ready for a one-line operator ratification (not a re-research task); gap #11's ULA- generation half now has an exact, safe, two-minute command instead of "go figure out RFC 4193."

STAYS OPEN, by design: the actual netem ratification (a decision only the operator can make); the actual ULA-48/GUA-carve/DC2-supernet values (real-world IPAM/ARIN coordination this session has no authority or visibility to perform) -- this document makes producing them fast and low-risk once the operator is ready, it does not produce them.