nixos/home: Separate router storage and uplinks

Give `river` a dedicated RDMA VF and two RSTP trunk attachments.
Keep client services on the router VIPs and carry Digiweb VLANs
over both switch paths.

Set VF trust, multicast reception, bridge MAC and ARP behavior for
local switching. Wait for Kea interface readiness and apply RSTP
costs through `mstpd` despite port-registration and rename races.

Load `palace`'s RAID module in the initrd. Record RouterOS and
RouterBOOT upgrades and validate port, carrier and switch outages.

Document the deployed architecture, interface handoffs and recovery
procedures. Add physical socket maps, NIC capacities and cable
connections alongside the logical topology and failover checks.
This commit is contained in:
2026-11-15 16:23:06 +00:00
parent b02948d826
commit a04d11423a
26 changed files with 2037 additions and 243 deletions
+21
View File
@@ -0,0 +1,21 @@
# Home network diagrams
`switch-ports.json` holds the socket inventory, NIC capacities and cable endpoints. Regenerate
`switch-panels.svg` and the cable table in `../switches.md` from the repository root:
```sh
python3 docs/sites/home/diagrams/render-switch-panels.py
```
The renderer uses only the Python standard library. Socket geometry and schematic cable routing
live in the renderer. Keep the inventory and routing together when adding a connection.
`home-fabric.mmd` is the Mermaid source for the logical fabric diagram. Render it with Mermaid
CLI (the checked-in SVG was rendered with Mermaid 11.12.0):
```sh
mmdc -i docs/sites/home/diagrams/home-fabric.mmd -o docs/sites/home/diagrams/home-fabric.svg
```
Check rendered SVGs visually after editing. Both diagrams are checked in so Markdown viewers
can show them without Mermaid support.
+14
View File
@@ -0,0 +1,14 @@
flowchart LR
virgin["Virgin Media modem"] --- shytzel["shytzel"]
ont["Digiweb ONT"] --- brian["brian"]
shytzel ---|"VLAN 130 trunk"| jim["jim"]
brian ---|"2 × 10G LAG"| dave["dave · RSTP root"]
brian -. "1G backup" .- jim
jim ---|"10G fabric trunk"| dave
dave ---|"100G"| palace["palace · river / cellar / sfh"]
jim ---|"1G host + separate 1G river trunk"| palace
dave ---|"100G"| castle["castle · NVMe-oF root"]
jim -. "1G · normally down" .- castle
dave ---|"10G LAN"| stream["stream"]
jim -. "1G LAN backup" .- stream
jim ---|"Separate VLAN 130 WAN handoff"| stream
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

@@ -0,0 +1,207 @@
#!/usr/bin/env python3
"""Render the rack panel map and cable table from switch-ports.json."""
import html
import json
from pathlib import Path
import re
import textwrap
ROOT = Path(__file__).resolve().parent
DATA = json.loads((ROOT / "switch-ports.json").read_text())
COLORS = ["#2563eb", "#7c3aed", "#d97706", "#0891b2", "#64748b", "#16a34a", "#db2777", "#dc2626", "#92400e", "#0f766e", "#4f46e5"]
TAGS = {}
POSITIONS = {}
foreground = []
for link, color in zip(DATA["links"], COLORS):
for end in ("from", "to"):
TAGS[tuple(link[end])] = (link["id"], color)
svg = ['<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1580" viewBox="0 0 1440 1580" role="img" aria-labelledby="title desc">',
'<title id="title">Home rack switch front panels and cable endpoints</title>',
'<desc id="desc">Stream is drawn above Brian but physically sits to its left. Brian above Jim above Dave, with palace several rack units below. Socket order follows the hardware; matching letter badges identify cable ends.</desc>',
'<style>text{font-family:system-ui,sans-serif;fill:#172033}.heading{font-weight:650;font-size:22px}.sub{fill:#526075;font-size:14px}.port{font-size:12px;font-weight:600}.small{font-size:11px}.mono{font-family:monospace}</style>']
def rect(x, y, w, h, fill, stroke="none", radius=5):
svg.append(f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="{radius}" fill="{fill}" stroke="{stroke}"/>')
def text(x, y, value, cls="", anchor="start", color=None):
style = f' style="fill:{color}"' if color else ""
svg.append(f'<text x="{x}" y="{y}" class="{cls}" text-anchor="{anchor}"{style}>{html.escape(value)}</text>')
def badge(x, y, tag, color):
rect(x - 10, y - 12, 20, 20, color, radius=4)
text(x, y + 2, tag, "port", "middle", "white")
def chassis(y, name, height, note):
rect(115, y, 1210, height, "#eef1f5", "#a8b2c1", 8)
text(140, y + 28, name, "heading")
text(1300, y + 27, note, "sub", "end")
def port(host, socket, x, y, width=46, height=27, label=True):
start = len(svg)
POSITIONS[(host, socket)] = (x, y, width, height)
p = next(p for p in DATA[host]["ports"] if p["socket"] == socket)
svg.append('<g><title>' + html.escape(f'{host} {socket}: {p["interface"]} — {p["role"]}') + '</title>')
tag, color = TAGS.get((host, socket), (None, "#64748b"))
rect(x - width / 2, y, width, height, "#fff", color, 3)
rect(x - width / 2 + 6, y + 5, width - 12, height - 10, "#28364a", radius=1)
text(x, y - 9, socket, "port mono", "middle")
if tag:
badge(x + width / 2 - 2, y - 9, tag, color)
if label:
for row, line in enumerate(textwrap.wrap(p["label"], width=8 if host == "jim" else 11)[:2]):
text(x, y + height + 15 + row * 12, line, "small", "middle")
svg.append('</g>')
foreground.extend(svg[start:])
del svg[start:]
rect(0, 0, 1440, 1580, "white", radius=0)
text(95, 38, "Home rack · physical socket map", "heading")
text(95, 64, "Front views, top to bottom. Socket positions follow the hardware; spacing and chassis widths are schematic.", "sub")
svg.append('<g transform="translate(0,330)">')
rect(330, -235, 780, 305, "#eef1f5", "#a8b2c1", 8)
text(350, -205, "stream · BROUNION R86S", "heading")
text(350, -180, "Physically left of brian; drawn above for cable routing", "sub")
text(350, -150, "DC / USB", "small")
for n, x in enumerate((600, 780, 960)):
port("stream", f"ETH{n}", x, -135, width=60)
text(x, -65, "Intel I225-V · 2.5G", "small", "middle")
text(x, -48, "1G connection" if n < 2 else "Unused", "small", "middle")
for socket, x in (("SFP+ L", 650), ("SFP+ R", 890)):
port("stream", socket, x, -12, width=70)
text(x, 53, "ConnectX-3 · 10G SFP+", "small", "middle")
# SFP captions sit below the narrow chassis to preserve the two-row socket layout.
for x in (93, 1347):
rect(x, 90, 9, 1080, "#dce2eb", radius=2)
for y in range(106, 1170, 24):
rect(x + 2, y, 5, 8, "white", radius=1)
chassis(100, "brian · USW-Pro-XG-8-PoE", 155, "8 × RJ45, then 2 × SFP+")
rect(205, 180, 10, 10, "#60a5fa", radius=5)
text(210, 218, "LED", "small", "middle")
for n in range(1, 9):
port("brian", str(n), 320 + (n - 1) * 75, 174, width=48)
for n in (9, 10):
port("brian", str(n), 1060 + (n - 9) * 120, 174, width=65)
chassis(340, "jim · CRS326-24G-2S+RM", 205, "3 banks of 8 RJ45 · even above odd · SFP+ at right")
rect(175, 425, 54, 29, "#28364a", "#94a3b8")
text(202, 410, "CONSOLE", "small", "middle")
for n in range(1, 25):
col = (n - 1) // 2
x = 285 + col * 59 + (col // 4) * 17
port("jim", str(n), x, 476 if n % 2 else 402, width=43, height=24)
port("jim", "S1", 1134, 445, width=54)
port("jim", "S2", 1235, 445, width=54)
chassis(630, "dave · CRS504-4XQ-IN", 165, "4 QSFP28 cages · console above management at right")
for x, label in ((175, "PSU 1"), (290, "PSU 2")):
rect(x, 680, 90, 78, "#d1d8e2", "#94a3b8")
text(x + 45, 725, label, "sub", "middle")
for n in range(1, 5):
x = 490 + (n - 1) * 140
if n == 3:
rect(x - 46, 695, 92, 29, "#fff", "#0891b2")
rect(x - 38, 701, 76, 17, "#28364a", radius=1)
text(x, 686, "Q3", "port mono", "middle")
text(x, 743, "4 × 10G breakout", "small", "middle")
svg.append(f'<path d="M{x} 757 V820" stroke="#0891b2" stroke-width="2" fill="none"/>')
else:
port("dave", f"Q{n}", x, 695, width=92)
rect(1095, 690, 54, 27, "#28364a", "#94a3b8")
text(1122, 681, "CONSOLE", "small", "middle")
port("dave", "MGMT", 1122, 741, width=54, height=24, label=False)
text(1235, 725, "DC / reset", "sub", "middle")
rect(430, 820, 820, 84, "#f4f8fc", "#b9cadb")
text(445, 841, "Q3 breakout lanes (one physical cage)", "sub")
for n in range(1, 5):
start = len(svg)
p = next(p for p in DATA["dave"]["ports"] if p["socket"] == f"Q3.{n}")
x = 485 + (n - 1) * 200
tag, color = TAGS.get(("dave", p["socket"]), (None, "#64748b"))
text(x, 870, p["socket"], "port mono")
if tag:
badge(x + 61, 866, tag, color)
text(x, 889, p["label"], "small")
rect(x + 83, 854, 34, 20, "white", color, radius=3)
rect(x + 89, 860, 22, 8, color, radius=1)
POSITIONS[("dave", p["socket"])] = (x + 100, 854, 34, 20)
foreground.extend(svg[start:])
del svg[start:]
text(720, 963, "⋮ several rack units ⋮", "sub", "middle")
chassis(1030, "palace", 160, "NIC endpoints only; rear-panel positions are not depicted")
for x, name in ((350, "uplink-dave"), (730, "host-jim"), (1110, "river-jim-phy")):
start = len(svg)
tag, color = TAGS[("palace", name)]
rect(x - 145, 1090, 290, 76, "white", color)
text(x - 118, 1120, name, "port mono")
badge(x + 119, 1114, tag, color)
spec = next(p for p in DATA["palace"]["ports"] if p["socket"] == name)
text(x, 1146, spec["nic"] + " · " + spec["capacity"], "small", "middle")
POSITIONS[("palace", name)] = (x, 1090, 290, 76)
foreground.extend(svg[start:])
del svg[start:]
def anchor(host, socket, side="bottom"):
x, y, w, h = POSITIONS[(host, socket)]
return {"top": (x, y), "bottom": (x, y + h),
"left": (x - w / 2, y + h / 2), "right": (x + w / 2, y + h / 2)}[side]
def cable(tag, points):
color = COLORS[ord(tag) - ord("A")]
points = " ".join(f"{x},{y}" for x, y in points)
svg.append(f'<polyline points="{points}" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>')
svg.append(f'<polyline points="{points}" fill="none" stroke="{color}" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>')
cable("A", [anchor("brian", "9"), (1060, 280), (38, 280), (38, 925),
(785, 925), anchor("dave", "Q3.2")])
cable("B", [anchor("brian", "10"), (1180, 300), (58, 300), (58, 950),
(1185, 950), anchor("dave", "Q3.4")])
cable("C", [anchor("brian", "5"), (620, 315), (492, 315), (492, 458),
(462, 458), anchor("jim", "7", "top")])
cable("D", [anchor("jim", "S1"), (1134, 575), (1394, 575), (1394, 975),
(585, 975), anchor("dave", "Q3.1")])
cable("E", [anchor("jim", "24", "right"), (1010, 414), (1010, 600),
(1380, 600), (1380, 753), anchor("dave", "MGMT", "right")])
cable("F", [anchor("jim", "5"), (403, 568), (1368, 568), (1368, 1010),
(730, 1010), anchor("palace", "host-jim", "top")])
cable("G", [anchor("jim", "22", "right"), (940, 414), (940, 590),
(1416, 590), (1416, 1025), (1110, 1025), anchor("palace", "river-jim-phy", "top")])
cable("H", [anchor("dave", "Q1"), (490, 790), (410, 790), (410, 1000),
(350, 1000), anchor("palace", "uplink-dave", "top")])
cable("I", [anchor("stream", "ETH0", "top"), (600, -160), (18, -160),
(18, 555), (898, 555), anchor("jim", "21")])
cable("J", [anchor("stream", "ETH1", "top"), (780, -170), (70, -170),
(70, 322), (403, 322), anchor("jim", "6", "top")])
cable("K", [anchor("stream", "SFP+ R"), (890, 80), (1428, 80),
(1428, 920), (985, 920), anchor("dave", "Q3.3")])
svg.extend(foreground)
text(95, 1220, "Matching letter badges identify cable ends. Port labels describe configured use; they do not indicate current link state.", "sub")
svg.append('</g></svg>')
(ROOT / "switch-panels.svg").write_text('\n'.join(svg) + '\n')
rows = ["| Cable | Endpoint | Endpoint | Connection |", "|---|---|---|---|"]
for link in DATA["links"]:
ends = [f'`{link[end][0]}` `{link[end][1]}`' for end in ("from", "to")]
rows.append(f'| **{link["id"]}** | {ends[0]} | {ends[1]} | {link["description"]} |')
page = ROOT.parent / "switches.md"
content = page.read_text()
start, end = "<!-- switch-cables -->", "<!-- /switch-cables -->"
if start in content:
content = re.sub(re.escape(start) + r'.*?' + re.escape(end),
start + '\n' + '\n'.join(rows) + '\n' + end, content, flags=re.S)
page.write_text(content)
+517
View File
@@ -0,0 +1,517 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1580" viewBox="0 0 1440 1580" role="img" aria-labelledby="title desc">
<title id="title">Home rack switch front panels and cable endpoints</title>
<desc id="desc">Stream is drawn above Brian but physically sits to its left. Brian above Jim above Dave, with palace several rack units below. Socket order follows the hardware; matching letter badges identify cable ends.</desc>
<style>text{font-family:system-ui,sans-serif;fill:#172033}.heading{font-weight:650;font-size:22px}.sub{fill:#526075;font-size:14px}.port{font-size:12px;font-weight:600}.small{font-size:11px}.mono{font-family:monospace}</style>
<rect x="0" y="0" width="1440" height="1580" rx="0" fill="white" stroke="none"/>
<text x="95" y="38" class="heading" text-anchor="start">Home rack · physical socket map</text>
<text x="95" y="64" class="sub" text-anchor="start">Front views, top to bottom. Socket positions follow the hardware; spacing and chassis widths are schematic.</text>
<g transform="translate(0,330)">
<rect x="330" y="-235" width="780" height="305" rx="8" fill="#eef1f5" stroke="#a8b2c1"/>
<text x="350" y="-205" class="heading" text-anchor="start">stream · BROUNION R86S</text>
<text x="350" y="-180" class="sub" text-anchor="start">Physically left of brian; drawn above for cable routing</text>
<text x="350" y="-150" class="small" text-anchor="start">DC / USB</text>
<text x="600" y="-65" class="small" text-anchor="middle">Intel I225-V · 2.5G</text>
<text x="600" y="-48" class="small" text-anchor="middle">1G connection</text>
<text x="780" y="-65" class="small" text-anchor="middle">Intel I225-V · 2.5G</text>
<text x="780" y="-48" class="small" text-anchor="middle">1G connection</text>
<text x="960" y="-65" class="small" text-anchor="middle">Intel I225-V · 2.5G</text>
<text x="960" y="-48" class="small" text-anchor="middle">Unused</text>
<text x="650" y="53" class="small" text-anchor="middle">ConnectX-3 · 10G SFP+</text>
<text x="890" y="53" class="small" text-anchor="middle">ConnectX-3 · 10G SFP+</text>
<rect x="93" y="90" width="9" height="1080" rx="2" fill="#dce2eb" stroke="none"/>
<rect x="95" y="106" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="130" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="154" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="178" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="202" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="226" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="250" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="274" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="298" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="322" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="346" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="370" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="394" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="418" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="442" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="466" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="490" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="514" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="538" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="562" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="586" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="610" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="634" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="658" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="682" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="706" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="730" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="754" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="778" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="802" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="826" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="850" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="874" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="898" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="922" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="946" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="970" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="994" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1018" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1042" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1066" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1090" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1114" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1138" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="95" y="1162" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1347" y="90" width="9" height="1080" rx="2" fill="#dce2eb" stroke="none"/>
<rect x="1349" y="106" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="130" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="154" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="178" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="202" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="226" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="250" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="274" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="298" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="322" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="346" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="370" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="394" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="418" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="442" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="466" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="490" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="514" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="538" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="562" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="586" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="610" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="634" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="658" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="682" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="706" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="730" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="754" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="778" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="802" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="826" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="850" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="874" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="898" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="922" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="946" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="970" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="994" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1018" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1042" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1066" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1090" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1114" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1138" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="1349" y="1162" width="5" height="8" rx="1" fill="white" stroke="none"/>
<rect x="115" y="100" width="1210" height="155" rx="8" fill="#eef1f5" stroke="#a8b2c1"/>
<text x="140" y="128" class="heading" text-anchor="start">brian · USW-Pro-XG-8-PoE</text>
<text x="1300" y="127" class="sub" text-anchor="end">8 × RJ45, then 2 × SFP+</text>
<rect x="205" y="180" width="10" height="10" rx="5" fill="#60a5fa" stroke="none"/>
<text x="210" y="218" class="small" text-anchor="middle">LED</text>
<rect x="115" y="340" width="1210" height="205" rx="8" fill="#eef1f5" stroke="#a8b2c1"/>
<text x="140" y="368" class="heading" text-anchor="start">jim · CRS326-24G-2S+RM</text>
<text x="1300" y="367" class="sub" text-anchor="end">3 banks of 8 RJ45 · even above odd · SFP+ at right</text>
<rect x="175" y="425" width="54" height="29" rx="5" fill="#28364a" stroke="#94a3b8"/>
<text x="202" y="410" class="small" text-anchor="middle">CONSOLE</text>
<rect x="115" y="630" width="1210" height="165" rx="8" fill="#eef1f5" stroke="#a8b2c1"/>
<text x="140" y="658" class="heading" text-anchor="start">dave · CRS504-4XQ-IN</text>
<text x="1300" y="657" class="sub" text-anchor="end">4 QSFP28 cages · console above management at right</text>
<rect x="175" y="680" width="90" height="78" rx="5" fill="#d1d8e2" stroke="#94a3b8"/>
<text x="220" y="725" class="sub" text-anchor="middle">PSU 1</text>
<rect x="290" y="680" width="90" height="78" rx="5" fill="#d1d8e2" stroke="#94a3b8"/>
<text x="335" y="725" class="sub" text-anchor="middle">PSU 2</text>
<rect x="724" y="695" width="92" height="29" rx="5" fill="#fff" stroke="#0891b2"/>
<rect x="732" y="701" width="76" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="770" y="686" class="port mono" text-anchor="middle">Q3</text>
<text x="770" y="743" class="small" text-anchor="middle">4 × 10G breakout</text>
<path d="M770 757 V820" stroke="#0891b2" stroke-width="2" fill="none"/>
<rect x="1095" y="690" width="54" height="27" rx="5" fill="#28364a" stroke="#94a3b8"/>
<text x="1122" y="681" class="small" text-anchor="middle">CONSOLE</text>
<text x="1235" y="725" class="sub" text-anchor="middle">DC / reset</text>
<rect x="430" y="820" width="820" height="84" rx="5" fill="#f4f8fc" stroke="#b9cadb"/>
<text x="445" y="841" class="sub" text-anchor="start">Q3 breakout lanes (one physical cage)</text>
<text x="720" y="963" class="sub" text-anchor="middle">⋮ several rack units ⋮</text>
<rect x="115" y="1030" width="1210" height="160" rx="8" fill="#eef1f5" stroke="#a8b2c1"/>
<text x="140" y="1058" class="heading" text-anchor="start">palace</text>
<text x="1300" y="1057" class="sub" text-anchor="end">NIC endpoints only; rear-panel positions are not depicted</text>
<polyline points="1060,201 1060,280 38,280 38,925 785,925 785,874" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="1060,201 1060,280 38,280 38,925 785,925 785,874" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="1180,201 1180,300 58,300 58,950 1185,950 1185,874" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="1180,201 1180,300 58,300 58,950 1185,950 1185,874" fill="none" stroke="#7c3aed" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="620,201 620,315 492,315 492,458 462,458 462,476" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="620,201 620,315 492,315 492,458 462,458 462,476" fill="none" stroke="#d97706" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="1134,472 1134,575 1394,575 1394,975 585,975 585,874" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="1134,472 1134,575 1394,575 1394,975 585,975 585,874" fill="none" stroke="#0891b2" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="989.5,414.0 1010,414 1010,600 1380,600 1380,753 1149.0,753.0" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="989.5,414.0 1010,414 1010,600 1380,600 1380,753 1149.0,753.0" fill="none" stroke="#64748b" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="403,500 403,568 1368,568 1368,1010 730,1010 730,1090" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="403,500 403,568 1368,568 1368,1010 730,1010 730,1090" fill="none" stroke="#16a34a" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="930.5,414.0 940,414 940,590 1416,590 1416,1025 1110,1025 1110,1090" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="930.5,414.0 940,414 940,590 1416,590 1416,1025 1110,1025 1110,1090" fill="none" stroke="#db2777" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="490,722 490,790 410,790 410,1000 350,1000 350,1090" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="490,722 490,790 410,790 410,1000 350,1000 350,1090" fill="none" stroke="#dc2626" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="600,-135 600,-160 18,-160 18,555 898,555 909,500" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="600,-135 600,-160 18,-160 18,555 898,555 909,500" fill="none" stroke="#92400e" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="780,-135 780,-170 70,-170 70,322 403,322 403,402" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="780,-135 780,-170 70,-170 70,322 403,322 403,402" fill="none" stroke="#0f766e" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="890,15 890,80 1428,80 1428,920 985,920 985,874" fill="none" stroke="white" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<polyline points="890,15 890,80 1428,80 1428,920 985,920 985,874" fill="none" stroke="#4f46e5" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<g><title>stream ETH0: wan — 1G connection to jim 21</title>
<rect x="570.0" y="-135" width="60" height="27" rx="3" fill="#fff" stroke="#92400e"/>
<rect x="576.0" y="-130" width="48" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="600" y="-144" class="port mono" text-anchor="middle">ETH0</text>
<rect x="618.0" y="-156" width="20" height="20" rx="4" fill="#92400e" stroke="none"/>
<text x="628.0" y="-142" class="port" text-anchor="middle" style="fill:white">I</text>
<text x="600" y="-93" class="small" text-anchor="middle">wan</text>
</g>
<g><title>stream ETH1: lan-jim — 1G connection to jim 6</title>
<rect x="750.0" y="-135" width="60" height="27" rx="3" fill="#fff" stroke="#0f766e"/>
<rect x="756.0" y="-130" width="48" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="780" y="-144" class="port mono" text-anchor="middle">ETH1</text>
<rect x="798.0" y="-156" width="20" height="20" rx="4" fill="#0f766e" stroke="none"/>
<text x="808.0" y="-142" class="port" text-anchor="middle" style="fill:white">J</text>
<text x="780" y="-93" class="small" text-anchor="middle">lan-jim</text>
</g>
<g><title>stream ETH2: et2 — Unused</title>
<rect x="930.0" y="-135" width="60" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="936.0" y="-130" width="48" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="960" y="-144" class="port mono" text-anchor="middle">ETH2</text>
<text x="960" y="-93" class="small" text-anchor="middle">et2</text>
</g>
<g><title>stream SFP+ L: et5 — Unused</title>
<rect x="615.0" y="-12" width="70" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="621.0" y="-7" width="58" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="650" y="-21" class="port mono" text-anchor="middle">SFP+ L</text>
<text x="650" y="30" class="small" text-anchor="middle">et5</text>
</g>
<g><title>stream SFP+ R: lan-dave — 10G connection to dave Q3.3</title>
<rect x="855.0" y="-12" width="70" height="27" rx="3" fill="#fff" stroke="#4f46e5"/>
<rect x="861.0" y="-7" width="58" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="890" y="-21" class="port mono" text-anchor="middle">SFP+ R</text>
<rect x="913.0" y="-33" width="20" height="20" rx="4" fill="#4f46e5" stroke="none"/>
<text x="923.0" y="-19" class="port" text-anchor="middle" style="fill:white">K</text>
<text x="890" y="30" class="small" text-anchor="middle">lan-dave</text>
</g>
<g><title>brian 1: Port 1 — Configured port label</title>
<rect x="296.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="302.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="320" y="165" class="port mono" text-anchor="middle">1</text>
<text x="320" y="216" class="small" text-anchor="middle">fort</text>
</g>
<g><title>brian 2: Port 2 — Configured port label</title>
<rect x="371.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="377.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="395" y="165" class="port mono" text-anchor="middle">2</text>
<text x="395" y="216" class="small" text-anchor="middle">castle</text>
</g>
<g><title>brian 3: Port 3 — portcullis test connection</title>
<rect x="446.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="452.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="470" y="165" class="port mono" text-anchor="middle">3</text>
<text x="470" y="216" class="small" text-anchor="middle">portcullis</text>
<text x="470" y="228" class="small" text-anchor="middle">test</text>
</g>
<g><title>brian 4: Port 4 — Second JetKVM</title>
<rect x="521.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="527.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="545" y="165" class="port mono" text-anchor="middle">4</text>
<text x="545" y="216" class="small" text-anchor="middle">portcullis</text>
<text x="545" y="228" class="small" text-anchor="middle">KVM</text>
</g>
<g><title>brian 5: Port 5 — Backup fabric trunk</title>
<rect x="596.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#d97706"/>
<rect x="602.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="620" y="165" class="port mono" text-anchor="middle">5</text>
<rect x="632.0" y="153" width="20" height="20" rx="4" fill="#d97706" stroke="none"/>
<text x="642.0" y="167" class="port" text-anchor="middle" style="fill:white">C</text>
<text x="620" y="216" class="small" text-anchor="middle">jim P7</text>
</g>
<g><title>brian 6: Port 6 — Native VLAN 140; tagged VLAN 10</title>
<rect x="671.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="677.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="695" y="165" class="port mono" text-anchor="middle">6</text>
<text x="695" y="216" class="small" text-anchor="middle">Digiweb ONT</text>
</g>
<g><title>brian 7: Port 7 — AP trunk</title>
<rect x="746.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="752.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="770" y="165" class="port mono" text-anchor="middle">7</text>
<text x="770" y="216" class="small" text-anchor="middle">wave</text>
</g>
<g><title>brian 8: Port 8 — AP trunk</title>
<rect x="821.0" y="174" width="48" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="827.0" y="179" width="36" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="845" y="165" class="port mono" text-anchor="middle">8</text>
<text x="845" y="216" class="small" text-anchor="middle">vibe</text>
</g>
<g><title>brian 9: SFP+ 1 — LAG member 1</title>
<rect x="1027.5" y="174" width="65" height="27" rx="3" fill="#fff" stroke="#2563eb"/>
<rect x="1033.5" y="179" width="53" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="1060" y="165" class="port mono" text-anchor="middle">9</text>
<rect x="1080.5" y="153" width="20" height="20" rx="4" fill="#2563eb" stroke="none"/>
<text x="1090.5" y="167" class="port" text-anchor="middle" style="fill:white">A</text>
<text x="1060" y="216" class="small" text-anchor="middle">dave Q3.2</text>
</g>
<g><title>brian 10: SFP+ 2 — LAG member 2</title>
<rect x="1147.5" y="174" width="65" height="27" rx="3" fill="#fff" stroke="#7c3aed"/>
<rect x="1153.5" y="179" width="53" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="1180" y="165" class="port mono" text-anchor="middle">10</text>
<rect x="1200.5" y="153" width="20" height="20" rx="4" fill="#7c3aed" stroke="none"/>
<text x="1210.5" y="167" class="port" text-anchor="middle" style="fill:white">B</text>
<text x="1180" y="216" class="small" text-anchor="middle">dave Q3.4</text>
</g>
<g><title>jim 1: ether1 — Configured member of shytzel-downlink</title>
<rect x="263.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="269.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="285" y="467" class="port mono" text-anchor="middle">1</text>
<text x="285" y="515" class="small" text-anchor="middle">shytzel</text>
<text x="285" y="527" class="small" text-anchor="middle">LAG</text>
</g>
<g><title>jim 2: ether2 — Configured member of shytzel-downlink</title>
<rect x="263.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="269.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="285" y="393" class="port mono" text-anchor="middle">2</text>
<text x="285" y="441" class="small" text-anchor="middle">shytzel</text>
<text x="285" y="453" class="small" text-anchor="middle">LAG</text>
</g>
<g><title>jim 3: ether3 — Configured member of shytzel-downlink</title>
<rect x="322.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="328.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="344" y="467" class="port mono" text-anchor="middle">3</text>
<text x="344" y="515" class="small" text-anchor="middle">shytzel</text>
<text x="344" y="527" class="small" text-anchor="middle">LAG</text>
</g>
<g><title>jim 4: ether4 — Configured member of shytzel-downlink</title>
<rect x="322.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="328.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="344" y="393" class="port mono" text-anchor="middle">4</text>
<text x="344" y="441" class="small" text-anchor="middle">shytzel</text>
<text x="344" y="453" class="small" text-anchor="middle">LAG</text>
</g>
<g><title>jim 5: palace — Core / netboot trunk</title>
<rect x="381.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#16a34a"/>
<rect x="387.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="403" y="467" class="port mono" text-anchor="middle">5</text>
<rect x="412.5" y="455" width="20" height="20" rx="4" fill="#16a34a" stroke="none"/>
<text x="422.5" y="469" class="port" text-anchor="middle" style="fill:white">F</text>
<text x="403" y="515" class="small" text-anchor="middle">palace</text>
<text x="403" y="527" class="small" text-anchor="middle">host</text>
</g>
<g><title>jim 6: stream — Backup RSTP trunk</title>
<rect x="381.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#0f766e"/>
<rect x="387.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="403" y="393" class="port mono" text-anchor="middle">6</text>
<rect x="412.5" y="381" width="20" height="20" rx="4" fill="#0f766e" stroke="none"/>
<text x="422.5" y="395" class="port" text-anchor="middle" style="fill:white">J</text>
<text x="403" y="441" class="small" text-anchor="middle">stream</text>
<text x="403" y="453" class="small" text-anchor="middle">LAN</text>
</g>
<g><title>jim 7: brian-downlink — Backup fabric trunk</title>
<rect x="440.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#d97706"/>
<rect x="446.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="462" y="467" class="port mono" text-anchor="middle">7</text>
<rect x="471.5" y="455" width="20" height="20" rx="4" fill="#d97706" stroke="none"/>
<text x="481.5" y="469" class="port" text-anchor="middle" style="fill:white">C</text>
<text x="462" y="515" class="small" text-anchor="middle">brian P5</text>
</g>
<g><title>jim 8: palace-kvm — lo access</title>
<rect x="440.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="446.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="462" y="393" class="port mono" text-anchor="middle">8</text>
<text x="462" y="441" class="small" text-anchor="middle">JetKVM</text>
</g>
<g><title>jim 9: ether9 — Unbridged spare</title>
<rect x="516.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="522.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="538" y="467" class="port mono" text-anchor="middle">9</text>
<text x="538" y="515" class="small" text-anchor="middle">spare</text>
</g>
<g><title>jim 10: castle — Backup attachment, normally down</title>
<rect x="516.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="522.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="538" y="393" class="port mono" text-anchor="middle">10</text>
<text x="538" y="441" class="small" text-anchor="middle">castle</text>
</g>
<g><title>jim 11: fort — lo access (configured label)</title>
<rect x="575.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="581.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="597" y="467" class="port mono" text-anchor="middle">11</text>
<text x="597" y="515" class="small" text-anchor="middle">fort</text>
</g>
<g><title>jim 12: laptop-dock — lo access (configured label)</title>
<rect x="575.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="581.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="597" y="393" class="port mono" text-anchor="middle">12</text>
<text x="597" y="441" class="small" text-anchor="middle">dock</text>
</g>
<g><title>jim 13: pronter — lo access (configured label)</title>
<rect x="634.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="640.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="656" y="467" class="port mono" text-anchor="middle">13</text>
<text x="656" y="515" class="small" text-anchor="middle">pronter</text>
</g>
<g><title>jim 14: untrusted-sta1 — Untrusted access</title>
<rect x="634.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="640.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="656" y="393" class="port mono" text-anchor="middle">14</text>
<text x="656" y="441" class="small" text-anchor="middle">guest</text>
</g>
<g><title>jim 15: ether15 — lo access; peer unconfirmed</title>
<rect x="693.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="699.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="715" y="467" class="port mono" text-anchor="middle">15</text>
<text x="715" y="515" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 16: ether16 — lo access; peer unconfirmed</title>
<rect x="693.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="699.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="715" y="393" class="port mono" text-anchor="middle">16</text>
<text x="715" y="441" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 17: ether17 — lo access; peer unconfirmed</title>
<rect x="769.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="775.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="791" y="467" class="port mono" text-anchor="middle">17</text>
<text x="791" y="515" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 18: ether18 — lo access; peer unconfirmed</title>
<rect x="769.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="775.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="791" y="393" class="port mono" text-anchor="middle">18</text>
<text x="791" y="441" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 19: ether19 — lo access; peer unconfirmed</title>
<rect x="828.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="834.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="850" y="467" class="port mono" text-anchor="middle">19</text>
<text x="850" y="515" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 20: ether20 — lo access; peer unconfirmed</title>
<rect x="828.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="834.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="850" y="393" class="port mono" text-anchor="middle">20</text>
<text x="850" y="441" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>jim 21: stream-wan — Untagged VLAN 130 handoff</title>
<rect x="887.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#92400e"/>
<rect x="893.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="909" y="467" class="port mono" text-anchor="middle">21</text>
<rect x="918.5" y="455" width="20" height="20" rx="4" fill="#92400e" stroke="none"/>
<text x="928.5" y="469" class="port" text-anchor="middle" style="fill:white">I</text>
<text x="909" y="515" class="small" text-anchor="middle">stream</text>
<text x="909" y="527" class="small" text-anchor="middle">WAN</text>
</g>
<g><title>jim 22: river — Dedicated router trunk</title>
<rect x="887.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#db2777"/>
<rect x="893.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="909" y="393" class="port mono" text-anchor="middle">22</text>
<rect x="918.5" y="381" width="20" height="20" rx="4" fill="#db2777" stroke="none"/>
<text x="928.5" y="395" class="port" text-anchor="middle" style="fill:white">G</text>
<text x="909" y="441" class="small" text-anchor="middle">river</text>
<text x="909" y="453" class="small" text-anchor="middle">backup</text>
</g>
<g><title>jim 23: ups — lo access</title>
<rect x="946.5" y="476" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="952.5" y="481" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="968" y="467" class="port mono" text-anchor="middle">23</text>
<text x="968" y="515" class="small" text-anchor="middle">UPS</text>
</g>
<g><title>jim 24: dave-management — Core management</title>
<rect x="946.5" y="402" width="43" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="952.5" y="407" width="31" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="968" y="393" class="port mono" text-anchor="middle">24</text>
<rect x="977.5" y="381" width="20" height="20" rx="4" fill="#64748b" stroke="none"/>
<text x="987.5" y="395" class="port" text-anchor="middle" style="fill:white">E</text>
<text x="968" y="441" class="small" text-anchor="middle">dave</text>
<text x="968" y="453" class="small" text-anchor="middle">mgmt</text>
</g>
<g><title>jim S1: dave-uplink — 10G fabric trunk</title>
<rect x="1107.0" y="445" width="54" height="27" rx="3" fill="#fff" stroke="#0891b2"/>
<rect x="1113.0" y="450" width="42" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="1134" y="436" class="port mono" text-anchor="middle">S1</text>
<rect x="1149.0" y="424" width="20" height="20" rx="4" fill="#0891b2" stroke="none"/>
<text x="1159.0" y="438" class="port" text-anchor="middle" style="fill:white">D</text>
<text x="1134" y="487" class="small" text-anchor="middle">dave</text>
<text x="1134" y="499" class="small" text-anchor="middle">Q3.1</text>
</g>
<g><title>jim S2: sfp-spare — 10G trunk; colony staging</title>
<rect x="1208.0" y="445" width="54" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="1214.0" y="450" width="42" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="1235" y="436" class="port mono" text-anchor="middle">S2</text>
<text x="1235" y="487" class="small" text-anchor="middle">fergal</text>
</g>
<g><title>dave Q1: palace — 100G; whole cage</title>
<rect x="444.0" y="695" width="92" height="27" rx="3" fill="#fff" stroke="#dc2626"/>
<rect x="450.0" y="700" width="80" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="490" y="686" class="port mono" text-anchor="middle">Q1</text>
<rect x="524.0" y="674" width="20" height="20" rx="4" fill="#dc2626" stroke="none"/>
<text x="534.0" y="688" class="port" text-anchor="middle" style="fill:white">H</text>
<text x="490" y="737" class="small" text-anchor="middle">palace</text>
</g>
<g><title>dave Q2: castle — 100G; whole cage</title>
<rect x="584.0" y="695" width="92" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="590.0" y="700" width="80" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="630" y="686" class="port mono" text-anchor="middle">Q2</text>
<text x="630" y="737" class="small" text-anchor="middle">castle</text>
</g>
<g><title>dave Q4: qsfp28-4-1 — No identified peer</title>
<rect x="864.0" y="695" width="92" height="27" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="870.0" y="700" width="80" height="17" rx="1" fill="#28364a" stroke="none"/>
<text x="910" y="686" class="port mono" text-anchor="middle">Q4</text>
<text x="910" y="737" class="small" text-anchor="middle">unmapped</text>
</g>
<g><title>dave MGMT: management — 100M management RJ45</title>
<rect x="1095.0" y="741" width="54" height="24" rx="3" fill="#fff" stroke="#64748b"/>
<rect x="1101.0" y="746" width="42" height="14" rx="1" fill="#28364a" stroke="none"/>
<text x="1122" y="732" class="port mono" text-anchor="middle">MGMT</text>
<rect x="1137.0" y="720" width="20" height="20" rx="4" fill="#64748b" stroke="none"/>
<text x="1147.0" y="734" class="port" text-anchor="middle" style="fill:white">E</text>
</g>
<text x="485" y="870" class="port mono" text-anchor="start">Q3.1</text>
<rect x="536" y="854" width="20" height="20" rx="4" fill="#0891b2" stroke="none"/>
<text x="546" y="868" class="port" text-anchor="middle" style="fill:white">D</text>
<text x="485" y="889" class="small" text-anchor="start">jim SFP+1</text>
<rect x="568" y="854" width="34" height="20" rx="3" fill="white" stroke="#0891b2"/>
<rect x="574" y="860" width="22" height="8" rx="1" fill="#0891b2" stroke="none"/>
<text x="685" y="870" class="port mono" text-anchor="start">Q3.2</text>
<rect x="736" y="854" width="20" height="20" rx="4" fill="#2563eb" stroke="none"/>
<text x="746" y="868" class="port" text-anchor="middle" style="fill:white">A</text>
<text x="685" y="889" class="small" text-anchor="start">brian SFP+1</text>
<rect x="768" y="854" width="34" height="20" rx="3" fill="white" stroke="#2563eb"/>
<rect x="774" y="860" width="22" height="8" rx="1" fill="#2563eb" stroke="none"/>
<text x="885" y="870" class="port mono" text-anchor="start">Q3.3</text>
<rect x="936" y="854" width="20" height="20" rx="4" fill="#4f46e5" stroke="none"/>
<text x="946" y="868" class="port" text-anchor="middle" style="fill:white">K</text>
<text x="885" y="889" class="small" text-anchor="start">stream LAN</text>
<rect x="968" y="854" width="34" height="20" rx="3" fill="white" stroke="#4f46e5"/>
<rect x="974" y="860" width="22" height="8" rx="1" fill="#4f46e5" stroke="none"/>
<text x="1085" y="870" class="port mono" text-anchor="start">Q3.4</text>
<rect x="1136" y="854" width="20" height="20" rx="4" fill="#7c3aed" stroke="none"/>
<text x="1146" y="868" class="port" text-anchor="middle" style="fill:white">B</text>
<text x="1085" y="889" class="small" text-anchor="start">brian SFP+2</text>
<rect x="1168" y="854" width="34" height="20" rx="3" fill="white" stroke="#7c3aed"/>
<rect x="1174" y="860" width="22" height="8" rx="1" fill="#7c3aed" stroke="none"/>
<rect x="205" y="1090" width="290" height="76" rx="5" fill="white" stroke="#dc2626"/>
<text x="232" y="1120" class="port mono" text-anchor="start">uplink-dave</text>
<rect x="459" y="1102" width="20" height="20" rx="4" fill="#dc2626" stroke="none"/>
<text x="469" y="1116" class="port" text-anchor="middle" style="fill:white">H</text>
<text x="350" y="1146" class="small" text-anchor="middle">Mellanox ConnectX-4 · 100G QSFP28</text>
<rect x="585" y="1090" width="290" height="76" rx="5" fill="white" stroke="#16a34a"/>
<text x="612" y="1120" class="port mono" text-anchor="start">host-jim</text>
<rect x="839" y="1102" width="20" height="20" rx="4" fill="#16a34a" stroke="none"/>
<text x="849" y="1116" class="port" text-anchor="middle" style="fill:white">F</text>
<text x="730" y="1146" class="small" text-anchor="middle">Intel I211 · 1G RJ45</text>
<rect x="965" y="1090" width="290" height="76" rx="5" fill="white" stroke="#db2777"/>
<text x="992" y="1120" class="port mono" text-anchor="start">river-jim-phy</text>
<rect x="1219" y="1102" width="20" height="20" rx="4" fill="#db2777" stroke="none"/>
<text x="1229" y="1116" class="port" text-anchor="middle" style="fill:white">G</text>
<text x="1110" y="1146" class="small" text-anchor="middle">Intel I211 · 1G RJ45</text>
<text x="95" y="1220" class="sub" text-anchor="start">Matching letter badges identify cable ends. Port labels describe configured use; they do not indicate current link state.</text>
</g></svg>

After

Width:  |  Height:  |  Size: 38 KiB

+608
View File
@@ -0,0 +1,608 @@
{
"view": "Front view; rack order is brian, jim, dave, then palace several U below. Socket order is physical; spacing and chassis widths are schematic. Stream sits physically left of brian and is drawn above it.",
"sources": {
"brian": "https://dl.ui.com/qig/usw-pro-xg-8-poe/",
"jim": "https://mikrotik.com/product/CRS326-24G-2SplusRM",
"dave": "https://mikrotik.com/product/crs504_4xq_in",
"stream": "https://www.gowinfanless.com/news/blogs/the-r86s-revolution-low-power-2-5gbe-and-10gbe-networking"
},
"brian": {
"model": "USW-Pro-XG-8-PoE",
"ports": [
{
"socket": "1",
"interface": "Port 1",
"label": "fort",
"role": "Configured port label",
"peer": "fort",
"peer_port": null
},
{
"socket": "2",
"interface": "Port 2",
"label": "castle",
"role": "Configured port label",
"peer": "castle",
"peer_port": null
},
{
"socket": "3",
"interface": "Port 3",
"label": "portcullis test",
"role": "portcullis test connection",
"peer": "portcullis",
"peer_port": null
},
{
"socket": "4",
"interface": "Port 4",
"label": "portcullis KVM",
"role": "Second JetKVM",
"peer": "portcullis-kvm",
"peer_port": null
},
{
"socket": "5",
"interface": "Port 5",
"label": "jim P7",
"role": "Backup fabric trunk",
"peer": "jim",
"peer_port": "7"
},
{
"socket": "6",
"interface": "Port 6",
"label": "Digiweb ONT",
"role": "Native VLAN 140; tagged VLAN 10",
"peer": "Digiweb ONT",
"peer_port": null
},
{
"socket": "7",
"interface": "Port 7",
"label": "wave",
"role": "AP trunk",
"peer": "wave",
"peer_port": "eth0"
},
{
"socket": "8",
"interface": "Port 8",
"label": "vibe",
"role": "AP trunk",
"peer": "vibe",
"peer_port": "ether1"
},
{
"socket": "9",
"interface": "SFP+ 1",
"label": "dave Q3.2",
"role": "LAG member 1",
"peer": "dave",
"peer_port": "Q3.2"
},
{
"socket": "10",
"interface": "SFP+ 2",
"label": "dave Q3.4",
"role": "LAG member 2",
"peer": "dave",
"peer_port": "Q3.4"
}
]
},
"jim": {
"model": "CRS326-24G-2S+RM",
"ports": [
{
"socket": "1",
"interface": "ether1",
"default_name": "ether1",
"label": "shytzel LAG",
"role": "Configured member of shytzel-downlink",
"peer": "shytzel",
"peer_port": null
},
{
"socket": "2",
"interface": "ether2",
"default_name": "ether2",
"label": "shytzel LAG",
"role": "Configured member of shytzel-downlink",
"peer": "shytzel",
"peer_port": null
},
{
"socket": "3",
"interface": "ether3",
"default_name": "ether3",
"label": "shytzel LAG",
"role": "Configured member of shytzel-downlink",
"peer": "shytzel",
"peer_port": null
},
{
"socket": "4",
"interface": "ether4",
"default_name": "ether4",
"label": "shytzel LAG",
"role": "Configured member of shytzel-downlink",
"peer": "shytzel",
"peer_port": null
},
{
"socket": "5",
"interface": "palace",
"default_name": "ether5",
"label": "palace host",
"role": "Core / netboot trunk",
"peer": "palace",
"peer_port": "host-jim"
},
{
"socket": "6",
"interface": "stream",
"default_name": "ether6",
"label": "stream LAN",
"role": "Backup RSTP trunk",
"peer": "stream",
"peer_port": "lan-jim"
},
{
"socket": "7",
"interface": "brian-downlink",
"default_name": "ether7",
"label": "brian P5",
"role": "Backup fabric trunk",
"peer": "brian",
"peer_port": "RJ45 5"
},
{
"socket": "8",
"interface": "palace-kvm",
"default_name": "ether8",
"label": "JetKVM",
"role": "lo access",
"peer": "palace-kvm",
"peer_port": null
},
{
"socket": "9",
"interface": "ether9",
"default_name": "ether9",
"label": "spare",
"role": "Unbridged spare",
"peer": null,
"peer_port": null
},
{
"socket": "10",
"interface": "castle",
"default_name": "ether10",
"label": "castle",
"role": "Backup attachment, normally down",
"peer": "castle",
"peer_port": "et2.5g"
},
{
"socket": "11",
"interface": "fort",
"default_name": "ether11",
"label": "fort",
"role": "lo access (configured label)",
"peer": "fort",
"peer_port": null
},
{
"socket": "12",
"interface": "laptop-dock",
"default_name": "ether12",
"label": "dock",
"role": "lo access (configured label)",
"peer": "laptop-dock",
"peer_port": null
},
{
"socket": "13",
"interface": "pronter",
"default_name": "ether13",
"label": "pronter",
"role": "lo access (configured label)",
"peer": "pronter",
"peer_port": null
},
{
"socket": "14",
"interface": "untrusted-sta1",
"default_name": "ether14",
"label": "guest",
"role": "Untrusted access",
"peer": "untrusted-sta1",
"peer_port": null
},
{
"socket": "15",
"interface": "ether15",
"default_name": "ether15",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "16",
"interface": "ether16",
"default_name": "ether16",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "17",
"interface": "ether17",
"default_name": "ether17",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "18",
"interface": "ether18",
"default_name": "ether18",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "19",
"interface": "ether19",
"default_name": "ether19",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "20",
"interface": "ether20",
"default_name": "ether20",
"label": "unmapped",
"role": "lo access; peer unconfirmed",
"peer": null,
"peer_port": null
},
{
"socket": "21",
"interface": "stream-wan",
"default_name": "ether21",
"label": "stream WAN",
"role": "Untagged VLAN 130 handoff",
"peer": "stream",
"peer_port": "wan"
},
{
"socket": "22",
"interface": "river",
"default_name": "ether22",
"label": "river backup",
"role": "Dedicated router trunk",
"peer": "palace",
"peer_port": "river-jim-phy"
},
{
"socket": "23",
"interface": "ups",
"default_name": "ether23",
"label": "UPS",
"role": "lo access",
"peer": "ups",
"peer_port": null
},
{
"socket": "24",
"interface": "dave-management",
"default_name": "ether24",
"label": "dave mgmt",
"role": "Core management",
"peer": "dave",
"peer_port": "MGMT"
},
{
"socket": "S1",
"interface": "dave-uplink",
"default_name": "sfp-sfpplus1",
"label": "dave Q3.1",
"role": "10G fabric trunk",
"peer": "dave",
"peer_port": "Q3.1"
},
{
"socket": "S2",
"interface": "sfp-spare",
"default_name": "sfp-sfpplus2",
"label": "fergal",
"role": "10G trunk; colony staging",
"peer": "fergal",
"peer_port": "lan1"
}
]
},
"dave": {
"model": "CRS504-4XQ-IN",
"ports": [
{
"socket": "Q1",
"interface": "palace",
"default_name": "qsfp28-1-1",
"label": "palace",
"role": "100G; whole cage",
"peer": "palace",
"peer_port": "uplink-dave"
},
{
"socket": "Q2",
"interface": "castle",
"default_name": "qsfp28-2-1",
"label": "castle",
"role": "100G; whole cage",
"peer": "castle",
"peer_port": "et100g"
},
{
"socket": "Q3.1",
"interface": "jim-downlink",
"default_name": "qsfp28-3-1",
"label": "jim SFP+1",
"role": "10G breakout lane 1",
"peer": "jim",
"peer_port": "S1"
},
{
"socket": "Q3.2",
"interface": "brian1",
"default_name": "qsfp28-3-2",
"label": "brian SFP+1",
"role": "10G breakout lane 2; LAG",
"peer": "brian",
"peer_port": "9"
},
{
"socket": "Q3.3",
"interface": "stream",
"default_name": "qsfp28-3-3",
"label": "stream LAN",
"role": "10G breakout lane 3",
"peer": "stream",
"peer_port": "lan-dave"
},
{
"socket": "Q3.4",
"interface": "brian2",
"default_name": "qsfp28-3-4",
"label": "brian SFP+2",
"role": "10G breakout lane 4; LAG",
"peer": "brian",
"peer_port": "10"
},
{
"socket": "Q4",
"interface": "qsfp28-4-1",
"default_name": "qsfp28-4-1",
"label": "unmapped",
"role": "No identified peer",
"peer": null,
"peer_port": null
},
{
"socket": "MGMT",
"interface": "management",
"default_name": "ether1",
"label": "jim P24",
"role": "100M management RJ45",
"peer": "jim",
"peer_port": "24"
}
]
},
"links": [
{
"id": "A",
"from": [
"brian",
"9"
],
"to": [
"dave",
"Q3.2"
],
"description": "10G; first LAG member"
},
{
"id": "B",
"from": [
"brian",
"10"
],
"to": [
"dave",
"Q3.4"
],
"description": "10G; second LAG member"
},
{
"id": "C",
"from": [
"brian",
"5"
],
"to": [
"jim",
"7"
],
"description": "1G; redundant fabric trunk"
},
{
"id": "D",
"from": [
"jim",
"S1"
],
"to": [
"dave",
"Q3.1"
],
"description": "10G; direct fabric trunk"
},
{
"id": "E",
"from": [
"jim",
"24"
],
"to": [
"dave",
"MGMT"
],
"description": "100M; dave management"
},
{
"id": "F",
"from": [
"jim",
"5"
],
"to": [
"palace",
"host-jim"
],
"description": "1G; host core / netboot"
},
{
"id": "G",
"from": [
"jim",
"22"
],
"to": [
"palace",
"river-jim-phy"
],
"description": "1G; river backup trunk"
},
{
"id": "H",
"from": [
"dave",
"Q1"
],
"to": [
"palace",
"uplink-dave"
],
"description": "100G; host PF and guest VFs"
},
{
"id": "I",
"from": [
"stream",
"ETH0"
],
"to": [
"jim",
"21"
],
"description": "1G WAN; 2.5G socket on stream"
},
{
"id": "J",
"from": [
"stream",
"ETH1"
],
"to": [
"jim",
"6"
],
"description": "1G backup LAN; 2.5G socket on stream"
},
{
"id": "K",
"from": [
"stream",
"SFP+ R"
],
"to": [
"dave",
"Q3.3"
],
"description": "10G preferred LAN"
}
],
"stream": {
"model": "BROUNION R86S",
"ports": [
{
"socket": "ETH0",
"interface": "wan",
"label": "wan",
"role": "1G connection to jim 21",
"nic": "Intel I225-V",
"capacity": "2.5G"
},
{
"socket": "ETH1",
"interface": "lan-jim",
"label": "lan-jim",
"role": "1G connection to jim 6",
"nic": "Intel I225-V",
"capacity": "2.5G"
},
{
"socket": "ETH2",
"interface": "et2",
"label": "et2",
"role": "Unused",
"nic": "Intel I225-V",
"capacity": "2.5G"
},
{
"socket": "SFP+ R",
"interface": "lan-dave",
"label": "lan-dave",
"role": "10G connection to dave Q3.3",
"nic": "Mellanox ConnectX-3",
"capacity": "10G"
},
{
"socket": "SFP+ L",
"interface": "et5",
"label": "et5",
"role": "Unused",
"nic": "Mellanox ConnectX-3",
"capacity": "10G"
}
]
},
"palace": {
"ports": [
{
"socket": "uplink-dave",
"nic": "Mellanox ConnectX-4",
"capacity": "100G QSFP28"
},
{
"socket": "host-jim",
"nic": "Intel I211",
"capacity": "1G RJ45"
},
{
"socket": "river-jim-phy",
"nic": "Intel I211",
"capacity": "1G RJ45"
}
]
}
}