figdown 0.1.6 → 0.1.7

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.
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "figdown",
4
4
  "displayName": "FigDown",
5
- "version": "0.1.6",
5
+ "version": "0.1.7",
6
6
  "description": "Figures as text: create and maintain documentation figures as FigDown .fd sources with deterministic SVG artifacts embedded in Markdown — block diagrams, topologies, flowcharts, bit-level layouts, tables, timing waveforms.",
7
7
  "author": {
8
8
  "name": "FigDown",
package/dist/figdown.js CHANGED
@@ -1,4 +1,4 @@
1
- // figdown.js — FigDown embeddable library (0.1.6)
1
+ // figdown.js — FigDown embeddable library (0.1.7)
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.6";
13
+ var VERSION = "0.1.7";
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.6';
27
+ const FIGDOWN_VERSION = '0.1.7';
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
@@ -3112,6 +3112,45 @@ function renderScene(doc,y0){
3112
3112
  const halo=' paint-order="stroke" stroke="#fff" stroke-width="3"';
3113
3113
  const seg=(p,q,t,lbl,fs)=>reqLabel({p,q,t0:t,text:lbl,fs,col:ecol,halo,e,A,B,kind:'end'});
3114
3114
  if(isBack.has(e)&&!pinned(e.a)&&!pinned(e.b)){
3115
+ // ── ROUTING-CHANGE ARCHITECTURE NOTE ──────────
3116
+ // Edge labels are DEFERRED: every label is registered against its
3117
+ // FINAL segment geometry (reqLabel/lblReq above) and placed by ONE
3118
+ // greedy pass after all edges are drawn; arrowheads are computed from
3119
+ // final terminal points (arrowTri). Therefore a routing change made
3120
+ // HERE — upstream of reqLabel/noteSegs/arrowTri — gets label and
3121
+ // arrowhead re-placement for free. A change spliced into the emitted
3122
+ // SVG downstream, or made outside the engine, will strand both.
3123
+ // Two prototype rounds re-derived this the hard way (floating
3124
+ // arrowheads, orphaned labels): that was external splicing, not an
3125
+ // engine gap. Patch routing here; do not "fix" the label machinery.
3126
+ if(A===B){
3127
+ // Self-transition: a small side loop on the node, the
3128
+ // convention of every drawing tool — never a lap of the figure
3129
+ // through the back-edge channel. Side order r,l,b,t; first side
3130
+ // whose loop box overlaps no other node wins (deterministic).
3131
+ const scy=A.y+A.h/2, scx=A.x+A.w/2;
3132
+ const mkLoop=sd=>sd==='r'?[[A.x+A.w,scy-8],[A.x+A.w+20,scy-8],[A.x+A.w+20,scy+8],[A.x+A.w,scy+8]]
3133
+ :sd==='l'?[[A.x,scy-8],[A.x-20,scy-8],[A.x-20,scy+8],[A.x,scy+8]]
3134
+ :sd==='b'?[[scx-8,A.y+A.h],[scx-8,A.y+A.h+20],[scx+8,A.y+A.h+20],[scx+8,A.y+A.h]]
3135
+ :[[scx-8,A.y],[scx-8,A.y-20],[scx+8,A.y-20],[scx+8,A.y]];
3136
+ const loopHit=pp=>{
3137
+ const x0=Math.min(...pp.map(p=>p[0]))-2, x1=Math.max(...pp.map(p=>p[0]))+2;
3138
+ const z0=Math.min(...pp.map(p=>p[1]))-2, z1=Math.max(...pp.map(p=>p[1]))+2;
3139
+ return nodes.some(n=>n!==A&&!n.boundary&&n.x<x1&&n.x+n.w>x0&&n.y<z1&&n.y+n.h>z0);
3140
+ };
3141
+ let sp=null;
3142
+ for(const sd of ['r','l','b','t']){ const pp=mkLoop(sd); if(!loopHit(pp)){ sp=pp; break; } }
3143
+ if(!sp) sp=mkLoop('r');
3144
+ for(const p of sp){ W=Math.max(W,p[0]+4); Hh=Math.max(Hh,p[1]+16-y0-20); }
3145
+ esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(sp)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3146
+ noteSegs(e,sp);
3147
+ if(e.mid) reqLabel({p:sp[1],q:sp[2],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});
3148
+ if(e.tail) seg(sp[0],sp[1],0.5,e.tail,10);
3149
+ if(e.head) seg(sp[3],sp[2],0.5,e.head,10);
3150
+ if(wantsStart) arrowTri(sp[0],sp[1],col);
3151
+ if(wantsEnd) arrowTri(sp[sp.length-1],sp[sp.length-2],col);
3152
+ continue;
3153
+ }
3115
3154
  // back-edge (retry loop): polyline through a side channel beyond the
3116
3155
  // occupied lanes instead of a straight line hidden under the spine,
3117
3156
  // using the nested slot from the channel plan. Ring-eligible loops
@@ -3238,6 +3277,50 @@ function renderScene(doc,y0){
3238
3277
  // their neighbours turns a 40-point staircase into the 2–4 bends a
3239
3278
  // dummy-vertex chain should have, without moving the drawn line.
3240
3279
  simplifyPts(pts);
3280
+ // Waypoint prune: after collinear simplification a
3281
+ // chain can still carry a staircase of near-collinear jogs — the drift
3282
+ // clamp allows only a few px of sideways movement per rank, so a run
3283
+ // that wants to move 35px sideways alternates short diagonals and
3284
+ // verticals that Douglas-Peucker cannot collapse (each angle differs).
3285
+ // The rule: an interior waypoint SURVIVES only if removing it would
3286
+ // make the edge pierce something. Obstacles are the same set the
3287
+ // straight-edge router uses below: non-incident nodes, plus group
3288
+ // boxes when NEITHER endpoint lies inside (a run through a group
3289
+ // interior asserts membership the figure does not declare). Fixed
3290
+ // left-to-right scan to fixpoint — deterministic. Endpoints are then
3291
+ // re-derived so the edge leaves its node facing the first bend, and
3292
+ // each re-derived terminal segment is re-checked: if it would hit an
3293
+ // obstacle the old endpoint stays.
3294
+ {
3295
+ const pobs=nodes.filter(n=>n!==A&&n!==B&&!n.boundary).map(n=>({x:n.x,y:n.y,w:n.w,h:n.h}));
3296
+ const ep0=pts[0], ep1=pts[pts.length-1];
3297
+ for(const k in gBox){
3298
+ const b=gBox[k];
3299
+ const inG=(px,py)=>px>b.x0&&px<b.x1&&py>b.yA&&py<b.yB;
3300
+ if(!inG(ep0[0],ep0[1])&&!inG(ep1[0],ep1[1]))
3301
+ pobs.push({x:b.x0,y:b.yA,w:b.x1-b.x0,h:b.yB-b.yA});
3302
+ }
3303
+ let ch=true, pruned=false;
3304
+ while(ch){ ch=false;
3305
+ for(let i=1;i+1<pts.length;i++)
3306
+ if(!segHitsObs(pts[i-1],pts[i+1],pobs)){ pts.splice(i,1); ch=true; pruned=true; i--; }
3307
+ }
3308
+ // untouched chains stay byte-identical: endpoints and the label
3309
+ // segment are only re-derived when the prune removed a waypoint
3310
+ if(pruned){
3311
+ const nb0=borderPoint(A,pts[1][0],pts[1][1]);
3312
+ if(!segHitsObs(nb0,pts[1],pobs)) pts[0]=nb0;
3313
+ const nb1=borderPoint(B,pts[pts.length-2][0],pts[pts.length-2][1]);
3314
+ if(!segHitsObs(nb1,pts[pts.length-2],pobs)) pts[pts.length-1]=nb1;
3315
+ if(midSeg){ let bi=0,bl=-1;
3316
+ for(let i=0;i+1<pts.length;i++){
3317
+ const l=Math.hypot(pts[i+1][0]-pts[i][0],pts[i+1][1]-pts[i][1]);
3318
+ if(l>bl){ bl=l; bi=i; }
3319
+ }
3320
+ midSeg=[pts[bi],pts[bi+1]];
3321
+ }
3322
+ }
3323
+ }
3241
3324
  esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(pts)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3242
3325
  noteSegs(e,pts);
3243
3326
  if(midSeg) reqLabel({p:midSeg[0],q:midSeg[1],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});
package/dist/figdown.mjs CHANGED
@@ -1,8 +1,8 @@
1
- // figdown.mjs — FigDown embeddable library (0.1.6)
1
+ // figdown.mjs — FigDown embeddable library (0.1.7)
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.6";
5
+ var VERSION = "0.1.7";
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.6';
19
+ const FIGDOWN_VERSION = '0.1.7';
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
@@ -3104,6 +3104,45 @@ function renderScene(doc,y0){
3104
3104
  const halo=' paint-order="stroke" stroke="#fff" stroke-width="3"';
3105
3105
  const seg=(p,q,t,lbl,fs)=>reqLabel({p,q,t0:t,text:lbl,fs,col:ecol,halo,e,A,B,kind:'end'});
3106
3106
  if(isBack.has(e)&&!pinned(e.a)&&!pinned(e.b)){
3107
+ // ── ROUTING-CHANGE ARCHITECTURE NOTE ──────────
3108
+ // Edge labels are DEFERRED: every label is registered against its
3109
+ // FINAL segment geometry (reqLabel/lblReq above) and placed by ONE
3110
+ // greedy pass after all edges are drawn; arrowheads are computed from
3111
+ // final terminal points (arrowTri). Therefore a routing change made
3112
+ // HERE — upstream of reqLabel/noteSegs/arrowTri — gets label and
3113
+ // arrowhead re-placement for free. A change spliced into the emitted
3114
+ // SVG downstream, or made outside the engine, will strand both.
3115
+ // Two prototype rounds re-derived this the hard way (floating
3116
+ // arrowheads, orphaned labels): that was external splicing, not an
3117
+ // engine gap. Patch routing here; do not "fix" the label machinery.
3118
+ if(A===B){
3119
+ // Self-transition: a small side loop on the node, the
3120
+ // convention of every drawing tool — never a lap of the figure
3121
+ // through the back-edge channel. Side order r,l,b,t; first side
3122
+ // whose loop box overlaps no other node wins (deterministic).
3123
+ const scy=A.y+A.h/2, scx=A.x+A.w/2;
3124
+ const mkLoop=sd=>sd==='r'?[[A.x+A.w,scy-8],[A.x+A.w+20,scy-8],[A.x+A.w+20,scy+8],[A.x+A.w,scy+8]]
3125
+ :sd==='l'?[[A.x,scy-8],[A.x-20,scy-8],[A.x-20,scy+8],[A.x,scy+8]]
3126
+ :sd==='b'?[[scx-8,A.y+A.h],[scx-8,A.y+A.h+20],[scx+8,A.y+A.h+20],[scx+8,A.y+A.h]]
3127
+ :[[scx-8,A.y],[scx-8,A.y-20],[scx+8,A.y-20],[scx+8,A.y]];
3128
+ const loopHit=pp=>{
3129
+ const x0=Math.min(...pp.map(p=>p[0]))-2, x1=Math.max(...pp.map(p=>p[0]))+2;
3130
+ const z0=Math.min(...pp.map(p=>p[1]))-2, z1=Math.max(...pp.map(p=>p[1]))+2;
3131
+ return nodes.some(n=>n!==A&&!n.boundary&&n.x<x1&&n.x+n.w>x0&&n.y<z1&&n.y+n.h>z0);
3132
+ };
3133
+ let sp=null;
3134
+ for(const sd of ['r','l','b','t']){ const pp=mkLoop(sd); if(!loopHit(pp)){ sp=pp; break; } }
3135
+ if(!sp) sp=mkLoop('r');
3136
+ for(const p of sp){ W=Math.max(W,p[0]+4); Hh=Math.max(Hh,p[1]+16-y0-20); }
3137
+ esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(sp)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3138
+ noteSegs(e,sp);
3139
+ if(e.mid) reqLabel({p:sp[1],q:sp[2],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});
3140
+ if(e.tail) seg(sp[0],sp[1],0.5,e.tail,10);
3141
+ if(e.head) seg(sp[3],sp[2],0.5,e.head,10);
3142
+ if(wantsStart) arrowTri(sp[0],sp[1],col);
3143
+ if(wantsEnd) arrowTri(sp[sp.length-1],sp[sp.length-2],col);
3144
+ continue;
3145
+ }
3107
3146
  // back-edge (retry loop): polyline through a side channel beyond the
3108
3147
  // occupied lanes instead of a straight line hidden under the spine,
3109
3148
  // using the nested slot from the channel plan. Ring-eligible loops
@@ -3230,6 +3269,50 @@ function renderScene(doc,y0){
3230
3269
  // their neighbours turns a 40-point staircase into the 2–4 bends a
3231
3270
  // dummy-vertex chain should have, without moving the drawn line.
3232
3271
  simplifyPts(pts);
3272
+ // Waypoint prune: after collinear simplification a
3273
+ // chain can still carry a staircase of near-collinear jogs — the drift
3274
+ // clamp allows only a few px of sideways movement per rank, so a run
3275
+ // that wants to move 35px sideways alternates short diagonals and
3276
+ // verticals that Douglas-Peucker cannot collapse (each angle differs).
3277
+ // The rule: an interior waypoint SURVIVES only if removing it would
3278
+ // make the edge pierce something. Obstacles are the same set the
3279
+ // straight-edge router uses below: non-incident nodes, plus group
3280
+ // boxes when NEITHER endpoint lies inside (a run through a group
3281
+ // interior asserts membership the figure does not declare). Fixed
3282
+ // left-to-right scan to fixpoint — deterministic. Endpoints are then
3283
+ // re-derived so the edge leaves its node facing the first bend, and
3284
+ // each re-derived terminal segment is re-checked: if it would hit an
3285
+ // obstacle the old endpoint stays.
3286
+ {
3287
+ const pobs=nodes.filter(n=>n!==A&&n!==B&&!n.boundary).map(n=>({x:n.x,y:n.y,w:n.w,h:n.h}));
3288
+ const ep0=pts[0], ep1=pts[pts.length-1];
3289
+ for(const k in gBox){
3290
+ const b=gBox[k];
3291
+ const inG=(px,py)=>px>b.x0&&px<b.x1&&py>b.yA&&py<b.yB;
3292
+ if(!inG(ep0[0],ep0[1])&&!inG(ep1[0],ep1[1]))
3293
+ pobs.push({x:b.x0,y:b.yA,w:b.x1-b.x0,h:b.yB-b.yA});
3294
+ }
3295
+ let ch=true, pruned=false;
3296
+ while(ch){ ch=false;
3297
+ for(let i=1;i+1<pts.length;i++)
3298
+ if(!segHitsObs(pts[i-1],pts[i+1],pobs)){ pts.splice(i,1); ch=true; pruned=true; i--; }
3299
+ }
3300
+ // untouched chains stay byte-identical: endpoints and the label
3301
+ // segment are only re-derived when the prune removed a waypoint
3302
+ if(pruned){
3303
+ const nb0=borderPoint(A,pts[1][0],pts[1][1]);
3304
+ if(!segHitsObs(nb0,pts[1],pobs)) pts[0]=nb0;
3305
+ const nb1=borderPoint(B,pts[pts.length-2][0],pts[pts.length-2][1]);
3306
+ if(!segHitsObs(nb1,pts[pts.length-2],pobs)) pts[pts.length-1]=nb1;
3307
+ if(midSeg){ let bi=0,bl=-1;
3308
+ for(let i=0;i+1<pts.length;i++){
3309
+ const l=Math.hypot(pts[i+1][0]-pts[i][0],pts[i+1][1]-pts[i][1]);
3310
+ if(l>bl){ bl=l; bi=i; }
3311
+ }
3312
+ midSeg=[pts[bi],pts[bi+1]];
3313
+ }
3314
+ }
3315
+ }
3233
3316
  esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(pts)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3234
3317
  noteSegs(e,pts);
3235
3318
  if(midSeg) reqLabel({p:midSeg[0],q:midSeg[1],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});
@@ -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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" data-cell="vni:3:4" style="cursor:pointer"/><text x="199" y="117.3" font-size="12" text-anchor="start">L2</text><line x1="0" y1="22" x2="0" y2="126" stroke="#c9c7bf"/><line x1="71.2" y1="22" x2="71.2" y2="126" stroke="#c9c7bf"/><line x1="128" y1="22" x2="128" y2="126" stroke="#c9c7bf"/><line x1="192" y1="22" x2="192" y2="126" stroke="#c9c7bf"/><line x1="248.8" y1="22" x2="248.8" y2="126" stroke="#c9c7bf"/><line x1="0" y1="22" x2="248.8" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="248.8" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="248.8" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="248.8" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="248.8" y2="126" stroke="#c9c7bf"/><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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="178" x2="0" y2="282" stroke="#c9c7bf"/><line x1="136" y1="178" x2="136" y2="282" stroke="#c9c7bf"/><line x1="279.2" y1="178" x2="279.2" y2="282" stroke="#c9c7bf"/><line x1="487.2" y1="178" x2="487.2" y2="282" stroke="#c9c7bf"/><line x1="0" y1="178" x2="487.2" y2="178" stroke="#c9c7bf"/><line x1="0" y1="204" x2="487.2" y2="204" stroke="#c9c7bf"/><line x1="0" y1="230" x2="487.2" y2="230" stroke="#c9c7bf"/><line x1="0" y1="256" x2="487.2" y2="256" stroke="#c9c7bf"/><line x1="0" y1="282" x2="487.2" y2="282" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="bc3fb7fb66c7628738359b5135f8da14572e5fb24c4f6efb18a6b8365ab602ea" data-engine-version="0.1.6"><![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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" data-cell="vni:3:4" style="cursor:pointer"/><text x="199" y="117.3" font-size="12" text-anchor="start">L2</text><line x1="0" y1="22" x2="0" y2="126" stroke="#c9c7bf"/><line x1="71.2" y1="22" x2="71.2" y2="126" stroke="#c9c7bf"/><line x1="128" y1="22" x2="128" y2="126" stroke="#c9c7bf"/><line x1="192" y1="22" x2="192" y2="126" stroke="#c9c7bf"/><line x1="248.8" y1="22" x2="248.8" y2="126" stroke="#c9c7bf"/><line x1="0" y1="22" x2="248.8" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="248.8" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="248.8" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="248.8" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="248.8" y2="126" stroke="#c9c7bf"/><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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="178" x2="0" y2="282" stroke="#c9c7bf"/><line x1="136" y1="178" x2="136" y2="282" stroke="#c9c7bf"/><line x1="279.2" y1="178" x2="279.2" y2="282" stroke="#c9c7bf"/><line x1="487.2" y1="178" x2="487.2" y2="282" stroke="#c9c7bf"/><line x1="0" y1="178" x2="487.2" y2="178" stroke="#c9c7bf"/><line x1="0" y1="204" x2="487.2" y2="204" stroke="#c9c7bf"/><line x1="0" y1="230" x2="487.2" y2="230" stroke="#c9c7bf"/><line x1="0" y1="256" x2="487.2" y2="256" stroke="#c9c7bf"/><line x1="0" y1="282" x2="487.2" y2="282" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="bc3fb7fb66c7628738359b5135f8da14572e5fb24c4f6efb18a6b8365ab602ea" data-engine-version="0.1.7"><![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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="22" x2="0" y2="100" stroke="#c9c7bf"/><line x1="164.8" y1="22" x2="164.8" y2="100" stroke="#c9c7bf"/><line x1="524" y1="22" x2="524" y2="100" stroke="#c9c7bf"/><line x1="0" y1="22" x2="524" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="524" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="524" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="524" y2="100" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="6ddb80cf95500ada2890c436006495c99a7cfa719412f6dafdc298badffa743e" data-engine-version="0.1.6"><![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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="22" x2="0" y2="100" stroke="#c9c7bf"/><line x1="164.8" y1="22" x2="164.8" y2="100" stroke="#c9c7bf"/><line x1="524" y1="22" x2="524" y2="100" stroke="#c9c7bf"/><line x1="0" y1="22" x2="524" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="524" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="524" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="524" y2="100" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="6ddb80cf95500ada2890c436006495c99a7cfa719412f6dafdc298badffa743e" data-engine-version="0.1.7"><![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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" data-cell="eth:2:7" style="cursor:pointer"/><text x="769.8" y="117.3" font-size="12" text-anchor="start">CRC-32</text><line x1="0" y1="22" x2="0" y2="126" stroke="#c9c7bf"/><line x1="90" y1="22" x2="90" y2="126" stroke="#c9c7bf"/><line x1="226" y1="22" x2="226" y2="126" stroke="#c9c7bf"/><line x1="326" y1="22" x2="326" y2="126" stroke="#c9c7bf"/><line x1="534" y1="22" x2="534" y2="126" stroke="#c9c7bf"/><line x1="626.8" y1="22" x2="626.8" y2="126" stroke="#c9c7bf"/><line x1="762.8" y1="22" x2="762.8" y2="126" stroke="#c9c7bf"/><line x1="855.5999999999999" y1="22" x2="855.5999999999999" y2="126" stroke="#c9c7bf"/><line x1="0" y1="22" x2="855.5999999999999" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="855.5999999999999" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="855.5999999999999" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="855.5999999999999" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="855.5999999999999" y2="126" stroke="#c9c7bf"/><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.6"><![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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" data-cell="eth:2:7" style="cursor:pointer"/><text x="769.8" y="117.3" font-size="12" text-anchor="start">CRC-32</text><line x1="0" y1="22" x2="0" y2="126" stroke="#c9c7bf"/><line x1="90" y1="22" x2="90" y2="126" stroke="#c9c7bf"/><line x1="226" y1="22" x2="226" y2="126" stroke="#c9c7bf"/><line x1="326" y1="22" x2="326" y2="126" stroke="#c9c7bf"/><line x1="534" y1="22" x2="534" y2="126" stroke="#c9c7bf"/><line x1="626.8" y1="22" x2="626.8" y2="126" stroke="#c9c7bf"/><line x1="762.8" y1="22" x2="762.8" y2="126" stroke="#c9c7bf"/><line x1="855.5999999999999" y1="22" x2="855.5999999999999" y2="126" stroke="#c9c7bf"/><line x1="0" y1="22" x2="855.5999999999999" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="855.5999999999999" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="855.5999999999999" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="855.5999999999999" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="855.5999999999999" y2="126" stroke="#c9c7bf"/><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.7"><![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.6"><![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.7"><![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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="22" x2="0" y2="152" stroke="#c9c7bf"/><line x1="114.4" y1="22" x2="114.4" y2="152" stroke="#c9c7bf"/><line x1="300.8" y1="22" x2="300.8" y2="152" stroke="#c9c7bf"/><line x1="494.4" y1="22" x2="494.4" y2="152" stroke="#c9c7bf"/><line x1="0" y1="22" x2="494.4" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="494.4" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="494.4" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="494.4" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="494.4" y2="126" stroke="#c9c7bf"/><line x1="0" y1="152" x2="494.4" y2="152" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="deb9fdc0ac4b3caf600ad4ebd23afb19bb7b431c44c30a9b47ba70f87a1d4ad5" data-engine-version="0.1.6"><![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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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="none" 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><line x1="0" y1="22" x2="0" y2="152" stroke="#c9c7bf"/><line x1="114.4" y1="22" x2="114.4" y2="152" stroke="#c9c7bf"/><line x1="300.8" y1="22" x2="300.8" y2="152" stroke="#c9c7bf"/><line x1="494.4" y1="22" x2="494.4" y2="152" stroke="#c9c7bf"/><line x1="0" y1="22" x2="494.4" y2="22" stroke="#c9c7bf"/><line x1="0" y1="48" x2="494.4" y2="48" stroke="#c9c7bf"/><line x1="0" y1="74" x2="494.4" y2="74" stroke="#c9c7bf"/><line x1="0" y1="100" x2="494.4" y2="100" stroke="#c9c7bf"/><line x1="0" y1="126" x2="494.4" y2="126" stroke="#c9c7bf"/><line x1="0" y1="152" x2="494.4" y2="152" stroke="#c9c7bf"/></g></g><metadata id="figdown-source" data-sha256="deb9fdc0ac4b3caf600ad4ebd23afb19bb7b431c44c30a9b47ba70f87a1d4ad5" data-engine-version="0.1.7"><![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="none"/><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="none"/><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="none"/><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="none"/><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="none"><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="none"><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"><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="none"/><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="none"/><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="none"><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="none"><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><line x1="0" y1="34" x2="0" y2="184" stroke="#555"/><line x1="0" y1="184" x2="0" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="214" x2="0" y2="244" stroke="#555"/><line x1="92" y1="124" x2="92" y2="154" stroke="#555"/><line x1="184" y1="124" x2="184" y2="154" stroke="#555"/><line x1="207" y1="124" x2="207" y2="154" stroke="#555"/><line x1="230" y1="124" x2="230" y2="154" stroke="#555"/><line x1="253" y1="124" x2="253" y2="154" stroke="#555"/><line x1="276" y1="124" x2="276" y2="154" stroke="#555"/><line x1="299" y1="124" x2="299" y2="154" stroke="#555"/><line x1="322" y1="124" x2="322" y2="154" stroke="#555"/><line x1="345" y1="124" x2="345" y2="154" stroke="#555"/><line x1="368" y1="34" x2="368" y2="64" stroke="#555"/><line x1="368" y1="124" x2="368" y2="184" stroke="#555"/><line x1="736" y1="34" x2="736" y2="184" stroke="#555"/><line x1="736" y1="184" x2="736" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="736" y1="214" x2="736" y2="244" stroke="#555"/><line x1="0" y1="34" x2="736" y2="34" stroke="#555"/><line x1="0" y1="64" x2="736" y2="64" stroke="#555"/><line x1="0" y1="94" x2="736" y2="94" stroke="#555"/><line x1="0" y1="124" x2="736" y2="124" stroke="#555"/><line x1="0" y1="154" x2="736" y2="154" stroke="#555"/><line x1="0" y1="184" x2="736" y2="184" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="214" x2="736" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="244" x2="736" y2="244" stroke="#555"/><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.6"><![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="none"/><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="none"/><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="none"/><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="none"/><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="none"><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="none"><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"/><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="none"><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="none"/><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="none"/><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="none"><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="none"><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><line x1="0" y1="34" x2="0" y2="184" stroke="#555"/><line x1="0" y1="184" x2="0" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="214" x2="0" y2="244" stroke="#555"/><line x1="92" y1="124" x2="92" y2="154" stroke="#555"/><line x1="184" y1="124" x2="184" y2="154" stroke="#555"/><line x1="207" y1="124" x2="207" y2="154" stroke="#555"/><line x1="230" y1="124" x2="230" y2="154" stroke="#555"/><line x1="253" y1="124" x2="253" y2="154" stroke="#555"/><line x1="276" y1="124" x2="276" y2="154" stroke="#555"/><line x1="299" y1="124" x2="299" y2="154" stroke="#555"/><line x1="322" y1="124" x2="322" y2="154" stroke="#555"/><line x1="345" y1="124" x2="345" y2="154" stroke="#555"/><line x1="368" y1="34" x2="368" y2="64" stroke="#555"/><line x1="368" y1="124" x2="368" y2="184" stroke="#555"/><line x1="736" y1="34" x2="736" y2="184" stroke="#555"/><line x1="736" y1="184" x2="736" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="736" y1="214" x2="736" y2="244" stroke="#555"/><line x1="0" y1="34" x2="736" y2="34" stroke="#555"/><line x1="0" y1="64" x2="736" y2="64" stroke="#555"/><line x1="0" y1="94" x2="736" y2="94" stroke="#555"/><line x1="0" y1="124" x2="736" y2="124" stroke="#555"/><line x1="0" y1="154" x2="736" y2="154" stroke="#555"/><line x1="0" y1="184" x2="736" y2="184" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="214" x2="736" y2="214" stroke="#555" stroke-dasharray="5 3"/><line x1="0" y1="244" x2="736" y2="244" stroke="#555"/><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.7"><![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.6"><![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.7"><![CDATA[
2
2
  # FigDown — figures as text. Spec: https://github.com/FigDown/figdown
3
3
 
4
4
  figdown 0.1 flowchart
package/guide/layout.md CHANGED
@@ -442,9 +442,10 @@ that need deliberate arranging is unaffected — the ratio is what this
442
442
  paragraph is for.)
443
443
 
444
444
  **Long back-edges and bypasses read as detours — say what they are.** An edge
445
- that skips several ranks is routed out to the canvas margin and picks up a
446
- bend per rank crossed; on a large figure that reads as a staircase, and a
447
- reader who cannot tell *why* a line is out there reads it as noise. Until this release the taught answer was a hand-written waypoint; `path` is withdrawn
445
+ that skips several ranks is routed through the gaps and keeps a bend only
446
+ where something is actually in the way (it used to pick up
447
+ a bend per rank crossed and read as a staircase); but however clean the line,
448
+ a reader who cannot tell *why* a line is out there reads it as noise. Until this release the taught answer was a hand-written waypoint; `path` is withdrawn
448
449
  and there is no replacement, so the answer moves into the content zone, where
449
450
  it arguably belonged: name the bypass so the detour is legible as a bypass.
450
451
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figdown",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
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>",
@@ -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.6';
124
+ const FIGDOWN_VERSION = '0.1.7';
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
@@ -3209,6 +3209,45 @@ function renderScene(doc,y0){
3209
3209
  const halo=' paint-order="stroke" stroke="#fff" stroke-width="3"';
3210
3210
  const seg=(p,q,t,lbl,fs)=>reqLabel({p,q,t0:t,text:lbl,fs,col:ecol,halo,e,A,B,kind:'end'});
3211
3211
  if(isBack.has(e)&&!pinned(e.a)&&!pinned(e.b)){
3212
+ // ── ROUTING-CHANGE ARCHITECTURE NOTE ──────────
3213
+ // Edge labels are DEFERRED: every label is registered against its
3214
+ // FINAL segment geometry (reqLabel/lblReq above) and placed by ONE
3215
+ // greedy pass after all edges are drawn; arrowheads are computed from
3216
+ // final terminal points (arrowTri). Therefore a routing change made
3217
+ // HERE — upstream of reqLabel/noteSegs/arrowTri — gets label and
3218
+ // arrowhead re-placement for free. A change spliced into the emitted
3219
+ // SVG downstream, or made outside the engine, will strand both.
3220
+ // Two prototype rounds re-derived this the hard way (floating
3221
+ // arrowheads, orphaned labels): that was external splicing, not an
3222
+ // engine gap. Patch routing here; do not "fix" the label machinery.
3223
+ if(A===B){
3224
+ // Self-transition: a small side loop on the node, the
3225
+ // convention of every drawing tool — never a lap of the figure
3226
+ // through the back-edge channel. Side order r,l,b,t; first side
3227
+ // whose loop box overlaps no other node wins (deterministic).
3228
+ const scy=A.y+A.h/2, scx=A.x+A.w/2;
3229
+ const mkLoop=sd=>sd==='r'?[[A.x+A.w,scy-8],[A.x+A.w+20,scy-8],[A.x+A.w+20,scy+8],[A.x+A.w,scy+8]]
3230
+ :sd==='l'?[[A.x,scy-8],[A.x-20,scy-8],[A.x-20,scy+8],[A.x,scy+8]]
3231
+ :sd==='b'?[[scx-8,A.y+A.h],[scx-8,A.y+A.h+20],[scx+8,A.y+A.h+20],[scx+8,A.y+A.h]]
3232
+ :[[scx-8,A.y],[scx-8,A.y-20],[scx+8,A.y-20],[scx+8,A.y]];
3233
+ const loopHit=pp=>{
3234
+ const x0=Math.min(...pp.map(p=>p[0]))-2, x1=Math.max(...pp.map(p=>p[0]))+2;
3235
+ const z0=Math.min(...pp.map(p=>p[1]))-2, z1=Math.max(...pp.map(p=>p[1]))+2;
3236
+ return nodes.some(n=>n!==A&&!n.boundary&&n.x<x1&&n.x+n.w>x0&&n.y<z1&&n.y+n.h>z0);
3237
+ };
3238
+ let sp=null;
3239
+ for(const sd of ['r','l','b','t']){ const pp=mkLoop(sd); if(!loopHit(pp)){ sp=pp; break; } }
3240
+ if(!sp) sp=mkLoop('r');
3241
+ for(const p of sp){ W=Math.max(W,p[0]+4); Hh=Math.max(Hh,p[1]+16-y0-20); }
3242
+ esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(sp)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3243
+ noteSegs(e,sp);
3244
+ if(e.mid) reqLabel({p:sp[1],q:sp[2],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});
3245
+ if(e.tail) seg(sp[0],sp[1],0.5,e.tail,10);
3246
+ if(e.head) seg(sp[3],sp[2],0.5,e.head,10);
3247
+ if(wantsStart) arrowTri(sp[0],sp[1],col);
3248
+ if(wantsEnd) arrowTri(sp[sp.length-1],sp[sp.length-2],col);
3249
+ continue;
3250
+ }
3212
3251
  // back-edge (retry loop): polyline through a side channel beyond the
3213
3252
  // occupied lanes instead of a straight line hidden under the spine,
3214
3253
  // using the nested slot from the channel plan. Ring-eligible loops
@@ -3335,6 +3374,50 @@ function renderScene(doc,y0){
3335
3374
  // their neighbours turns a 40-point staircase into the 2–4 bends a
3336
3375
  // dummy-vertex chain should have, without moving the drawn line.
3337
3376
  simplifyPts(pts);
3377
+ // Waypoint prune: after collinear simplification a
3378
+ // chain can still carry a staircase of near-collinear jogs — the drift
3379
+ // clamp allows only a few px of sideways movement per rank, so a run
3380
+ // that wants to move 35px sideways alternates short diagonals and
3381
+ // verticals that Douglas-Peucker cannot collapse (each angle differs).
3382
+ // The rule: an interior waypoint SURVIVES only if removing it would
3383
+ // make the edge pierce something. Obstacles are the same set the
3384
+ // straight-edge router uses below: non-incident nodes, plus group
3385
+ // boxes when NEITHER endpoint lies inside (a run through a group
3386
+ // interior asserts membership the figure does not declare). Fixed
3387
+ // left-to-right scan to fixpoint — deterministic. Endpoints are then
3388
+ // re-derived so the edge leaves its node facing the first bend, and
3389
+ // each re-derived terminal segment is re-checked: if it would hit an
3390
+ // obstacle the old endpoint stays.
3391
+ {
3392
+ const pobs=nodes.filter(n=>n!==A&&n!==B&&!n.boundary).map(n=>({x:n.x,y:n.y,w:n.w,h:n.h}));
3393
+ const ep0=pts[0], ep1=pts[pts.length-1];
3394
+ for(const k in gBox){
3395
+ const b=gBox[k];
3396
+ const inG=(px,py)=>px>b.x0&&px<b.x1&&py>b.yA&&py<b.yB;
3397
+ if(!inG(ep0[0],ep0[1])&&!inG(ep1[0],ep1[1]))
3398
+ pobs.push({x:b.x0,y:b.yA,w:b.x1-b.x0,h:b.yB-b.yA});
3399
+ }
3400
+ let ch=true, pruned=false;
3401
+ while(ch){ ch=false;
3402
+ for(let i=1;i+1<pts.length;i++)
3403
+ if(!segHitsObs(pts[i-1],pts[i+1],pobs)){ pts.splice(i,1); ch=true; pruned=true; i--; }
3404
+ }
3405
+ // untouched chains stay byte-identical: endpoints and the label
3406
+ // segment are only re-derived when the prune removed a waypoint
3407
+ if(pruned){
3408
+ const nb0=borderPoint(A,pts[1][0],pts[1][1]);
3409
+ if(!segHitsObs(nb0,pts[1],pobs)) pts[0]=nb0;
3410
+ const nb1=borderPoint(B,pts[pts.length-2][0],pts[pts.length-2][1]);
3411
+ if(!segHitsObs(nb1,pts[pts.length-2],pobs)) pts[pts.length-1]=nb1;
3412
+ if(midSeg){ let bi=0,bl=-1;
3413
+ for(let i=0;i+1<pts.length;i++){
3414
+ const l=Math.hypot(pts[i+1][0]-pts[i][0],pts[i+1][1]-pts[i][1]);
3415
+ if(l>bl){ bl=l; bi=i; }
3416
+ }
3417
+ midSeg=[pts[bi],pts[bi+1]];
3418
+ }
3419
+ }
3420
+ }
3338
3421
  esvg.push('<path data-edge="'+e.line+'" d="'+roundPath(pts)+'" fill="none" stroke="'+col+'" stroke-width="1.6"'+dash+'/>');
3339
3422
  noteSegs(e,pts);
3340
3423
  if(midSeg) reqLabel({p:midSeg[0],q:midSeg[1],text:e.mid,fs:11,col:lcol,halo,e,A,B,kind:'mid',first:false});