figdown 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,62 +14,110 @@ different things from it:
14
14
  a plain program — no model in the rendering path — and the artifact travels
15
15
  with the document, viewable in any Markdown viewer.
16
16
 
17
+ ![One source, two readers](figures/one-source-two-readers.svg)
18
+
19
+ <sub>source: [figures/one-source-two-readers.fd](figures/one-source-two-readers.fd) — this figure is FigDown</sub>
20
+
17
21
  Think of it as the figure layer of Markdown: what Mermaid did for flowcharts,
18
22
  extended to the diagram families Mermaid cannot express — annotated block
19
23
  architectures, protocol headers, lookup tables, packet walks — with **layout
20
24
  treated as part of the knowledge** rather than as something the renderer is
21
25
  free to rearrange.
22
26
 
23
- **[Try it live — the editor runs in your browser, no install.](https://figdown.github.io/figdown/)**
27
+ **[Try it live — the editor runs in your browser, no install.](https://figdown.org/editor/figdown.html)**
24
28
 
25
29
  ---
26
30
 
27
31
  ## Fifteen seconds
28
32
 
29
- This is a complete FigDown document. Nothing has been elided.
33
+ The figure above is the whole idea, and it is itself a FigDown figure: one
34
+ `.fd` is the source of truth, a deterministic renderer turns it into the SVG a
35
+ human sees, and an agent reads the same `.fd` directly for meaning.
36
+
37
+ Here is what that source looks like. This document is
38
+ [`examples/dns.fd`](examples/dns.fd) in full — 30 lines, nothing has been
39
+ elided.
30
40
 
31
41
  ```figdown
32
- figdown 0.1 block
33
- title "Ingress datapath (excerpt)"
34
- group ing "Ingress Pipeline"
35
- node mac "MAC RX" in=ing
36
- node parser "Parser" in=ing
37
- node l2 "L2 Lookup" in=ing
38
- node l3 "L3 Lookup" in=ing fill=#d1fae5
39
- node acl "ACL" in=ing
40
- node mmu "MMU / Buffer"
41
- flow right
42
- edge mac -> parser
43
- edge parser -> l2
44
- edge l2 -[L3 hit]-> l3
45
- edge l2 -[miss]-> acl style=dashed
46
- edge l3 -> mmu
47
- edge acl -> mmu
42
+ # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
43
+
44
+ figdown 0.1 bitfield
45
+
46
+ # DNS Message Header — RFC 1035 §4.1.1
47
+ # Each row is 16 bits, MSB-0 numbering (bit 0 at left).
48
+
49
+ bitfield dns "DNS Message Header (RFC 1035)" word=16 numbering=msb0
50
+
51
+ # Row 1: Transaction ID
52
+ field "ID" 16 description="Identifier assigned by the program that generates the query; copied into the reply"
53
+
54
+ # Row 2: Flags (QR + Opcode + AA + TC + RD + RA + Z + RCODE = 16 bits)
55
+ field QR:1,Opcode:4,AA:1,TC:1,RD:1,RA:1,Z:3,RCODE:4
56
+
57
+ # Row 3: Question Count
58
+ field "QDCOUNT" 16 description="Number of entries in the question section"
59
+
60
+ # Row 4: Answer Record Count
61
+ field "ANCOUNT" 16 description="Number of resource records in the answer section"
62
+
63
+ # Row 5: Authority Record Count
64
+ field "NSCOUNT" 16 description="Number of name server resource records in the authority section"
65
+
66
+ # Row 6: Additional Record Count
67
+ field "ARCOUNT" 16 description="Number of resource records in the additional records section"
68
+
69
+ # Variable-length sections (one representative row each)
70
+ break
71
+ field "Question / Answer / Authority / Additional sections" * description="Variable-length sections follow the header; see RFC 1035 §4.1.2–4.1.4"
48
72
  ```
49
73
 
50
74
  It renders to this, deterministically — same source, same bytes, every time:
51
75
 
52
- ![Ingress datapath (excerpt)](figures/ingress.svg)
76
+ ![DNS message header (RFC 1035)](examples/dns.svg)
77
+
78
+ <sub>source: [examples/dns.fd](examples/dns.fd) — this figure is FigDown</sub>
53
79
 
54
- <sub>source: [figures/ingress.fd](figures/ingress.fd) this figure is FigDown</sub>
80
+ Look at what the picture had to carry: a bit ruler numbering 0–15 across the
81
+ top, and a flags word split into eight sub-byte fields — `QR | Opcode | AA |
82
+ TC | RD | RA | Z | RCODE` — drawn at their real widths, four bits for `Opcode`
83
+ and one for `AA`. No Markdown-native diagram tool draws that.
55
84
 
56
- An agent handed the text above can say which stages are inside the ingress
57
- pipeline, that an L2 miss goes to the ACL stage, and that both branches
58
- converge on the MMU. It can say all of it without seeing the picture. That is
59
- the whole idea.
85
+ An agent handed the text says the same things without the picture: that
86
+ `RCODE` is the low four bits of the second 16-bit word, that a DNS header is
87
+ six 16-bit words, that what follows it is variable-length and the document
88
+ declines to give a width for it. It can say all of it without seeing the
89
+ picture. That is the whole idea.
60
90
 
61
91
  In a Markdown document you embed the artifact and point at the source:
62
92
 
63
93
  ```markdown
64
- ![Ingress datapath](figures/ingress.svg)
94
+ ![DNS message header](examples/dns.svg)
65
95
 
66
- <sub>source: [figures/ingress.fd](figures/ingress.fd)</sub>
96
+ <sub>source: [examples/dns.fd](examples/dns.fd)</sub>
67
97
  ```
68
98
 
69
99
  The SVG is what humans see; the `source:` footer is what agents follow. Each
70
100
  generated SVG also embeds its own source text and a SHA-256 of it, so a figure
71
101
  that gets separated from its `.fd` can always be recovered and reopened.
72
102
 
103
+ ### One document, several coordinated forms
104
+
105
+ A `.fd` is not one picture per file. Two examples, shown small — the source is
106
+ behind each link, because their point is range and range needs more room than a
107
+ side-by-side fence gives:
108
+
109
+ <a href="examples/vxlan-encap.fd"><img src="examples/vxlan-encap.svg" width="46%" alt="VXLAN encapsulation: the Ethernet frame before encapsulation and the VXLAN-encapsulated frame after it, an overhead table, and a legend derived from the class declarations"></a>
110
+ <a href="examples/pvlan-flows.fd"><img src="examples/pvlan-flows.svg" width="46%" alt="Private VLAN: a topology of promiscuous, community and isolated ports, a derived legend, and two rule tables"></a>
111
+
112
+ - **[`examples/vxlan-encap.fd`](examples/vxlan-encap.fd)** — the frame layout
113
+ before and after encapsulation, side by side in one document, plus the
114
+ encapsulation overhead. The legend is derived from the `class` declarations;
115
+ nobody drew it.
116
+ - **[`examples/pvlan-flows.fd`](examples/pvlan-flows.fd)** — one document
117
+ producing a topology, a derived legend and two rule tables, because the
118
+ prohibitions that define a private VLAN cannot be drawn as arrows and have to
119
+ be written down.
120
+
73
121
  ---
74
122
 
75
123
  ## Why
@@ -215,7 +263,11 @@ Two consequences worth planning around:
215
263
  tag and one immutable, self-contained engine page. A user who wants to stay
216
264
  on a language version always can, by running the release that implemented it
217
265
  — and that does not depend on any future engine still understanding old
218
- documents.
266
+ documents. For `v0.1.0` that page is
267
+ [`archive/0.1/figdown.html`](archive/0.1/figdown.html): open it in any
268
+ browser, paste a `figdown 0.1` document in, and it renders exactly as
269
+ `v0.1.0` rendered it. The live editor is a tool and tracks the current
270
+ state; only the versioned `archive/` path is promised never to change.
219
271
  - **Expect one migration at `figdown 1.0`, and none after it** — until a
220
272
  `figdown 2.0`, which is the only place a removal may occur and which arrives
221
273
  with its own migration.
package/dist/figdown.js CHANGED
@@ -1,4 +1,4 @@
1
- // figdown.js — FigDown embeddable library (0.1.0)
1
+ // figdown.js — FigDown embeddable library (0.1.2)
2
2
  // GENERATED FILE, DO NOT EDIT. Built from editor/figdown.html.
3
3
  // Regenerate with: node tools/make-lib.js
4
4
  (function (root, factory) {
@@ -10,7 +10,7 @@
10
10
  }
11
11
  }(typeof globalThis !== 'undefined' ? globalThis : this, function () {
12
12
  'use strict';
13
- var VERSION = "0.1.0";
13
+ var VERSION = "0.1.2";
14
14
 
15
15
  // ---- engine (extracted verbatim from editor/figdown.html) ----
16
16
  var __engine = (function () {
@@ -24,7 +24,7 @@ const SHAPES = ['box','rounded','circle','ellipse','diamond','cylinder'];
24
24
  // input to that promise, and under core §13 a 0.x renderer may differ from
25
25
  // the next — which makes the recorded version the only thing that can
26
26
  // explain a diff between two renderings of one source.
27
- const FIGDOWN_VERSION = '0.1.0';
27
+ const FIGDOWN_VERSION = '0.1.2';
28
28
  // Retired shape VALUES keep a named diagnostic (PROCESS §5(d)), the same way
29
29
  // retired option keys do: `cloud` was the one value that named a domain
30
30
  // (the internet cloud) in an enum the language keeps purely geometric
package/dist/figdown.mjs CHANGED
@@ -1,8 +1,8 @@
1
- // figdown.mjs — FigDown embeddable library (0.1.0)
1
+ // figdown.mjs — FigDown embeddable library (0.1.2)
2
2
  // GENERATED FILE, DO NOT EDIT. Built from editor/figdown.html.
3
3
  // Regenerate with: node tools/make-lib.js
4
4
  'use strict';
5
- var VERSION = "0.1.0";
5
+ var VERSION = "0.1.2";
6
6
 
7
7
  // ---- engine (extracted verbatim from editor/figdown.html) ----
8
8
  var __engine = (function () {
@@ -16,7 +16,7 @@ const SHAPES = ['box','rounded','circle','ellipse','diamond','cylinder'];
16
16
  // input to that promise, and under core §13 a 0.x renderer may differ from
17
17
  // the next — which makes the recorded version the only thing that can
18
18
  // explain a diff between two renderings of one source.
19
- const FIGDOWN_VERSION = '0.1.0';
19
+ const FIGDOWN_VERSION = '0.1.2';
20
20
  // Retired shape VALUES keep a named diagnostic (PROCESS §5(d)), the same way
21
21
  // retired option keys do: `cloud` was the one value that named a domain
22
22
  // (the internet cloud) in an enum the language keeps purely geometric
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 527 634" width="527" height="634" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="24" x1="157.16" y1="56" x2="96.44000000000003" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="25" x1="197.12" y1="56" x2="234.08000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="26" x1="221.2" y1="50.810457516339866" x2="371.72" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="27" x1="277.20000000000005" y1="50.810457516339866" x2="126.68000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="28" x1="301.28000000000003" y1="56" x2="264.32000000000005" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="29" x1="341.24000000000007" y1="56" x2="401.96000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="30" x1="69.98000000000002" y1="136" x2="66.02000000000001" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="31" x1="249.20000000000005" y1="136" x2="249.20000000000002" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="32" x1="428.4200000000001" y1="136" x2="432.38" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="36" x1="132.40000000000003" y1="118" x2="188.40000000000003" y2="118" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><g data-node="sp1" data-x="142.8" data-y="20" style="cursor:move"><rect x="142.8" y="20" width="78.4" height="36" rx="14" fill="#e0e7ff" stroke="#8a8880" stroke-width="1.8"/><text x="182" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Spine-1</text></g><g data-node="sp2" data-x="277.20000000000005" data-y="20" style="cursor:move"><rect x="277.20000000000005" y="20" width="78.4" height="36" rx="14" fill="#e0e7ff" stroke="#8a8880" stroke-width="1.8"/><text x="316.40000000000003" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Spine-2</text></g><g data-node="lf1" data-x="10.800000000000011" data-y="100" style="cursor:move"><rect x="10.800000000000011" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="71.60000000000002" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-1 (VTEP)</text></g><g data-node="lf2" data-x="188.40000000000003" data-y="100" style="cursor:move"><rect x="188.40000000000003" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="249.20000000000005" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-2 (VTEP)</text></g><g data-node="lf3" data-x="366.00000000000006" data-y="100" style="cursor:move"><rect x="366.00000000000006" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="426.80000000000007" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-3 (VTEP)</text></g><g data-node="h1" data-x="0" data-y="180" style="cursor:move"><rect x="0" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="64.4" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-A (VLAN 10)</text></g><g data-node="h2" data-x="184.8" data-y="180" style="cursor:move"><rect x="184.8" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="249.20000000000002" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-B (VLAN 10)</text></g><g data-node="h3" data-x="369.6" data-y="180" style="cursor:move"><rect x="369.6" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="434" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-C (VLAN 20)</text></g><text x="126.80000000000001" y="72.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">eBGP</text><text x="126.80000000000001" y="72.25" font-size="11" text-anchor="middle" fill="#555">eBGP</text><text x="160.40000000000003" y="112.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">VXLAN VNI 10010</text><text x="160.40000000000003" y="112.25" font-size="11" text-anchor="middle" fill="#dc2626">VXLAN VNI 10010</text><path d="M132.40000000000003 118 L142.48000000000005 112.4 L142.48000000000005 123.6 z" fill="#dc2626" stroke="none"/><path d="M188.40000000000003 118 L178.32000000000002 123.6 L178.32000000000002 112.4 z" fill="#dc2626" stroke="none"/><rect x="0" y="237" width="16" height="11" fill="#fff" stroke="#555"/><text x="21" y="246.5" font-size="11" fill="#1d1d1b">Physical underlay link — eBGP/L3 transport between leaf and spine</text><rect x="0" y="257" width="16" height="11" fill="#fff" stroke="#dc2626" stroke-dasharray="6 4"/><text x="21" y="266.5" font-size="11" fill="#1d1d1b">Logical VXLAN overlay tunnel — rides on the physical underlay</text></g></g><g transform="translate(0,312)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">VNI mapping</text><rect x="0" y="22" width="71.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:1" style="cursor:pointer"/><text x="35.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Leaf</text><rect x="71.2" y="22" width="56.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:2" style="cursor:pointer"/><text x="99.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">VLAN</text><rect x="128" y="22" width="64" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:3" style="cursor:pointer"/><text x="160" y="39.3" font-size="12" text-anchor="middle" font-weight="600">VNI</text><rect x="192" y="22" width="56.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:4" style="cursor:pointer"/><text x="220.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Type</text><rect x="0" y="48" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">Leaf-1</text><rect x="71.2" y="48" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:2" style="cursor:pointer"/><text x="99.6" y="65.3" font-size="12" text-anchor="middle">10</text><rect x="128" y="48" width="64" height="26" fill="#fee2e2" stroke="#c9c7bf" data-cell="vni:1:3" style="cursor:pointer"/><text x="135" y="65.3" font-size="12" text-anchor="start">10010</text><rect x="192" y="48" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:4" style="cursor:pointer"/><text x="199" y="65.3" font-size="12" text-anchor="start">L2</text><rect x="0" y="74" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">Leaf-2</text><rect x="71.2" y="74" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:2" style="cursor:pointer"/><text x="99.6" y="91.3" font-size="12" text-anchor="middle">10</text><rect x="128" y="74" width="64" height="26" fill="#fee2e2" stroke="#c9c7bf" data-cell="vni:2:3" style="cursor:pointer"/><text x="135" y="91.3" font-size="12" text-anchor="start">10010</text><rect x="192" y="74" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:4" style="cursor:pointer"/><text x="199" y="91.3" font-size="12" text-anchor="start">L2</text><rect x="0" y="100" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">Leaf-3</text><rect x="71.2" y="100" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:2" style="cursor:pointer"/><text x="99.6" y="117.3" font-size="12" text-anchor="middle">20</text><rect x="128" y="100" width="64" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:3" style="cursor:pointer"/><text x="135" y="117.3" font-size="12" text-anchor="start">10020</text><rect x="192" y="100" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:4" style="cursor:pointer"/><text x="199" y="117.3" font-size="12" text-anchor="start">L2</text><text x="0" y="170" font-size="13" font-weight="600">Fabric planes</text><rect x="0" y="178" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:1" style="cursor:pointer"/><text x="68" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Plane</text><rect x="136" y="178" width="143.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:2" style="cursor:pointer"/><text x="207.6" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Protocol</text><rect x="279.2" y="178" width="208" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:3" style="cursor:pointer"/><text x="383.2" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Role</text><rect x="0" y="204" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:1" style="cursor:pointer"/><text x="7" y="221.3" font-size="12" text-anchor="start">Underlay</text><rect x="136" y="204" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:2" style="cursor:pointer"/><text x="143" y="221.3" font-size="12" text-anchor="start">eBGP</text><rect x="279.2" y="204" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:3" style="cursor:pointer"/><text x="286.2" y="221.3" font-size="12" text-anchor="start">loopback reachability</text><rect x="0" y="230" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:1" style="cursor:pointer"/><text x="7" y="247.3" font-size="12" text-anchor="start">Overlay control</text><rect x="136" y="230" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:2" style="cursor:pointer"/><text x="143" y="247.3" font-size="12" text-anchor="start">MP-BGP EVPN</text><rect x="279.2" y="230" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:3" style="cursor:pointer"/><text x="286.2" y="247.3" font-size="12" text-anchor="start">MAC/IP route distribution</text><rect x="0" y="256" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:1" style="cursor:pointer"/><text x="7" y="273.3" font-size="12" text-anchor="start">Overlay data</text><rect x="136" y="256" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:2" style="cursor:pointer"/><text x="143" y="273.3" font-size="12" text-anchor="start">VXLAN (UDP 4789)</text><rect x="279.2" y="256" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:3" style="cursor:pointer"/><text x="286.2" y="273.3" font-size="12" text-anchor="start">L2-in-L3 encapsulation</text></g></g><metadata id="figdown-source" data-sha256="bc3fb7fb66c7628738359b5135f8da14572e5fb24c4f6efb18a6b8365ab602ea" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 527 634" width="527" height="634" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="24" x1="157.16" y1="56" x2="96.44000000000003" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="25" x1="197.12" y1="56" x2="234.08000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="26" x1="221.2" y1="50.810457516339866" x2="371.72" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="27" x1="277.20000000000005" y1="50.810457516339866" x2="126.68000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="28" x1="301.28000000000003" y1="56" x2="264.32000000000005" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="29" x1="341.24000000000007" y1="56" x2="401.96000000000004" y2="100" stroke="#555" stroke-width="1.6"/><line data-edge="30" x1="69.98000000000002" y1="136" x2="66.02000000000001" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="31" x1="249.20000000000005" y1="136" x2="249.20000000000002" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="32" x1="428.4200000000001" y1="136" x2="432.38" y2="180" stroke="#555" stroke-width="1.6"/><line data-edge="36" x1="132.40000000000003" y1="118" x2="188.40000000000003" y2="118" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><g data-node="sp1" data-x="142.8" data-y="20" style="cursor:move"><rect x="142.8" y="20" width="78.4" height="36" rx="14" fill="#e0e7ff" stroke="#8a8880" stroke-width="1.8"/><text x="182" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Spine-1</text></g><g data-node="sp2" data-x="277.20000000000005" data-y="20" style="cursor:move"><rect x="277.20000000000005" y="20" width="78.4" height="36" rx="14" fill="#e0e7ff" stroke="#8a8880" stroke-width="1.8"/><text x="316.40000000000003" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Spine-2</text></g><g data-node="lf1" data-x="10.800000000000011" data-y="100" style="cursor:move"><rect x="10.800000000000011" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="71.60000000000002" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-1 (VTEP)</text></g><g data-node="lf2" data-x="188.40000000000003" data-y="100" style="cursor:move"><rect x="188.40000000000003" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="249.20000000000005" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-2 (VTEP)</text></g><g data-node="lf3" data-x="366.00000000000006" data-y="100" style="cursor:move"><rect x="366.00000000000006" y="100" width="121.60000000000001" height="36" rx="14" fill="#fff" stroke="#8a8880" stroke-width="1.8"/><text x="426.80000000000007" y="122.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Leaf-3 (VTEP)</text></g><g data-node="h1" data-x="0" data-y="180" style="cursor:move"><rect x="0" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="64.4" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-A (VLAN 10)</text></g><g data-node="h2" data-x="184.8" data-y="180" style="cursor:move"><rect x="184.8" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="249.20000000000002" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-B (VLAN 10)</text></g><g data-node="h3" data-x="369.6" data-y="180" style="cursor:move"><rect x="369.6" y="180" width="128.8" height="36" fill="#fff" stroke="#8a8880"/><text x="434" y="202.55" font-size="13" text-anchor="middle" fill="#1d1d1b">VM-C (VLAN 20)</text></g><text x="126.80000000000001" y="72.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">eBGP</text><text x="126.80000000000001" y="72.25" font-size="11" text-anchor="middle" fill="#555">eBGP</text><text x="160.40000000000003" y="112.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">VXLAN VNI 10010</text><text x="160.40000000000003" y="112.25" font-size="11" text-anchor="middle" fill="#dc2626">VXLAN VNI 10010</text><path d="M132.40000000000003 118 L142.48000000000005 112.4 L142.48000000000005 123.6 z" fill="#dc2626" stroke="none"/><path d="M188.40000000000003 118 L178.32000000000002 123.6 L178.32000000000002 112.4 z" fill="#dc2626" stroke="none"/><rect x="0" y="237" width="16" height="11" fill="#fff" stroke="#555"/><text x="21" y="246.5" font-size="11" fill="#1d1d1b">Physical underlay link — eBGP/L3 transport between leaf and spine</text><rect x="0" y="257" width="16" height="11" fill="#fff" stroke="#dc2626" stroke-dasharray="6 4"/><text x="21" y="266.5" font-size="11" fill="#1d1d1b">Logical VXLAN overlay tunnel — rides on the physical underlay</text></g></g><g transform="translate(0,312)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">VNI mapping</text><rect x="0" y="22" width="71.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:1" style="cursor:pointer"/><text x="35.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Leaf</text><rect x="71.2" y="22" width="56.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:2" style="cursor:pointer"/><text x="99.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">VLAN</text><rect x="128" y="22" width="64" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:3" style="cursor:pointer"/><text x="160" y="39.3" font-size="12" text-anchor="middle" font-weight="600">VNI</text><rect x="192" y="22" width="56.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="vni:0:4" style="cursor:pointer"/><text x="220.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Type</text><rect x="0" y="48" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">Leaf-1</text><rect x="71.2" y="48" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:2" style="cursor:pointer"/><text x="99.6" y="65.3" font-size="12" text-anchor="middle">10</text><rect x="128" y="48" width="64" height="26" fill="#fee2e2" stroke="#c9c7bf" data-cell="vni:1:3" style="cursor:pointer"/><text x="135" y="65.3" font-size="12" text-anchor="start">10010</text><rect x="192" y="48" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:1:4" style="cursor:pointer"/><text x="199" y="65.3" font-size="12" text-anchor="start">L2</text><rect x="0" y="74" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">Leaf-2</text><rect x="71.2" y="74" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:2" style="cursor:pointer"/><text x="99.6" y="91.3" font-size="12" text-anchor="middle">10</text><rect x="128" y="74" width="64" height="26" fill="#fee2e2" stroke="#c9c7bf" data-cell="vni:2:3" style="cursor:pointer"/><text x="135" y="91.3" font-size="12" text-anchor="start">10010</text><rect x="192" y="74" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:2:4" style="cursor:pointer"/><text x="199" y="91.3" font-size="12" text-anchor="start">L2</text><rect x="0" y="100" width="71.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">Leaf-3</text><rect x="71.2" y="100" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:2" style="cursor:pointer"/><text x="99.6" y="117.3" font-size="12" text-anchor="middle">20</text><rect x="128" y="100" width="64" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:3" style="cursor:pointer"/><text x="135" y="117.3" font-size="12" text-anchor="start">10020</text><rect x="192" y="100" width="56.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="vni:3:4" style="cursor:pointer"/><text x="199" y="117.3" font-size="12" text-anchor="start">L2</text><text x="0" y="170" font-size="13" font-weight="600">Fabric planes</text><rect x="0" y="178" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:1" style="cursor:pointer"/><text x="68" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Plane</text><rect x="136" y="178" width="143.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:2" style="cursor:pointer"/><text x="207.6" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Protocol</text><rect x="279.2" y="178" width="208" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="planes:0:3" style="cursor:pointer"/><text x="383.2" y="195.3" font-size="12" text-anchor="middle" font-weight="600">Role</text><rect x="0" y="204" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:1" style="cursor:pointer"/><text x="7" y="221.3" font-size="12" text-anchor="start">Underlay</text><rect x="136" y="204" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:2" style="cursor:pointer"/><text x="143" y="221.3" font-size="12" text-anchor="start">eBGP</text><rect x="279.2" y="204" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:1:3" style="cursor:pointer"/><text x="286.2" y="221.3" font-size="12" text-anchor="start">loopback reachability</text><rect x="0" y="230" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:1" style="cursor:pointer"/><text x="7" y="247.3" font-size="12" text-anchor="start">Overlay control</text><rect x="136" y="230" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:2" style="cursor:pointer"/><text x="143" y="247.3" font-size="12" text-anchor="start">MP-BGP EVPN</text><rect x="279.2" y="230" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:2:3" style="cursor:pointer"/><text x="286.2" y="247.3" font-size="12" text-anchor="start">MAC/IP route distribution</text><rect x="0" y="256" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:1" style="cursor:pointer"/><text x="7" y="273.3" font-size="12" text-anchor="start">Overlay data</text><rect x="136" y="256" width="143.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:2" style="cursor:pointer"/><text x="143" y="273.3" font-size="12" text-anchor="start">VXLAN (UDP 4789)</text><rect x="279.2" y="256" width="208" height="26" fill="#fff" stroke="#c9c7bf" data-cell="planes:3:3" style="cursor:pointer"/><text x="286.2" y="273.3" font-size="12" text-anchor="start">L2-in-L3 encapsulation</text></g></g><metadata id="figdown-source" data-sha256="bc3fb7fb66c7628738359b5135f8da14572e5fb24c4f6efb18a6b8365ab602ea" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 topology
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559 408" width="559" height="408" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="34" x1="172" y1="74.86640581330352" x2="365" y2="54.36892118501956" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="35" x1="172" y1="95.46666666666667" x2="365" y2="121.2" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><path data-edge="39" d="M443.8 72 L443.8 146 Q443.8 156 433.8 156 L96 156 Q86 156 86 146 L86 110" fill="none" stroke="#16a34a" stroke-width="1.6"/><g data-node="a" data-x="0" data-y="58" style="cursor:move"><rect x="0" y="58" width="172" height="52" fill="#fff" stroke="#8a8880"/><text x="86" y="80.1" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="86" dy="0">Host A</tspan><tspan x="86" dy="16.900000000000002">wants MAC for B's IP</tspan></text></g><g data-node="b" data-x="365" data-y="20" style="cursor:move"><rect x="365" y="20" width="157.6" height="52" fill="#fff" stroke="#8a8880"/><text x="443.8" y="42.099999999999994" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="443.8" dy="0">Host B</tspan><tspan x="443.8" dy="16.900000000000002">owns the target IP</tspan></text></g><text x="268.5" y="58.86766349916154" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: who-has B? (broadcast)</text><text x="268.5" y="58.86766349916154" font-size="11" text-anchor="middle" fill="#dc2626">1: who-has B? (broadcast)</text><path d="M365 54.36892118501956 L355.5677913970842 61.00215877092595 L354.38495222174663 49.864794114720844 z" fill="#dc2626" stroke="none"/><text x="268.5" y="102.58333333333334" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: heard, ignored</text><text x="268.5" y="102.58333333333334" font-size="11" text-anchor="middle" fill="#dc2626">1: heard, ignored</text><path d="M365 121.2 L354.2683059286093 125.41866594530529 L355.7485395936288 114.31691345765978 z" fill="#dc2626" stroke="none"/><text x="264.9" y="150.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">2: B is at aa:bb:cc:... A caches it</text><text x="264.9" y="150.25" font-size="11" text-anchor="middle" fill="#16a34a">2: B is at aa:bb:cc:... A caches it</text><path d="M86 110 L91.6 120.08 L80.4 120.08 z" fill="#16a34a" stroke="none"/><text x="381" y="119" font-size="10" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round"><tspan x="381" dy="0">rest of the LAN</tspan><tspan x="381" dy="13">(hosts C, D, ...)</tspan></text><text x="381" y="119" font-size="10" text-anchor="start" fill="#555"><tspan x="381" dy="0">rest of the LAN</tspan><tspan x="381" dy="13">(hosts C, D, ...)</tspan></text><rect x="0" y="193" width="16" height="11" fill="#fff" stroke="#dc2626" stroke-dasharray="6 4"/><text x="21" y="202.5" font-size="11" fill="#1d1d1b">Broadcast — delivered to every host on the LAN (dst MAC ff:ff:ff:ff:ff:ff)</text><rect x="0" y="213" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="222.5" font-size="11" fill="#1d1d1b">Unicast — delivered only to the requester (dst MAC = A's MAC)</text></g></g><g transform="translate(0,268)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Host A's ARP cache — before and after the exchange</text><rect x="0" y="22" width="164.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="cache:0:1" style="cursor:pointer"/><text x="82.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Moment</text><rect x="164.8" y="22" width="359.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="cache:0:2" style="cursor:pointer"/><text x="344.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Entry</text><rect x="0" y="48" width="164.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">before the exchange</text><rect x="164.8" y="48" width="359.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:1:2" style="cursor:pointer"/><text x="171.8" y="65.3" font-size="12" text-anchor="start">(no entry for B's IP)</text><rect x="0" y="74" width="164.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">after segment 2</text><rect x="164.8" y="74" width="359.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:2:2" style="cursor:pointer"/><text x="171.8" y="91.3" font-size="12" text-anchor="start">B's IP → aa:bb:cc:... , learned from the reply</text></g></g><metadata id="figdown-source" data-sha256="6ddb80cf95500ada2890c436006495c99a7cfa719412f6dafdc298badffa743e" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559 408" width="559" height="408" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="34" x1="172" y1="74.86640581330352" x2="365" y2="54.36892118501956" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="35" x1="172" y1="95.46666666666667" x2="365" y2="121.2" stroke="#dc2626" stroke-width="1.6" stroke-dasharray="6 4"/><path data-edge="39" d="M443.8 72 L443.8 146 Q443.8 156 433.8 156 L96 156 Q86 156 86 146 L86 110" fill="none" stroke="#16a34a" stroke-width="1.6"/><g data-node="a" data-x="0" data-y="58" style="cursor:move"><rect x="0" y="58" width="172" height="52" fill="#fff" stroke="#8a8880"/><text x="86" y="80.1" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="86" dy="0">Host A</tspan><tspan x="86" dy="16.900000000000002">wants MAC for B's IP</tspan></text></g><g data-node="b" data-x="365" data-y="20" style="cursor:move"><rect x="365" y="20" width="157.6" height="52" fill="#fff" stroke="#8a8880"/><text x="443.8" y="42.099999999999994" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="443.8" dy="0">Host B</tspan><tspan x="443.8" dy="16.900000000000002">owns the target IP</tspan></text></g><text x="268.5" y="58.86766349916154" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: who-has B? (broadcast)</text><text x="268.5" y="58.86766349916154" font-size="11" text-anchor="middle" fill="#dc2626">1: who-has B? (broadcast)</text><path d="M365 54.36892118501956 L355.5677913970842 61.00215877092595 L354.38495222174663 49.864794114720844 z" fill="#dc2626" stroke="none"/><text x="268.5" y="102.58333333333334" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: heard, ignored</text><text x="268.5" y="102.58333333333334" font-size="11" text-anchor="middle" fill="#dc2626">1: heard, ignored</text><path d="M365 121.2 L354.2683059286093 125.41866594530529 L355.7485395936288 114.31691345765978 z" fill="#dc2626" stroke="none"/><text x="264.9" y="150.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">2: B is at aa:bb:cc:... A caches it</text><text x="264.9" y="150.25" font-size="11" text-anchor="middle" fill="#16a34a">2: B is at aa:bb:cc:... A caches it</text><path d="M86 110 L91.6 120.08 L80.4 120.08 z" fill="#16a34a" stroke="none"/><text x="381" y="119" font-size="10" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round"><tspan x="381" dy="0">rest of the LAN</tspan><tspan x="381" dy="13">(hosts C, D, ...)</tspan></text><text x="381" y="119" font-size="10" text-anchor="start" fill="#555"><tspan x="381" dy="0">rest of the LAN</tspan><tspan x="381" dy="13">(hosts C, D, ...)</tspan></text><rect x="0" y="193" width="16" height="11" fill="#fff" stroke="#dc2626" stroke-dasharray="6 4"/><text x="21" y="202.5" font-size="11" fill="#1d1d1b">Broadcast — delivered to every host on the LAN (dst MAC ff:ff:ff:ff:ff:ff)</text><rect x="0" y="213" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="222.5" font-size="11" fill="#1d1d1b">Unicast — delivered only to the requester (dst MAC = A's MAC)</text></g></g><g transform="translate(0,268)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Host A's ARP cache — before and after the exchange</text><rect x="0" y="22" width="164.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="cache:0:1" style="cursor:pointer"/><text x="82.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Moment</text><rect x="164.8" y="22" width="359.2" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="cache:0:2" style="cursor:pointer"/><text x="344.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Entry</text><rect x="0" y="48" width="164.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">before the exchange</text><rect x="164.8" y="48" width="359.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:1:2" style="cursor:pointer"/><text x="171.8" y="65.3" font-size="12" text-anchor="start">(no entry for B's IP)</text><rect x="0" y="74" width="164.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">after segment 2</text><rect x="164.8" y="74" width="359.2" height="26" fill="#fff" stroke="#c9c7bf" data-cell="cache:2:2" style="cursor:pointer"/><text x="171.8" y="91.3" font-size="12" text-anchor="start">B's IP → aa:bb:cc:... , learned from the reply</text></g></g><metadata id="figdown-source" data-sha256="6ddb80cf95500ada2890c436006495c99a7cfa719412f6dafdc298badffa743e" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 topology
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 884 194" width="884" height="194" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Ethernet II frame — column order = wire order (byte counts in the second header tier)</text><rect x="0" y="22" width="90" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="45" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Variant</text><rect x="90" y="22" width="136" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="158" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Destination MAC</text><rect x="226" y="22" width="100" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="276" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Source MAC</text><rect x="326" y="22" width="208" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="430" y="39.3" font-size="12" text-anchor="middle" font-weight="600">802.1Q Tag</text><rect x="534" y="22" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="580.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">EtherType</text><rect x="626.8" y="22" width="136" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="694.8" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Payload</text><rect x="762.8" y="22" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="809.1999999999999" y="39.3" font-size="12" text-anchor="middle" font-weight="600">FCS</text><rect x="0" y="48" width="90" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:1" style="cursor:pointer"/><text x="45" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(frame)</text><rect x="90" y="48" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:2" style="cursor:pointer"/><text x="158" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(6 bytes)</text><rect x="226" y="48" width="100" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:3" style="cursor:pointer"/><text x="276" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(6 bytes)</text><rect x="326" y="48" width="208" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:4" style="cursor:pointer"/><text x="430" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(4 bytes)</text><rect x="534" y="48" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:5" style="cursor:pointer"/><text x="580.4" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(2 bytes)</text><rect x="626.8" y="48" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:6" style="cursor:pointer"/><text x="694.8" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(46-1500 bytes)</text><rect x="762.8" y="48" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:7" style="cursor:pointer"/><text x="809.1999999999999" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(4 bytes)</text><rect x="0" y="74" width="90" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">Untagged</text><rect x="90" y="74" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:2" style="cursor:pointer"/><text x="97" y="91.3" font-size="12" text-anchor="start">DA</text><rect x="226" y="74" width="100" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:3" style="cursor:pointer"/><text x="233" y="91.3" font-size="12" text-anchor="start">SA</text><rect x="326" y="74" width="208" height="26" fill="#dbeafe" stroke="#c9c7bf" data-cell="eth:1:4" style="cursor:pointer"/><text x="333" y="91.3" font-size="12" text-anchor="start">(none)</text><rect x="534" y="74" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:5" style="cursor:pointer"/><text x="541" y="91.3" font-size="12" text-anchor="start">Type</text><rect x="626.8" y="74" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:6" style="cursor:pointer"/><text x="633.8" y="91.3" font-size="12" text-anchor="start">Data</text><rect x="762.8" y="74" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:7" style="cursor:pointer"/><text x="769.8" y="91.3" font-size="12" text-anchor="start">CRC-32</text><rect x="0" y="100" width="90" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">Tagged</text><rect x="90" y="100" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:2" style="cursor:pointer"/><text x="97" y="117.3" font-size="12" text-anchor="start">DA</text><rect x="226" y="100" width="100" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:3" style="cursor:pointer"/><text x="233" y="117.3" font-size="12" text-anchor="start">SA</text><rect x="326" y="100" width="208" height="26" fill="#dbeafe" stroke="#c9c7bf" data-cell="eth:2:4" style="cursor:pointer"/><text x="333" y="117.3" font-size="12" text-anchor="start">TPID 0x8100 + PCP/DEI/VID</text><rect x="534" y="100" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:5" style="cursor:pointer"/><text x="541" y="117.3" font-size="12" text-anchor="start">Type</text><rect x="626.8" y="100" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:6" style="cursor:pointer"/><text x="633.8" y="117.3" font-size="12" text-anchor="start">Data</text><rect x="762.8" y="100" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:7" style="cursor:pointer"/><text x="769.8" y="117.3" font-size="12" text-anchor="start">CRC-32</text><rect x="0" y="167" width="16" height="11" fill="#dbeafe" stroke="#555"/><text x="21" y="176.5" font-size="11" fill="#1d1d1b">802.1Q VLAN tag (4 bytes), inserted after Source MAC; absent in an untagged frame</text></g><metadata id="figdown-source" data-sha256="b00b608d31c790edaa5e3d993691a440e1bd2ef93e108f045fe840952a4f1b6b" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 884 194" width="884" height="194" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Ethernet II frame — column order = wire order (byte counts in the second header tier)</text><rect x="0" y="22" width="90" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="45" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Variant</text><rect x="90" y="22" width="136" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="158" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Destination MAC</text><rect x="226" y="22" width="100" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="276" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Source MAC</text><rect x="326" y="22" width="208" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="430" y="39.3" font-size="12" text-anchor="middle" font-weight="600">802.1Q Tag</text><rect x="534" y="22" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="580.4" y="39.3" font-size="12" text-anchor="middle" font-weight="600">EtherType</text><rect x="626.8" y="22" width="136" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="694.8" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Payload</text><rect x="762.8" y="22" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf"/><text x="809.1999999999999" y="39.3" font-size="12" text-anchor="middle" font-weight="600">FCS</text><rect x="0" y="48" width="90" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:1" style="cursor:pointer"/><text x="45" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(frame)</text><rect x="90" y="48" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:2" style="cursor:pointer"/><text x="158" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(6 bytes)</text><rect x="226" y="48" width="100" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:3" style="cursor:pointer"/><text x="276" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(6 bytes)</text><rect x="326" y="48" width="208" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:4" style="cursor:pointer"/><text x="430" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(4 bytes)</text><rect x="534" y="48" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:5" style="cursor:pointer"/><text x="580.4" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(2 bytes)</text><rect x="626.8" y="48" width="136" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:6" style="cursor:pointer"/><text x="694.8" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(46-1500 bytes)</text><rect x="762.8" y="48" width="92.8" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="eth:0:7" style="cursor:pointer"/><text x="809.1999999999999" y="65.3" font-size="12" text-anchor="middle" font-weight="600">(4 bytes)</text><rect x="0" y="74" width="90" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">Untagged</text><rect x="90" y="74" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:2" style="cursor:pointer"/><text x="97" y="91.3" font-size="12" text-anchor="start">DA</text><rect x="226" y="74" width="100" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:3" style="cursor:pointer"/><text x="233" y="91.3" font-size="12" text-anchor="start">SA</text><rect x="326" y="74" width="208" height="26" fill="#dbeafe" stroke="#c9c7bf" data-cell="eth:1:4" style="cursor:pointer"/><text x="333" y="91.3" font-size="12" text-anchor="start">(none)</text><rect x="534" y="74" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:5" style="cursor:pointer"/><text x="541" y="91.3" font-size="12" text-anchor="start">Type</text><rect x="626.8" y="74" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:6" style="cursor:pointer"/><text x="633.8" y="91.3" font-size="12" text-anchor="start">Data</text><rect x="762.8" y="74" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:1:7" style="cursor:pointer"/><text x="769.8" y="91.3" font-size="12" text-anchor="start">CRC-32</text><rect x="0" y="100" width="90" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">Tagged</text><rect x="90" y="100" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:2" style="cursor:pointer"/><text x="97" y="117.3" font-size="12" text-anchor="start">DA</text><rect x="226" y="100" width="100" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:3" style="cursor:pointer"/><text x="233" y="117.3" font-size="12" text-anchor="start">SA</text><rect x="326" y="100" width="208" height="26" fill="#dbeafe" stroke="#c9c7bf" data-cell="eth:2:4" style="cursor:pointer"/><text x="333" y="117.3" font-size="12" text-anchor="start">TPID 0x8100 + PCP/DEI/VID</text><rect x="534" y="100" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:5" style="cursor:pointer"/><text x="541" y="117.3" font-size="12" text-anchor="start">Type</text><rect x="626.8" y="100" width="136" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:6" style="cursor:pointer"/><text x="633.8" y="117.3" font-size="12" text-anchor="start">Data</text><rect x="762.8" y="100" width="92.8" height="26" fill="#fff" stroke="#c9c7bf" data-cell="eth:2:7" style="cursor:pointer"/><text x="769.8" y="117.3" font-size="12" text-anchor="start">CRC-32</text><rect x="0" y="167" width="16" height="11" fill="#dbeafe" stroke="#555"/><text x="21" y="176.5" font-size="11" fill="#1d1d1b">802.1Q VLAN tag (4 bytes), inserted after Source MAC; absent in an untagged frame</text></g><metadata id="figdown-source" data-sha256="b00b608d31c790edaa5e3d993691a440e1bd2ef93e108f045fe840952a4f1b6b" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 table
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 544 651" width="544" height="651" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="35" x1="290.37307692307695" y1="32" x2="290.37307692307695" y2="76" stroke="#555" stroke-width="1.6"/><line data-edge="36" x1="290.37307692307695" y1="144" x2="290.37307692307695" y2="188" stroke="#555" stroke-width="1.6"/><line data-edge="37" x1="290.37307692307695" y1="240" x2="290.37307692307695" y2="284" stroke="#555" stroke-width="1.6"/><line data-edge="39" x1="316.80398475528494" y1="333.30324720278287" x2="387.66843676737295" y2="386.74285714285713" stroke="#555" stroke-width="1.6"/><line data-edge="40" x1="266.24256332978035" y1="334.1248165738226" x2="191.637909323235" y2="398.2883630891489" stroke="#555" stroke-width="1.6"/><line data-edge="42" x1="186.46826779078154" y1="456.9233011944657" x2="236.0239383938394" y2="510.66221198156677" stroke="#555" stroke-width="1.6"/><line data-edge="43" x1="130.7317322092185" y1="456.9233011944657" x2="81.17606160616063" y2="510.66221198156677" stroke="#555" stroke-width="1.6"/><g data-node="learn" data-x="204.37307692307695" data-y="76" style="cursor:move"><rect x="204.37307692307695" y="76" width="172" height="68" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="97.64999999999999" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="290.37307692307695" dy="0">Learn source MAC:</tspan><tspan x="290.37307692307695" dy="16.900000000000002">update MAC table</tspan><tspan x="290.37307692307695" dy="16.900000000000002">(SA -&gt; ingress port)</tspan></text></g><g data-node="lookup" data-x="193.57307692307694" data-y="188" style="cursor:move"><rect x="193.57307692307694" y="188" width="193.6" height="52" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="210.10000000000002" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="290.37307692307695" dy="0">Look up destination MAC</tspan><tspan x="290.37307692307695" dy="16.900000000000002">in MAC table</tspan></text></g><g data-node="hit" data-x="208.13307692307694" data-y="284" style="cursor:move"><polygon points="290.37307692307695,284 372.61307692307696,313.37142857142857 290.37307692307695,342.74285714285713 208.13307692307694,313.37142857142857" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="317.9214285714286" font-size="13" text-anchor="middle" fill="#1d1d1b">Entry found?</text></g><g data-node="same" data-x="44.253846153846155" data-y="386.74285714285713" style="cursor:move"><polygon points="158.60000000000002,386.74285714285713 272.94615384615383,426.70253456221195 158.60000000000002,466.66221198156677 44.253846153846155,426.70253456221195" fill="#fff" stroke="#8a8880"/><text x="158.60000000000002" y="422.802534562212" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="158.60000000000002" dy="0">Egress port ==</tspan><tspan x="158.60000000000002" dy="16.900000000000002">ingress port?</tspan></text></g><g data-node="fwd" data-x="0" data-y="510.66221198156677" style="cursor:move"><rect x="0" y="510.66221198156677" width="114.4" height="52" rx="14" fill="#16a34a" stroke="#8a8880" stroke-width="1.8"/><text x="57.2" y="532.7622119815667" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="57.2" dy="0">Forward out</tspan><tspan x="57.2" dy="16.900000000000002">learned port</tspan></text></g><g data-node="fld" data-x="328.9461538461539" data-y="386.74285714285713" style="cursor:move"><rect x="328.9461538461539" y="386.74285714285713" width="186.4" height="52" rx="14" fill="#2563eb" stroke="#8a8880" stroke-width="1.8"/><text x="422.1461538461539" y="408.84285714285716" font-size="13" text-anchor="middle" fill="#ffffff"><tspan x="422.1461538461539" dy="0">Flood to all ports</tspan><tspan x="422.1461538461539" dy="16.900000000000002">in VLAN except ingress</tspan></text></g><g data-node="flt" data-x="170.4" data-y="510.66221198156677" style="cursor:move"><rect x="170.4" y="510.66221198156677" width="179.20000000000002" height="52" rx="14" fill="#dc2626" stroke="#8a8880" stroke-width="1.8"/><text x="260" y="532.7622119815667" font-size="13" text-anchor="middle" fill="#ffffff"><tspan x="260" dy="0">Filter (drop):</tspan><tspan x="260" dy="16.900000000000002">same-port destination</tspan></text></g><path d="M290.37307692307695 76 L284.7730769230769 65.92 L295.973076923077 65.92 z" fill="#555" stroke="none"/><path d="M290.37307692307695 188 L284.7730769230769 177.92 L295.973076923077 177.92 z" fill="#555" stroke="none"/><path d="M290.37307692307695 284 L284.7730769230769 273.92 L295.973076923077 273.92 z" fill="#555" stroke="none"/><text x="332.3941641979443" y="357.40996138959923" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">no</text><text x="332.3941641979443" y="357.40996138959923" font-size="11" text-anchor="middle" fill="#555">no</text><path d="M387.66843676737295 386.74285714285713 L376.2485927245621 385.1448702724861 L382.99209291771245 376.2025436655576 z" fill="#555" stroke="none"/><text x="249.82953944834037" y="360.5907968071944" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">yes</text><text x="249.82953944834037" y="360.5907968071944" font-size="11" text-anchor="middle" fill="#555">yes</text><path d="M191.637909323235 398.2883630891489 L195.62870077540882 387.46986117875224 L202.93177246717303 395.96133595436993 z" fill="#555" stroke="none"/><text x="207.33496897169888" y="476.34497443059604" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">yes</text><text x="207.33496897169888" y="476.34497443059604" font-size="11" text-anchor="start" fill="#555">yes</text><path d="M236.0239383938394 510.66221198156677 L225.07377169049153 507.04831530776835 L233.30734750001278 499.4556721982269 z" fill="#555" stroke="none"/><text x="121.86503102830115" y="476.34497443059604" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">no</text><text x="121.86503102830115" y="476.34497443059604" font-size="11" text-anchor="start" fill="#555">no</text><path d="M81.17606160616063 510.66221198156677 L83.89265249998722 499.4556721982269 L92.1262283095085 507.04831530776835 z" fill="#555" stroke="none"/><text x="290.37307692307695" y="16" font-size="10" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">from ingress port</text><text x="290.37307692307695" y="16" font-size="10" text-anchor="middle" fill="#555">from ingress port</text><rect x="0" y="583.6622119815668" width="16" height="11" fill="#16a34a" stroke="#555"/><text x="21" y="593.1622119815668" font-size="11" fill="#1d1d1b">Forward — send the frame out the single learned egress port</text><rect x="0" y="603.6622119815668" width="16" height="11" fill="#2563eb" stroke="#555"/><text x="21" y="613.1622119815668" font-size="11" fill="#1d1d1b">Flood — send out every port in the VLAN except the ingress port</text><rect x="0" y="623.6622119815668" width="16" height="11" fill="#dc2626" stroke="#555"/><text x="21" y="633.1622119815668" font-size="11" fill="#1d1d1b">Filter — discard; destination is out the same port it arrived on</text></g><metadata id="figdown-source" data-sha256="a40dea326cd8c523f5fbe86e4a906de9acf7b3367a5b6f2cc9d4356e624d1b70" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 544 651" width="544" height="651" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="35" x1="290.37307692307695" y1="32" x2="290.37307692307695" y2="76" stroke="#555" stroke-width="1.6"/><line data-edge="36" x1="290.37307692307695" y1="144" x2="290.37307692307695" y2="188" stroke="#555" stroke-width="1.6"/><line data-edge="37" x1="290.37307692307695" y1="240" x2="290.37307692307695" y2="284" stroke="#555" stroke-width="1.6"/><line data-edge="39" x1="316.80398475528494" y1="333.30324720278287" x2="387.66843676737295" y2="386.74285714285713" stroke="#555" stroke-width="1.6"/><line data-edge="40" x1="266.24256332978035" y1="334.1248165738226" x2="191.637909323235" y2="398.2883630891489" stroke="#555" stroke-width="1.6"/><line data-edge="42" x1="186.46826779078154" y1="456.9233011944657" x2="236.0239383938394" y2="510.66221198156677" stroke="#555" stroke-width="1.6"/><line data-edge="43" x1="130.7317322092185" y1="456.9233011944657" x2="81.17606160616063" y2="510.66221198156677" stroke="#555" stroke-width="1.6"/><g data-node="learn" data-x="204.37307692307695" data-y="76" style="cursor:move"><rect x="204.37307692307695" y="76" width="172" height="68" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="97.64999999999999" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="290.37307692307695" dy="0">Learn source MAC:</tspan><tspan x="290.37307692307695" dy="16.900000000000002">update MAC table</tspan><tspan x="290.37307692307695" dy="16.900000000000002">(SA -&gt; ingress port)</tspan></text></g><g data-node="lookup" data-x="193.57307692307694" data-y="188" style="cursor:move"><rect x="193.57307692307694" y="188" width="193.6" height="52" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="210.10000000000002" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="290.37307692307695" dy="0">Look up destination MAC</tspan><tspan x="290.37307692307695" dy="16.900000000000002">in MAC table</tspan></text></g><g data-node="hit" data-x="208.13307692307694" data-y="284" style="cursor:move"><polygon points="290.37307692307695,284 372.61307692307696,313.37142857142857 290.37307692307695,342.74285714285713 208.13307692307694,313.37142857142857" fill="#fff" stroke="#8a8880"/><text x="290.37307692307695" y="317.9214285714286" font-size="13" text-anchor="middle" fill="#1d1d1b">Entry found?</text></g><g data-node="same" data-x="44.253846153846155" data-y="386.74285714285713" style="cursor:move"><polygon points="158.60000000000002,386.74285714285713 272.94615384615383,426.70253456221195 158.60000000000002,466.66221198156677 44.253846153846155,426.70253456221195" fill="#fff" stroke="#8a8880"/><text x="158.60000000000002" y="422.802534562212" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="158.60000000000002" dy="0">Egress port ==</tspan><tspan x="158.60000000000002" dy="16.900000000000002">ingress port?</tspan></text></g><g data-node="fwd" data-x="0" data-y="510.66221198156677" style="cursor:move"><rect x="0" y="510.66221198156677" width="114.4" height="52" rx="14" fill="#16a34a" stroke="#8a8880" stroke-width="1.8"/><text x="57.2" y="532.7622119815667" font-size="13" text-anchor="middle" fill="#1d1d1b"><tspan x="57.2" dy="0">Forward out</tspan><tspan x="57.2" dy="16.900000000000002">learned port</tspan></text></g><g data-node="fld" data-x="328.9461538461539" data-y="386.74285714285713" style="cursor:move"><rect x="328.9461538461539" y="386.74285714285713" width="186.4" height="52" rx="14" fill="#2563eb" stroke="#8a8880" stroke-width="1.8"/><text x="422.1461538461539" y="408.84285714285716" font-size="13" text-anchor="middle" fill="#ffffff"><tspan x="422.1461538461539" dy="0">Flood to all ports</tspan><tspan x="422.1461538461539" dy="16.900000000000002">in VLAN except ingress</tspan></text></g><g data-node="flt" data-x="170.4" data-y="510.66221198156677" style="cursor:move"><rect x="170.4" y="510.66221198156677" width="179.20000000000002" height="52" rx="14" fill="#dc2626" stroke="#8a8880" stroke-width="1.8"/><text x="260" y="532.7622119815667" font-size="13" text-anchor="middle" fill="#ffffff"><tspan x="260" dy="0">Filter (drop):</tspan><tspan x="260" dy="16.900000000000002">same-port destination</tspan></text></g><path d="M290.37307692307695 76 L284.7730769230769 65.92 L295.973076923077 65.92 z" fill="#555" stroke="none"/><path d="M290.37307692307695 188 L284.7730769230769 177.92 L295.973076923077 177.92 z" fill="#555" stroke="none"/><path d="M290.37307692307695 284 L284.7730769230769 273.92 L295.973076923077 273.92 z" fill="#555" stroke="none"/><text x="332.3941641979443" y="357.40996138959923" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">no</text><text x="332.3941641979443" y="357.40996138959923" font-size="11" text-anchor="middle" fill="#555">no</text><path d="M387.66843676737295 386.74285714285713 L376.2485927245621 385.1448702724861 L382.99209291771245 376.2025436655576 z" fill="#555" stroke="none"/><text x="249.82953944834037" y="360.5907968071944" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">yes</text><text x="249.82953944834037" y="360.5907968071944" font-size="11" text-anchor="middle" fill="#555">yes</text><path d="M191.637909323235 398.2883630891489 L195.62870077540882 387.46986117875224 L202.93177246717303 395.96133595436993 z" fill="#555" stroke="none"/><text x="207.33496897169888" y="476.34497443059604" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">yes</text><text x="207.33496897169888" y="476.34497443059604" font-size="11" text-anchor="start" fill="#555">yes</text><path d="M236.0239383938394 510.66221198156677 L225.07377169049153 507.04831530776835 L233.30734750001278 499.4556721982269 z" fill="#555" stroke="none"/><text x="121.86503102830115" y="476.34497443059604" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">no</text><text x="121.86503102830115" y="476.34497443059604" font-size="11" text-anchor="start" fill="#555">no</text><path d="M81.17606160616063 510.66221198156677 L83.89265249998722 499.4556721982269 L92.1262283095085 507.04831530776835 z" fill="#555" stroke="none"/><text x="290.37307692307695" y="16" font-size="10" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">from ingress port</text><text x="290.37307692307695" y="16" font-size="10" text-anchor="middle" fill="#555">from ingress port</text><rect x="0" y="583.6622119815668" width="16" height="11" fill="#16a34a" stroke="#555"/><text x="21" y="593.1622119815668" font-size="11" fill="#1d1d1b">Forward — send the frame out the single learned egress port</text><rect x="0" y="603.6622119815668" width="16" height="11" fill="#2563eb" stroke="#555"/><text x="21" y="613.1622119815668" font-size="11" fill="#1d1d1b">Flood — send out every port in the VLAN except the ingress port</text><rect x="0" y="623.6622119815668" width="16" height="11" fill="#dc2626" stroke="#555"/><text x="21" y="633.1622119815668" font-size="11" fill="#1d1d1b">Filter — discard; destination is out the same port it arrived on</text></g><metadata id="figdown-source" data-sha256="a40dea326cd8c523f5fbe86e4a906de9acf7b3367a5b6f2cc9d4356e624d1b70" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 flowchart
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 624 388" width="624" height="388" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="33" x1="172" y1="34.5" x2="358.5" y2="34.5" stroke="#2563eb" stroke-width="1.6"/><path data-edge="36" d="M476.9 56 L476.9 74 Q476.9 84 466.9 84 L96 84 Q86 84 86 74 L86 56" fill="none" stroke="#2563eb" stroke-width="1.6"/><line data-edge="41" x1="172" y1="41.5" x2="358.5" y2="41.5" stroke="#16a34a" stroke-width="1.6"/><g data-node="client" data-x="0" data-y="20" style="cursor:move"><rect x="0" y="20" width="172" height="36" fill="#fff" stroke="#8a8880"/><text x="86" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Client (active open)</text></g><g data-node="server" data-x="358.5" data-y="20" style="cursor:move"><rect x="358.5" y="20" width="236.8" height="36" fill="#fff" stroke="#8a8880"/><text x="476.9" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Server (passive open, LISTEN)</text></g><text x="265.25" y="28.75" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: SYN seq=x</text><text x="265.25" y="28.75" font-size="11" text-anchor="middle" fill="#2563eb">1: SYN seq=x</text><path d="M358.5 34.5 L348.42 40.1 L348.42 28.9 z" fill="#2563eb" stroke="none"/><text x="281.45" y="78.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">2: SYN,ACK seq=y ack=x+1</text><text x="281.45" y="78.25" font-size="11" text-anchor="middle" fill="#2563eb">2: SYN,ACK seq=y ack=x+1</text><path d="M86 56 L91.6 66.08 L80.4 66.08 z" fill="#2563eb" stroke="none"/><text x="265.25" y="53.85" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">3: ACK ack=y+1 (+ data)</text><text x="265.25" y="53.85" font-size="11" text-anchor="middle" fill="#16a34a">3: ACK ack=y+1 (+ data)</text><path d="M358.5 41.5 L348.42 47.1 L348.42 35.9 z" fill="#16a34a" stroke="none"/><rect x="0" y="121" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="130.5" font-size="11" fill="#1d1d1b">Connection-setup segment — carries SYN and/or ACK control flags</text><rect x="0" y="141" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="150.5" font-size="11" fill="#1d1d1b">Segment that also carries application data (piggybacked on the ACK)</text></g></g><g transform="translate(0,196)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Endpoint state after each segment (RFC 9293 §3.3.2 state names)</text><rect x="0" y="22" width="114.4" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:1" style="cursor:pointer"/><text x="57.2" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Segment</text><rect x="114.4" y="22" width="186.4" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:2" style="cursor:pointer"/><text x="207.60000000000002" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Client state</text><rect x="300.8" y="22" width="193.6" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:3" style="cursor:pointer"/><text x="397.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Server state</text><rect x="0" y="48" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">start</text><rect x="114.4" y="48" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:2" style="cursor:pointer"/><text x="121.4" y="65.3" font-size="12" text-anchor="start">CLOSED</text><rect x="300.8" y="48" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:3" style="cursor:pointer"/><text x="307.8" y="65.3" font-size="12" text-anchor="start">LISTEN</text><rect x="0" y="74" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">1: SYN →</text><rect x="114.4" y="74" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:2" style="cursor:pointer"/><text x="121.4" y="91.3" font-size="12" text-anchor="start">SYN-SENT</text><rect x="300.8" y="74" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:3" style="cursor:pointer"/><text x="307.8" y="91.3" font-size="12" text-anchor="start">SYN-RECEIVED on receipt</text><rect x="0" y="100" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">2: SYN,ACK ←</text><rect x="114.4" y="100" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:2" style="cursor:pointer"/><text x="121.4" y="117.3" font-size="12" text-anchor="start">ESTABLISHED on receipt</text><rect x="300.8" y="100" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:3" style="cursor:pointer"/><text x="307.8" y="117.3" font-size="12" text-anchor="start">SYN-RECEIVED</text><rect x="0" y="126" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:1" style="cursor:pointer"/><text x="7" y="143.3" font-size="12" text-anchor="start">3: ACK →</text><rect x="114.4" y="126" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:2" style="cursor:pointer"/><text x="121.4" y="143.3" font-size="12" text-anchor="start">ESTABLISHED</text><rect x="300.8" y="126" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:3" style="cursor:pointer"/><text x="307.8" y="143.3" font-size="12" text-anchor="start">ESTABLISHED on receipt</text></g></g><metadata id="figdown-source" data-sha256="deb9fdc0ac4b3caf600ad4ebd23afb19bb7b431c44c30a9b47ba70f87a1d4ad5" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 624 388" width="624" height="388" font-family="system-ui,sans-serif"><g transform="translate(0,0)"><defs><marker id="s0_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s0_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="33" x1="172" y1="34.5" x2="358.5" y2="34.5" stroke="#2563eb" stroke-width="1.6"/><path data-edge="36" d="M476.9 56 L476.9 74 Q476.9 84 466.9 84 L96 84 Q86 84 86 74 L86 56" fill="none" stroke="#2563eb" stroke-width="1.6"/><line data-edge="41" x1="172" y1="41.5" x2="358.5" y2="41.5" stroke="#16a34a" stroke-width="1.6"/><g data-node="client" data-x="0" data-y="20" style="cursor:move"><rect x="0" y="20" width="172" height="36" fill="#fff" stroke="#8a8880"/><text x="86" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Client (active open)</text></g><g data-node="server" data-x="358.5" data-y="20" style="cursor:move"><rect x="358.5" y="20" width="236.8" height="36" fill="#fff" stroke="#8a8880"/><text x="476.9" y="42.55" font-size="13" text-anchor="middle" fill="#1d1d1b">Server (passive open, LISTEN)</text></g><text x="265.25" y="28.75" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">1: SYN seq=x</text><text x="265.25" y="28.75" font-size="11" text-anchor="middle" fill="#2563eb">1: SYN seq=x</text><path d="M358.5 34.5 L348.42 40.1 L348.42 28.9 z" fill="#2563eb" stroke="none"/><text x="281.45" y="78.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">2: SYN,ACK seq=y ack=x+1</text><text x="281.45" y="78.25" font-size="11" text-anchor="middle" fill="#2563eb">2: SYN,ACK seq=y ack=x+1</text><path d="M86 56 L91.6 66.08 L80.4 66.08 z" fill="#2563eb" stroke="none"/><text x="265.25" y="53.85" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">3: ACK ack=y+1 (+ data)</text><text x="265.25" y="53.85" font-size="11" text-anchor="middle" fill="#16a34a">3: ACK ack=y+1 (+ data)</text><path d="M358.5 41.5 L348.42 47.1 L348.42 35.9 z" fill="#16a34a" stroke="none"/><rect x="0" y="121" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="130.5" font-size="11" fill="#1d1d1b">Connection-setup segment — carries SYN and/or ACK control flags</text><rect x="0" y="141" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="150.5" font-size="11" fill="#1d1d1b">Segment that also carries application data (piggybacked on the ACK)</text></g></g><g transform="translate(0,196)"><defs><marker id="s1_arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="s1_hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">Endpoint state after each segment (RFC 9293 §3.3.2 state names)</text><rect x="0" y="22" width="114.4" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:1" style="cursor:pointer"/><text x="57.2" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Segment</text><rect x="114.4" y="22" width="186.4" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:2" style="cursor:pointer"/><text x="207.60000000000002" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Client state</text><rect x="300.8" y="22" width="193.6" height="26" fill="#eeede6" stroke="#c9c7bf" data-cell="state:0:3" style="cursor:pointer"/><text x="397.6" y="39.3" font-size="12" text-anchor="middle" font-weight="600">Server state</text><rect x="0" y="48" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:1" style="cursor:pointer"/><text x="7" y="65.3" font-size="12" text-anchor="start">start</text><rect x="114.4" y="48" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:2" style="cursor:pointer"/><text x="121.4" y="65.3" font-size="12" text-anchor="start">CLOSED</text><rect x="300.8" y="48" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:1:3" style="cursor:pointer"/><text x="307.8" y="65.3" font-size="12" text-anchor="start">LISTEN</text><rect x="0" y="74" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:1" style="cursor:pointer"/><text x="7" y="91.3" font-size="12" text-anchor="start">1: SYN →</text><rect x="114.4" y="74" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:2" style="cursor:pointer"/><text x="121.4" y="91.3" font-size="12" text-anchor="start">SYN-SENT</text><rect x="300.8" y="74" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:2:3" style="cursor:pointer"/><text x="307.8" y="91.3" font-size="12" text-anchor="start">SYN-RECEIVED on receipt</text><rect x="0" y="100" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:1" style="cursor:pointer"/><text x="7" y="117.3" font-size="12" text-anchor="start">2: SYN,ACK ←</text><rect x="114.4" y="100" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:2" style="cursor:pointer"/><text x="121.4" y="117.3" font-size="12" text-anchor="start">ESTABLISHED on receipt</text><rect x="300.8" y="100" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:3:3" style="cursor:pointer"/><text x="307.8" y="117.3" font-size="12" text-anchor="start">SYN-RECEIVED</text><rect x="0" y="126" width="114.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:1" style="cursor:pointer"/><text x="7" y="143.3" font-size="12" text-anchor="start">3: ACK →</text><rect x="114.4" y="126" width="186.4" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:2" style="cursor:pointer"/><text x="121.4" y="143.3" font-size="12" text-anchor="start">ESTABLISHED</text><rect x="300.8" y="126" width="193.6" height="26" fill="#fff" stroke="#c9c7bf" data-cell="state:4:3" style="cursor:pointer"/><text x="307.8" y="143.3" font-size="12" text-anchor="start">ESTABLISHED on receipt</text></g></g><metadata id="figdown-source" data-sha256="deb9fdc0ac4b3caf600ad4ebd23afb19bb7b431c44c30a9b47ba70f87a1d4ad5" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 topology
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 764 332" width="764" height="332" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">TCP Header (RFC 9293)</text><text x="11.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">0</text><text x="34.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">1</text><text x="57.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">2</text><text x="80.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">3</text><text x="103.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">4</text><text x="126.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">5</text><text x="149.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">6</text><text x="172.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">7</text><text x="195.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">8</text><text x="218.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">9</text><text x="241.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">10</text><text x="264.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">11</text><text x="287.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">12</text><text x="310.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">13</text><text x="333.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">14</text><text x="356.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">15</text><text x="379.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">16</text><text x="402.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">17</text><text x="425.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">18</text><text x="448.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">19</text><text x="471.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">20</text><text x="494.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">21</text><text x="517.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">22</text><text x="540.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">23</text><text x="563.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">24</text><text x="586.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">25</text><text x="609.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">26</text><text x="632.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">27</text><text x="655.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">28</text><text x="678.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">29</text><text x="701.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">30</text><text x="724.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">31</text><rect x="0" y="34" width="368" height="30" fill="#fff" stroke="#555"/><text x="184" y="52.85" font-size="11" text-anchor="middle">Source Port</text><rect x="368" y="34" width="368" height="30" fill="#fff" stroke="#555"/><text x="552" y="52.85" font-size="11" text-anchor="middle">Destination Port</text><rect x="0" y="64" width="736" height="30" fill="#fff" stroke="#555"/><text x="368" y="82.85" font-size="11" text-anchor="middle">Sequence Number</text><rect x="0" y="94" width="736" height="30" fill="#fff" stroke="#555"/><text x="368" y="112.85" font-size="11" text-anchor="middle">Acknowledgment Number</text><rect x="0" y="124" width="92" height="30" fill="#fff" stroke="#555"><title>header length in 32-bit words; min 5 (=20 bytes), max 15 (=60 bytes)</title></rect><text x="46" y="142.85" font-size="11" text-anchor="middle">Data Offset</text><rect x="92" y="124" width="92" height="30" fill="#fff" stroke="#555"><title>must be zero</title></rect><text x="138" y="142.85" font-size="11" text-anchor="middle">Reserved</text><rect x="184" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="195.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">CWR</text><rect x="207" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="218.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">ECE</text><rect x="230" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="241.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">URG</text><rect x="253" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="264.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">ACK</text><rect x="276" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="287.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">PSH</text><rect x="299" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="310.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">RST</text><rect x="322" y="124" width="23" height="30" fill="#fee2e2" stroke="#555"/><text x="333.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">SYN</text><rect x="345" y="124" width="23" height="30" fill="#fee2e2" stroke="#555"/><text x="356.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">FIN</text><rect x="368" y="124" width="368" height="30" fill="#fff" stroke="#555"><title>receive window size in bytes (subject to window scaling option)</title></rect><text x="552" y="142.85" font-size="11" text-anchor="middle">Window</text><rect x="0" y="154" width="368" height="30" fill="#fff" stroke="#555"/><text x="184" y="172.85" font-size="11" text-anchor="middle">Checksum</text><rect x="368" y="154" width="368" height="30" fill="#fff" stroke="#555"/><text x="552" y="172.85" font-size="11" text-anchor="middle">Urgent Pointer</text><rect x="0" y="184" width="736" height="30" fill="#fff" stroke="#555" stroke-dasharray="5 3"><title>0-320 bits (0-40 octets), always a multiple of 32, padded to a 32-bit boundary — RFC 9293 §3.1</title></rect><text x="368" y="202.85" font-size="11" text-anchor="middle">Options</text><rect x="0" y="214" width="736" height="30" fill="#fff" stroke="#555"><title>variable-length payload; length derived from the IP datagram, not carried in the TCP header</title></rect><text x="368" y="232.85" font-size="11" text-anchor="middle">Data</text><text x="0" y="263" font-size="10.5" fill="#6f6e69">Options — present: Data Offset &gt; 5</text><text x="0" y="314.5" font-size="11" fill="#1d1d1b">Width is VARIABLE on the wire; the declared width is one representative word, not the field's length</text></g><metadata id="figdown-source" data-sha256="71ea53c27bd8adc9b27608ff6be740dea8ebc14e3cf8a663d5dd137f195d2b6e" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 764 332" width="764" height="332" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><text x="0" y="14" font-size="13" font-weight="600">TCP Header (RFC 9293)</text><text x="11.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">0</text><text x="34.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">1</text><text x="57.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">2</text><text x="80.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">3</text><text x="103.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">4</text><text x="126.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">5</text><text x="149.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">6</text><text x="172.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">7</text><text x="195.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">8</text><text x="218.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">9</text><text x="241.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">10</text><text x="264.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">11</text><text x="287.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">12</text><text x="310.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">13</text><text x="333.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">14</text><text x="356.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">15</text><text x="379.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">16</text><text x="402.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">17</text><text x="425.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">18</text><text x="448.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">19</text><text x="471.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">20</text><text x="494.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">21</text><text x="517.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">22</text><text x="540.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">23</text><text x="563.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">24</text><text x="586.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">25</text><text x="609.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">26</text><text x="632.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">27</text><text x="655.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">28</text><text x="678.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">29</text><text x="701.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">30</text><text x="724.5" y="29" font-size="8.5" text-anchor="middle" fill="#6f6e69">31</text><rect x="0" y="34" width="368" height="30" fill="#fff" stroke="#555"/><text x="184" y="52.85" font-size="11" text-anchor="middle">Source Port</text><rect x="368" y="34" width="368" height="30" fill="#fff" stroke="#555"/><text x="552" y="52.85" font-size="11" text-anchor="middle">Destination Port</text><rect x="0" y="64" width="736" height="30" fill="#fff" stroke="#555"/><text x="368" y="82.85" font-size="11" text-anchor="middle">Sequence Number</text><rect x="0" y="94" width="736" height="30" fill="#fff" stroke="#555"/><text x="368" y="112.85" font-size="11" text-anchor="middle">Acknowledgment Number</text><rect x="0" y="124" width="92" height="30" fill="#fff" stroke="#555"><title>header length in 32-bit words; min 5 (=20 bytes), max 15 (=60 bytes)</title></rect><text x="46" y="142.85" font-size="11" text-anchor="middle">Data Offset</text><rect x="92" y="124" width="92" height="30" fill="#fff" stroke="#555"><title>must be zero</title></rect><text x="138" y="142.85" font-size="11" text-anchor="middle">Reserved</text><rect x="184" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="195.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">CWR</text><rect x="207" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="218.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">ECE</text><rect x="230" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="241.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">URG</text><rect x="253" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="264.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">ACK</text><rect x="276" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="287.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">PSH</text><rect x="299" y="124" width="23" height="30" fill="#fff" stroke="#555"/><text x="310.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">RST</text><rect x="322" y="124" width="23" height="30" fill="#fee2e2" stroke="#555"/><text x="333.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">SYN</text><rect x="345" y="124" width="23" height="30" fill="#fee2e2" stroke="#555"/><text x="356.5" y="142.5188172043011" font-size="10.053763440860214" text-anchor="middle">FIN</text><rect x="368" y="124" width="368" height="30" fill="#fff" stroke="#555"><title>receive window size in bytes (subject to window scaling option)</title></rect><text x="552" y="142.85" font-size="11" text-anchor="middle">Window</text><rect x="0" y="154" width="368" height="30" fill="#fff" stroke="#555"/><text x="184" y="172.85" font-size="11" text-anchor="middle">Checksum</text><rect x="368" y="154" width="368" height="30" fill="#fff" stroke="#555"/><text x="552" y="172.85" font-size="11" text-anchor="middle">Urgent Pointer</text><rect x="0" y="184" width="736" height="30" fill="#fff" stroke="#555" stroke-dasharray="5 3"><title>0-320 bits (0-40 octets), always a multiple of 32, padded to a 32-bit boundary — RFC 9293 §3.1</title></rect><text x="368" y="202.85" font-size="11" text-anchor="middle">Options</text><rect x="0" y="214" width="736" height="30" fill="#fff" stroke="#555"><title>variable-length payload; length derived from the IP datagram, not carried in the TCP header</title></rect><text x="368" y="232.85" font-size="11" text-anchor="middle">Data</text><text x="0" y="263" font-size="10.5" fill="#6f6e69">Options — present: Data Offset &gt; 5</text><text x="0" y="314.5" font-size="11" fill="#1d1d1b">Width is VARIABLE on the wire; the declared width is one representative word, not the field's length</text></g><metadata id="figdown-source" data-sha256="71ea53c27bd8adc9b27608ff6be740dea8ebc14e3cf8a663d5dd137f195d2b6e" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 bitfield
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 888 984" width="888" height="984" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="70" x1="433.1" y1="76" x2="433.1" y2="190" stroke="#2563eb" stroke-width="1.6"/><line data-edge="71" x1="452.7652886772431" y1="73.34906513439799" x2="724.2052886772431" y2="307.34906513439796" stroke="#2563eb" stroke-width="1.6"/><line data-edge="72" x1="465.20000000000005" y1="221.63984674329504" x2="700" y2="311.6015325670498" stroke="#2563eb" stroke-width="1.6"/><line data-edge="73" x1="395.5028227438559" y1="228.0864522267111" x2="216.56282274385592" y2="313.1609371712436" stroke="#2563eb" stroke-width="1.6"/><line data-edge="74" x1="700" y1="328" x2="234.39999999999998" y2="328" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="75" x1="700" y1="344.3984674329502" x2="476.58000000000004" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="76" x1="215.06" y1="346" x2="391.74" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="79" x1="426.1" y1="190" x2="426.1" y2="76" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="80" x1="719.6347113227569" y1="312.65093486560204" x2="448.1947113227569" y2="78.65093486560201" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="81" x1="213.5571772561441" y1="306.8390628287564" x2="392.4971772561441" y2="221.76457788422394" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="84" x1="179.4896" y1="346" x2="206.7104" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="85" x1="399.05538461538464" y1="466" x2="239.54461538461538" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="86" x1="209" y1="596" x2="209" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="87" x1="228.55076923076922" y1="596" x2="330.64923076923077" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="88" x1="218.78923076923076" y1="596" x2="340.6107692307692" y2="820" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="89" x1="228.57846153846154" y1="726" x2="330.82153846153847" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="90" x1="350.2276923076923" y1="726" x2="350.3723076923077" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="91" x1="396.79999999999995" y1="838" x2="697" y2="838" stroke="#dc2626" stroke-width="1.6"/><line data-edge="94" x1="472.57846153846157" y1="466" x2="697.0215384615385" y2="560" stroke="#16a34a" stroke-width="1.6"/><line data-edge="95" x1="739.003076923077" y1="596" x2="733.796923076923" y2="690" stroke="#16a34a" stroke-width="1.6"/><line data-edge="96" x1="732.7723076923077" y1="726" x2="732.6276923076923" y2="820" stroke="#16a34a" stroke-width="1.6"/><g data-node="closed" data-x="394" data-y="40" style="cursor:move"><rect x="394" y="40" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="62.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><g data-node="listen" data-x="394" data-y="190" style="cursor:move"><rect x="394" y="190" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="212.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LISTEN</text></g><g data-node="synsent" data-x="700" data-y="310" style="cursor:move"><rect x="700" y="310" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="742.8" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-SENT</text></g><g data-node="synrcvd" data-x="120" data-y="310" style="cursor:move"><rect x="120" y="310" width="114.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="177.2" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-RECEIVED</text></g><g data-node="estab" data-x="376" data-y="430" style="cursor:move"><rect x="376" y="430" width="107.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="452.55" font-size="13" text-anchor="middle" fill="#1d1d1b">ESTABLISHED</text></g><g data-node="fw1" data-x="159" data-y="560" style="cursor:move"><rect x="159" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-1</text></g><g data-node="fw2" data-x="159" data-y="690" style="cursor:move"><rect x="159" y="690" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-2</text></g><g data-node="closing" data-x="311" data-y="690" style="cursor:move"><rect x="311" y="690" width="78.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.2" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSING</text></g><g data-node="closewait" data-x="690" data-y="560" style="cursor:move"><rect x="690" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="740" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSE-WAIT</text></g><g data-node="lastack" data-x="690" data-y="690" style="cursor:move"><rect x="690" y="690" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.8" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LAST-ACK</text></g><g data-node="timewait" data-x="304" data-y="820" style="cursor:move"><rect x="304" y="820" width="92.8" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.4" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">TIME-WAIT</text></g><g data-node="closed2" data-x="697" data-y="820" style="cursor:move"><rect x="697" y="820" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.6" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">passive OPEN / create TCB</text><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#2563eb">passive OPEN / create TCB</text><path d="M433.1 190 L427.5 179.92 L438.70000000000005 179.92 z" fill="#2563eb" stroke="none"/><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">active OPEN / create TCB, snd SYN</text><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#2563eb">active OPEN / create TCB, snd SYN</text><path d="M724.2052886772431 307.34906513439796 L712.9141343807203 305.008929528901 L720.2270581478983 296.52593795897457 z" fill="#2563eb" stroke="none"/><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">SEND / snd SYN</text><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#2563eb">SEND / snd SYN</text><path d="M700 311.6015325670498 L688.5836683972988 313.224422808922 L692.5908047969832 302.76579680574537 z" fill="#2563eb" stroke="none"/><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN / snd SYN,ACK</text><path d="M216.56282274385592 313.1609371712436 L223.261805406868 303.7753081949488 L228.0708381872069 313.89030714292835 z" fill="#2563eb" stroke="none"/><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#9333ea">rcv SYN / snd SYN,ACK</text><path d="M234.39999999999998 328 L244.48 322.4 L244.48 333.6 z" fill="#9333ea" stroke="none"/><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN,ACK / snd ACK</text><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN,ACK / snd ACK</text><path d="M476.58000000000004 430 L483.9891952030168 421.1642642386956 L487.99633160270133 431.6228902418722 z" fill="#2563eb" stroke="none"/><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of SYN / x</text><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#2563eb">rcv ACK of SYN / x</text><path d="M391.74 430 L380.231984556649 430.7293699716848 L385.041017336988 420.61437102370525 z" fill="#2563eb" stroke="none"/><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#9333ea">CLOSE / delete TCB</text><path d="M426.1 76 L431.70000000000005 86.08 L420.5 86.08 z" fill="#9333ea" stroke="none"/><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#9333ea">CLOSE / delete TCB</text><path d="M448.1947113227569 78.65093486560201 L459.4858656192797 80.99107047109896 L452.17294185210176 89.47406204102543 z" fill="#9333ea" stroke="none"/><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv RST (note 1) / x</text><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#9333ea">rcv RST (note 1) / x</text><path d="M392.4971772561441 221.76457788422394 L385.79819459313205 231.1502068605187 L380.9891618127931 221.03520791253922 z" fill="#9333ea" stroke="none"/><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#dc2626">CLOSE / snd FIN</text><path d="M206.7104 560 L199.88323361107894 550.7071963811783 L210.99371139541864 549.2939436070102 z" fill="#dc2626" stroke="none"/><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#dc2626">CLOSE / snd FIN</text><path d="M239.54461538461538 560 L245.38572668223014 550.0577759626491 L251.0719964792192 559.7069384027706 z" fill="#dc2626" stroke="none"/><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M209 690 L203.4 679.92 L214.6 679.92 z" fill="#dc2626" stroke="none"/><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.64923076923077 690 L319.4405255167678 687.2923577482596 L327.02659217035057 679.0527222752913 z" fill="#dc2626" stroke="none"/><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN,ACK / snd ACK</text><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#9333ea">rcv FIN,ACK / snd ACK</text><path d="M340.6107692307692 820 L330.875382512483 813.820303774018 L340.7144579488292 808.469360440559 z" fill="#9333ea" stroke="none"/><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.82153846153847 820 L319.61092639723944 817.3002635047485 L327.19118005561285 809.0552799101793 z" fill="#dc2626" stroke="none"/><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M350.3723076923077 820 L344.75680664555944 809.9286273033927 L355.9567933911451 809.9113965545532 z" fill="#dc2626" stroke="none"/><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">Timeout=2MSL / delete TCB</text><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#dc2626">Timeout=2MSL / delete TCB</text><path d="M697 838 L686.92 843.6 L686.92 832.4 z" fill="#dc2626" stroke="none"/><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#16a34a">rcv FIN / snd ACK</text><path d="M697.0215384615385 560 L685.5607329004544 561.2713519933599 L689.8873234537733 550.9407850106658 z" fill="#16a34a" stroke="none"/><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">CLOSE / snd FIN</text><path d="M733.796923076923 690 L728.7629148866224 679.6257452537551 L739.9457765533873 680.2451037460681 z" fill="#16a34a" stroke="none"/><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">rcv ACK of FIN / x</text><path d="M732.6276923076923 820 L727.0432066088549 809.9113965545532 L738.2431933544406 809.9286273033927 z" fill="#16a34a" stroke="none"/><rect x="0" y="877" width="16" height="11" fill="#eef2ff" stroke="#555"/><text x="21" y="886.5" font-size="11" fill="#1d1d1b">A node IS a TCP state (RFC 9293 §3.3.2); the two CLOSED nodes are one state drawn twice — only this label says so</text><rect x="0" y="897" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="906.5" font-size="11" fill="#1d1d1b">Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)</text><rect x="0" y="917" width="16" height="11" fill="#fff" stroke="#dc2626"/><text x="21" y="926.5" font-size="11" fill="#1d1d1b">Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED</text><rect x="0" y="937" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="946.5" font-size="11" fill="#1d1d1b">Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED</text><rect x="0" y="957" width="16" height="11" fill="#fff" stroke="#9333ea" stroke-dasharray="6 4"/><text x="21" y="966.5" font-size="11" fill="#1d1d1b">Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)</text></g><metadata id="figdown-source" data-sha256="8c7cba9f05b9da4dfe03b8c3fe8cc1f6f8983fe67703351f442602c4d0f7157a" data-engine-version="0.1.0"><![CDATA[
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 888 984" width="888" height="984" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="70" x1="433.1" y1="76" x2="433.1" y2="190" stroke="#2563eb" stroke-width="1.6"/><line data-edge="71" x1="452.7652886772431" y1="73.34906513439799" x2="724.2052886772431" y2="307.34906513439796" stroke="#2563eb" stroke-width="1.6"/><line data-edge="72" x1="465.20000000000005" y1="221.63984674329504" x2="700" y2="311.6015325670498" stroke="#2563eb" stroke-width="1.6"/><line data-edge="73" x1="395.5028227438559" y1="228.0864522267111" x2="216.56282274385592" y2="313.1609371712436" stroke="#2563eb" stroke-width="1.6"/><line data-edge="74" x1="700" y1="328" x2="234.39999999999998" y2="328" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="75" x1="700" y1="344.3984674329502" x2="476.58000000000004" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="76" x1="215.06" y1="346" x2="391.74" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="79" x1="426.1" y1="190" x2="426.1" y2="76" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="80" x1="719.6347113227569" y1="312.65093486560204" x2="448.1947113227569" y2="78.65093486560201" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="81" x1="213.5571772561441" y1="306.8390628287564" x2="392.4971772561441" y2="221.76457788422394" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="84" x1="179.4896" y1="346" x2="206.7104" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="85" x1="399.05538461538464" y1="466" x2="239.54461538461538" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="86" x1="209" y1="596" x2="209" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="87" x1="228.55076923076922" y1="596" x2="330.64923076923077" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="88" x1="218.78923076923076" y1="596" x2="340.6107692307692" y2="820" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="89" x1="228.57846153846154" y1="726" x2="330.82153846153847" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="90" x1="350.2276923076923" y1="726" x2="350.3723076923077" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="91" x1="396.79999999999995" y1="838" x2="697" y2="838" stroke="#dc2626" stroke-width="1.6"/><line data-edge="94" x1="472.57846153846157" y1="466" x2="697.0215384615385" y2="560" stroke="#16a34a" stroke-width="1.6"/><line data-edge="95" x1="739.003076923077" y1="596" x2="733.796923076923" y2="690" stroke="#16a34a" stroke-width="1.6"/><line data-edge="96" x1="732.7723076923077" y1="726" x2="732.6276923076923" y2="820" stroke="#16a34a" stroke-width="1.6"/><g data-node="closed" data-x="394" data-y="40" style="cursor:move"><rect x="394" y="40" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="62.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><g data-node="listen" data-x="394" data-y="190" style="cursor:move"><rect x="394" y="190" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="212.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LISTEN</text></g><g data-node="synsent" data-x="700" data-y="310" style="cursor:move"><rect x="700" y="310" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="742.8" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-SENT</text></g><g data-node="synrcvd" data-x="120" data-y="310" style="cursor:move"><rect x="120" y="310" width="114.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="177.2" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-RECEIVED</text></g><g data-node="estab" data-x="376" data-y="430" style="cursor:move"><rect x="376" y="430" width="107.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="452.55" font-size="13" text-anchor="middle" fill="#1d1d1b">ESTABLISHED</text></g><g data-node="fw1" data-x="159" data-y="560" style="cursor:move"><rect x="159" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-1</text></g><g data-node="fw2" data-x="159" data-y="690" style="cursor:move"><rect x="159" y="690" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-2</text></g><g data-node="closing" data-x="311" data-y="690" style="cursor:move"><rect x="311" y="690" width="78.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.2" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSING</text></g><g data-node="closewait" data-x="690" data-y="560" style="cursor:move"><rect x="690" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="740" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSE-WAIT</text></g><g data-node="lastack" data-x="690" data-y="690" style="cursor:move"><rect x="690" y="690" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.8" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LAST-ACK</text></g><g data-node="timewait" data-x="304" data-y="820" style="cursor:move"><rect x="304" y="820" width="92.8" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.4" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">TIME-WAIT</text></g><g data-node="closed2" data-x="697" data-y="820" style="cursor:move"><rect x="697" y="820" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.6" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">passive OPEN / create TCB</text><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#2563eb">passive OPEN / create TCB</text><path d="M433.1 190 L427.5 179.92 L438.70000000000005 179.92 z" fill="#2563eb" stroke="none"/><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">active OPEN / create TCB, snd SYN</text><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#2563eb">active OPEN / create TCB, snd SYN</text><path d="M724.2052886772431 307.34906513439796 L712.9141343807203 305.008929528901 L720.2270581478983 296.52593795897457 z" fill="#2563eb" stroke="none"/><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">SEND / snd SYN</text><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#2563eb">SEND / snd SYN</text><path d="M700 311.6015325670498 L688.5836683972988 313.224422808922 L692.5908047969832 302.76579680574537 z" fill="#2563eb" stroke="none"/><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN / snd SYN,ACK</text><path d="M216.56282274385592 313.1609371712436 L223.261805406868 303.7753081949488 L228.0708381872069 313.89030714292835 z" fill="#2563eb" stroke="none"/><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#9333ea">rcv SYN / snd SYN,ACK</text><path d="M234.39999999999998 328 L244.48 322.4 L244.48 333.6 z" fill="#9333ea" stroke="none"/><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN,ACK / snd ACK</text><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN,ACK / snd ACK</text><path d="M476.58000000000004 430 L483.9891952030168 421.1642642386956 L487.99633160270133 431.6228902418722 z" fill="#2563eb" stroke="none"/><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of SYN / x</text><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#2563eb">rcv ACK of SYN / x</text><path d="M391.74 430 L380.231984556649 430.7293699716848 L385.041017336988 420.61437102370525 z" fill="#2563eb" stroke="none"/><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#9333ea">CLOSE / delete TCB</text><path d="M426.1 76 L431.70000000000005 86.08 L420.5 86.08 z" fill="#9333ea" stroke="none"/><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#9333ea">CLOSE / delete TCB</text><path d="M448.1947113227569 78.65093486560201 L459.4858656192797 80.99107047109896 L452.17294185210176 89.47406204102543 z" fill="#9333ea" stroke="none"/><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv RST (note 1) / x</text><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#9333ea">rcv RST (note 1) / x</text><path d="M392.4971772561441 221.76457788422394 L385.79819459313205 231.1502068605187 L380.9891618127931 221.03520791253922 z" fill="#9333ea" stroke="none"/><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#dc2626">CLOSE / snd FIN</text><path d="M206.7104 560 L199.88323361107894 550.7071963811783 L210.99371139541864 549.2939436070102 z" fill="#dc2626" stroke="none"/><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#dc2626">CLOSE / snd FIN</text><path d="M239.54461538461538 560 L245.38572668223014 550.0577759626491 L251.0719964792192 559.7069384027706 z" fill="#dc2626" stroke="none"/><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M209 690 L203.4 679.92 L214.6 679.92 z" fill="#dc2626" stroke="none"/><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.64923076923077 690 L319.4405255167678 687.2923577482596 L327.02659217035057 679.0527222752913 z" fill="#dc2626" stroke="none"/><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN,ACK / snd ACK</text><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#9333ea">rcv FIN,ACK / snd ACK</text><path d="M340.6107692307692 820 L330.875382512483 813.820303774018 L340.7144579488292 808.469360440559 z" fill="#9333ea" stroke="none"/><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.82153846153847 820 L319.61092639723944 817.3002635047485 L327.19118005561285 809.0552799101793 z" fill="#dc2626" stroke="none"/><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M350.3723076923077 820 L344.75680664555944 809.9286273033927 L355.9567933911451 809.9113965545532 z" fill="#dc2626" stroke="none"/><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">Timeout=2MSL / delete TCB</text><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#dc2626">Timeout=2MSL / delete TCB</text><path d="M697 838 L686.92 843.6 L686.92 832.4 z" fill="#dc2626" stroke="none"/><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#16a34a">rcv FIN / snd ACK</text><path d="M697.0215384615385 560 L685.5607329004544 561.2713519933599 L689.8873234537733 550.9407850106658 z" fill="#16a34a" stroke="none"/><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">CLOSE / snd FIN</text><path d="M733.796923076923 690 L728.7629148866224 679.6257452537551 L739.9457765533873 680.2451037460681 z" fill="#16a34a" stroke="none"/><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">rcv ACK of FIN / x</text><path d="M732.6276923076923 820 L727.0432066088549 809.9113965545532 L738.2431933544406 809.9286273033927 z" fill="#16a34a" stroke="none"/><rect x="0" y="877" width="16" height="11" fill="#eef2ff" stroke="#555"/><text x="21" y="886.5" font-size="11" fill="#1d1d1b">A node IS a TCP state (RFC 9293 §3.3.2); the two CLOSED nodes are one state drawn twice — only this label says so</text><rect x="0" y="897" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="906.5" font-size="11" fill="#1d1d1b">Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)</text><rect x="0" y="917" width="16" height="11" fill="#fff" stroke="#dc2626"/><text x="21" y="926.5" font-size="11" fill="#1d1d1b">Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED</text><rect x="0" y="937" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="946.5" font-size="11" fill="#1d1d1b">Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED</text><rect x="0" y="957" width="16" height="11" fill="#fff" stroke="#9333ea" stroke-dasharray="6 4"/><text x="21" y="966.5" font-size="11" fill="#1d1d1b">Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)</text></g><metadata id="figdown-source" data-sha256="8c7cba9f05b9da4dfe03b8c3fe8cc1f6f8983fe67703351f442602c4d0f7157a" data-engine-version="0.1.2"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 flowchart
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figdown",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Figures as text — one source, two readers: a closed, deterministic figure language for Markdown, readable by AI agents and humans alike",
5
5
  "license": "MIT",
6
6
  "author": "FigDown <hello@figdown.org>",
@@ -43,6 +43,7 @@
43
43
  "gate:legend": "node tools/legend-check.js --strict",
44
44
  "gate:registry": "node tools/registry-check.js --strict",
45
45
  "gate:capability": "node tools/capability-coverage.js --strict",
46
+ "gate:archive": "node tools/archive-check.js --strict",
46
47
  "gates:list": "node -e \"const s=require(process.cwd()+'/package.json').scripts||{};const g=Object.keys(s).filter(k=>k.startsWith('gate:'));if(!g.length){console.error('gates:list — no gate:* scripts found');process.exit(2);}if(process.env.GATES_JSON)console.log(JSON.stringify(g));else g.forEach(k=>console.log(k+' -> '+s[k]));\"",
47
48
  "test": "node -e \"const s=require(process.cwd()+'/package.json').scripts||{};const sp=require('child_process').spawnSync;const g=Object.keys(s).filter(k=>k.startsWith('gate:'));if(!g.length){console.error('npm test — no gate:* scripts found; refusing to report success');process.exit(2);}const bad=[];g.forEach(k=>{const a=s[k].split(' ');const bin=a[0]==='node'?process.execPath:a[0];console.log('');console.log('=== GATE '+k+' ['+s[k]+'] ===');const r=sp(bin,a.slice(1),{stdio:'inherit'});if(r.error)console.error(' spawn error: '+r.error.message);const c=(r.status===null||r.status===undefined)?1:r.status;console.log('--- '+k+': '+(c===0?'PASS':'FAIL (exit '+c+')')+' ---');if(c!==0)bad.push(k+' ['+s[k]+'] exit '+c);});console.log('');console.log('=== GATE SUMMARY: '+(g.length-bad.length)+'/'+g.length+' passed ===');if(bad.length){console.log('FAILED GATES:');bad.forEach(b=>console.log(' '+b));process.exit(1);}console.log('ALL GATES GREEN');\"",
48
49
  "gate:reference": "node tools/reference-gate.js"
@@ -31,12 +31,16 @@ the figure do prose's job.
31
31
  2. Build + validate: `node <this-skill-dir>/build-svg.js X.fd`
32
32
  Errors come as `Line N: message` — fix and rerun until `OK`. Titles are not
33
33
  drawn by default (Markdown supplies the caption); `--with-title` opts in.
34
- 3. Embed in Markdown — the SVG only, never `.fd` content:
34
+ 3. Embed in Markdown — the SVG only, never `.fd` content. Below, `X` is the
35
+ basename from step 1 and both paths are written relative to the **host
36
+ document**, not to this skill. The source footer is the convention that
37
+ lets a later reader find the `.fd` behind a rendered figure, so it is
38
+ written on every embed:
35
39
 
36
40
  ```markdown
37
- ![Ingress datapath](figures/ingress.svg)
41
+ ![What the figure shows](figures/X.svg)
38
42
 
39
- <sub>source: [figures/ingress.fd](figures/ingress.fd)</sub>
43
+ <sub>source: [figures/X.fd](figures/X.fd)</sub>
40
44
  ```
41
45
 
42
46
  4. Keep `X.fd` and `X.svg` side by side, same basename; commit both.
@@ -48,6 +52,50 @@ Recover from there. On hash mismatch the `.fd` is truth: rebuild. If the hash
48
52
  matches but your drawing differs, compare `data-engine-version` — that is the
49
53
  other half of "same source → same SVG".
50
54
 
55
+ ## When the figure comes from a source
56
+
57
+ Drawing is step 5 of 6. The steps before it decide what is true; the step after
58
+ it is how you find out you were wrong.
59
+
60
+ **1 — Get the structure out, don't look at the picture.** Containers ship a
61
+ drawing twice: the editable object and a flat render of it. The render is not
62
+ the source. Open the container, take the object, and read nodes, edges and
63
+ labels from it. Vision is for flat pixels with no structure left, and
64
+ everything it produces is a hypothesis until checked.
65
+
66
+ **2 — Let the extraction pick the genre.** Many text shapes and no connectors
67
+ is not a graph: it is a `table`. Conditions with one outcome per combination is
68
+ a `table`, not a `flowchart` — drawn as a chart it buys crossing edges and
69
+ nothing else. Two mirrored mechanisms are two figures. A run in which most of a
70
+ page's figures become tables is a correct run.
71
+
72
+ **3 — Separate what the source states from what you concluded.** Write the
73
+ stated thing; for the rest, leave a `#` comment at the point of doubt and list
74
+ it where the host document can count it. A length the source does not give
75
+ stays the unresolved marker its genre provides, a condition the source states
76
+ goes in the genre's own condition key rather than into a label, and a value it
77
+ words in prose stays worded — resolving any of them is fabrication with a
78
+ plausible face.
79
+
80
+ **4 — Keep the original.** Store it beside the `.fd` and never delete it: a
81
+ later reader may find a misread, and the fix needs the ground truth. After
82
+ that, the `.fd` changes only when understanding changes.
83
+
84
+ **5 — Draw.**
85
+
86
+ **6 — Verify, and be able to fail.** Diff your `.fd` against the extracted
87
+ structure: same node set, same edge set, same labels. This is what catches an
88
+ invented node and a dropped edge — neither is visible in a picture that looks
89
+ fine. Then build and **look at the render**. Lint and crossing counts are a
90
+ smoke alarm, not a judge. A figure is not done because the file exists; it is
91
+ done when it has been compared and seen.
92
+
93
+ **Across a corpus:** one figure per session, one tool call per figure; never
94
+ read a large extraction whole; two failures on a step means halve the step;
95
+ keep progress in a file, not in the session. Check once per corpus that every
96
+ figure has both `.fd` and `.svg`, that every embed resolves, and that every
97
+ recorded uncertainty is still recorded.
98
+
51
99
  ## Load only what you need
52
100
 
53
101
  This file is the whole genre-independent language. **Everything else is one
@@ -121,7 +121,7 @@ const SHAPES = ['box','rounded','circle','ellipse','diamond','cylinder'];
121
121
  // input to that promise, and under core §13 a 0.x renderer may differ from
122
122
  // the next — which makes the recorded version the only thing that can
123
123
  // explain a diff between two renderings of one source.
124
- const FIGDOWN_VERSION = '0.1.0';
124
+ const FIGDOWN_VERSION = '0.1.2';
125
125
  // Retired shape VALUES keep a named diagnostic (PROCESS §5(d)), the same way
126
126
  // retired option keys do: `cloud` was the one value that named a domain
127
127
  // (the internet cloud) in an enum the language keeps purely geometric