# 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):

```bash
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.
