code wiki / (root) / nx_room_l4s.nx

nx_room_l4s.nx source

↩ module page · 177 lines · 7627 B

1// nx_room_l4s.nx -- L4S DUAL-SIGNAL congestion controller (RFC 9330 family): one 2// controller that reacts to EXPLICIT ECN telemetry (the fabric R2 / DCTCP signal) OR 3// to a DELAY setpoint (the room BWE signal) -- whichever fires first. 4// 5// WHY (grounded, knowledge/research/2026-06-23-fabric-applies-to-room-and-elsewhere.md): 6// * fabric R2 nx_fabric_cc = ECN/DCTCP: PRECISE + low setpoint, but requires the 7// bottleneck to MARK. On a dumb-FIFO (non-ECN) path it is BLIND -> bufferbloat 8// (exactly nx_fabric_cc's own NC2: K huge / never mark -> bloat). 9// * room nx_room_bwe = DELAY gradient/level: works on ANY path (no router support) 10// but a delay setpoint is coarser/looser than an explicit mark. 11// They are COMPLEMENTARY. L4S combines them: take the ECN signal when the path marks 12// (tight, low latency) and fall back to the delay setpoint when it does not (bounded, 13// graceful) -- so latency stays bounded across BOTH bottleneck types, which NEITHER 14// single signal achieves alone. That cross-path robustness is the measurable exceed. 15// 16// MODEL: reuses the PROVEN discrete-event link engine shape from nx_fabric_cc (R2) -- 17// ring-buffer bottleneck queue, RTT ack delay line carrying ECN marks, per-RTT 18// controller update, warmup + steady-state percentile histogram, independent 19// telemetry recount (NC liar-kill). Integer-only fixed-point (no float, ecosystem law). 20// ECN arm is DCTCP proportional (alpha EWMA). DELAY arm is a deadbeat setpoint cut: 21// excess standing queue == excess window, so reduce cwnd by the queue overshoot. 22// 23// HONEST SCOPE: software link MODEL (same altitude as R1-R4), single flow, both 24// signals idealised/RTT-coarse (the delay arm reads the bottleneck queue level as the 25// delay proxy, the same simplification nx_room_bwe makes). This is the controller-level 26// rung; wiring it into the live browser room (sites/nishifamily/video/app.js) + the 27// real uplink is the separate operator-gated deploy. expect_exit: 0 license_tier: ORIGINAL 28import "nx_fabric_cc.nx" 29const L4S_MAGIC_4000: i64 = 4000 30 31const L4S_DUAL: i64 = 0 // react to ECN mark OR delay overshoot (the L4S controller) 32const L4S_DELAY: i64 = 1 // delay setpoint only (ignore marks) = pure room-BWE arm 33const L4S_ECN: i64 = 2 // ECN/DCTCP only (ignore delay) = pure fabric-R2 arm 34 35// One discrete-event run. ecn_capable=1 -> bottleneck MARKS at queue>=K; =0 -> dumb FIFO 36// (never marks). K = ECN setpoint, KD = delay setpoint (KD>K: delay is the looser signal). 37func l4s_run(mode: i64, ecn_capable: i64, N: i64, D: i64, RTT: i64, BUFCAP: i64, 38 K: i64, KD: i64, base_cwnd: i64, m: *CcMetrics) -> i64 { 39 let MAXT: i64 = L4S_MAGIC_4000 40 let RS: i64 = BUFCAP + 1 41 let qmark: *i64 = sys_mmap(RS * 8) as *i64 42 var qhead: i64 = 0 43 var qtail: i64 = 0 44 var qocc: i64 = 0 45 let ackc: *i64 = sys_mmap(MAXT * 8) as *i64 46 let ackm: *i64 = sys_mmap(MAXT * 8) as *i64 47 let qhist: *i64 = sys_mmap((BUFCAP + 2) * 8) as *i64 48 49 let WARMUP: i64 = RTT * 12 50 var cwnd: i64 = base_cwnd 51 var in_flight: i64 = 0 52 var alpha: i64 = 0 53 var acc_total: i64 = 0 54 var acc_marked: i64 = 0 55 var rtt_timer: i64 = 0 56 var qmax_rtt: i64 = 0 // peak queue seen this RTT = delay proxy 57 var next_new: i64 = 0 58 var delivered: i64 = 0 59 var drops: i64 = 0 60 var tele_err: i64 = 0 61 var tick: i64 = 0 62 var d_sw: i64 = 0 63 var samples: i64 = 0 64 65 var ecn_allow: i64 = 0 66 if mode == L4S_DUAL { ecn_allow = 1 } 67 if mode == L4S_ECN { ecn_allow = 1 } 68 var delay_allow: i64 = 0 69 if mode == L4S_DUAL { delay_allow = 1 } 70 if mode == L4S_DELAY { delay_allow = 1 } 71 72 while delivered < N { 73 if tick >= MAXT { break } 74 75 // 1. ACKs (frames delivered RTT ticks ago) clear in-flight, carry their marks back. 76 let a: i64 = ackc[tick] 77 in_flight = in_flight - a 78 acc_total = acc_total + a 79 acc_marked = acc_marked + ackm[tick] 80 81 // 2. DRAIN up to D; each delivered frame schedules its ack at tick+RTT. 82 var dd: i64 = 0 83 while dd < D { 84 if qocc == 0 { break } 85 let mk: i64 = qmark[qhead] 86 qhead = qhead + 1; if qhead >= RS { qhead = 0 } 87 qocc = qocc - 1 88 delivered = delivered + 1 89 if tick >= WARMUP { d_sw = d_sw + 1 } 90 let at: i64 = tick + RTT 91 if at < MAXT { ackc[at] = ackc[at] + 1; ackm[at] = ackm[at] + mk } 92 dd = dd + 1 93 } 94 95 // 3. TELEMETRY: report queue; independently recount it (NC liar-kill); track peak. 96 var recount: i64 = qtail - qhead 97 if recount < 0 { recount = recount + RS } 98 var terr: i64 = qocc - recount 99 if terr < 0 { terr = 0 - terr } 100 if terr > tele_err { tele_err = terr } 101 if qocc > qmax_rtt { qmax_rtt = qocc } 102 if tick >= WARMUP { 103 samples = samples + 1 104 if qocc <= BUFCAP { qhist[qocc] = qhist[qocc] + 1 } else { qhist[BUFCAP] = qhist[BUFCAP] + 1 } 105 } 106 107 // 4. PER-RTT controller update. AI +1 always; ECN arm is PRIMARY (precise); the 108 // DELAY arm only acts when ECN did not (it is the fallback signal). 109 rtt_timer = rtt_timer + 1 110 if rtt_timer >= RTT { 111 cwnd = cwnd + 1 112 var reacted: i64 = 0 113 if ecn_allow == 1 { 114 if acc_total > 0 { 115 let frac: i64 = (acc_marked * CC_SCALE) / acc_total 116 alpha = alpha + (frac - alpha) / 16 117 } 118 if acc_marked > 0 { 119 cwnd = cwnd - (cwnd * alpha) / (2 * CC_SCALE) 120 reacted = 1 121 } 122 } 123 if reacted == 0 { 124 if delay_allow == 1 { 125 let over: i64 = qmax_rtt - KD // excess standing queue == excess window 126 if over > 0 { cwnd = cwnd - over } // deadbeat: shed the overshoot 127 } 128 } 129 if cwnd < 1 { cwnd = 1 } 130 acc_total = 0; acc_marked = 0; rtt_timer = 0; qmax_rtt = 0 131 } 132 133 // 5. SEND: window governs injection; excess parks in the bottleneck queue (bloat). 134 var ss: i64 = 0 135 while ss < 2 * D { 136 if in_flight >= cwnd { break } 137 if next_new >= N { break } 138 if qocc < BUFCAP { 139 var mk2: i64 = 0 140 if ecn_capable == 1 { if qocc >= K { mk2 = 1 } } // mark only on an ECN-capable path 141 qmark[qtail] = mk2; qtail = qtail + 1; if qtail >= RS { qtail = 0 }; qocc = qocc + 1 142 in_flight = in_flight + 1; next_new = next_new + 1 143 } else { 144 drops = drops + 1; next_new = next_new + 1 145 } 146 ss = ss + 1 147 } 148 tick = tick + 1 149 } 150 151 let t50: i64 = (samples * 50) / 100 152 let t99: i64 = (samples * 99) / 100 153 var cum: i64 = 0 154 var p50: i64 = 0 155 var p99: i64 = 0 156 var g50: i64 = 0 157 var g99: i64 = 0 158 var hh: i64 = 0 159 while hh <= BUFCAP { 160 cum = cum + qhist[hh] 161 if g50 == 0 { if cum > t50 { p50 = hh; g50 = 1 } } 162 if g99 == 0 { if cum > t99 { p99 = hh; g99 = 1 } } 163 if g99 == 1 { break } 164 hh = hh + 1 165 } 166 167 m.q_p50 = p50 168 m.q_p99 = p99 169 m.drops = drops 170 m.tele_max_err = tele_err 171 m.delivered = delivered 172 m.ticks = tick 173 if samples > 0 { m.util_x1000 = (d_sw * 1000) / (D * samples) } else { m.util_x1000 = 0 } 174 return 0 175} 176 177func main() -> i64 { return 0 }