code wiki / _hdl_build / nx_bwe_gate.nx
nx_bwe_gate.nx source
↩ module page · 94 lines · 4906 B
1import "nx_gate_base.nx"
2// nx_bwe_gate.nx -- proves the sovereign estimator does what GCC does, MEASURED on a link whose TRUE
3// capacity MOVES: it must TRACK the capacity (converge within a band), BACK OFF fast when capacity drops
4// (delay trend + loss both fire), and PROBE back up when the path clears. NEG-CONTROLS: an always-huge
5// link ramps to the ceiling; an always-tiny link collapses to the floor (it can't hallucinate bandwidth).
6// The link model: a queue grows while we send over capacity (rising delay = the GCC signal) and drops
7// packets when overloaded (the loss signal) -- so the estimator only "sees" congestion it truly caused.
8// expect_exit: 0 license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_bwe.nx"
11
12func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
13" as *u8); return ok }
14func gn(v: i64) -> i64 {
15 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
16 let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
17 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
18
19// TRUE capacity schedule (kbps): 4000 -> drop 1200 -> recover 3500
20func capacity(tick: i64) -> i64 {
21 if tick < 50 { return 4000 }
22 if tick < 100 { return 1200 }
23 return 3500
24}
25
26// run N ticks against a capacity function selector (0=schedule,1=huge,2=tiny); record est into rec[]
27func run(mode: i64, N: i64, rec: *i64) -> i64 {
28 let bw: *i64 = sys_mmap(8 * 16) as *i64
29 bwe_init(bw, 300, 6000, 2000, 200)
30 var queue: i64 = 0
31 var tick: i64 = 0
32 while tick < N {
33 var C: i64 = capacity(tick)
34 if mode == 1 { C = 100000 }
35 if mode == 2 { C = 150 }
36 let est: i64 = bwe_estimate(bw)
37 let over: i64 = est - C
38 // link queue: grows while over-sending (rising delay), drains when under
39 if over > 0 { queue = queue + over / 8 } else { queue = queue - 200 }
40 if queue < 0 { queue = 0 }
41 let send_ts: i64 = tick * 1000
42 let arr_ts: i64 = send_ts + 50 + queue // arrival delayed by the queue = the delay signal
43 bwe_on_arrival(bw, send_ts, arr_ts)
44 // loss: fraction of the over-send is dropped
45 var lost: i64 = 0
46 if over > 0 { lost = over }
47 bwe_report_loss(bw, lost, est)
48 rec[tick] = bwe_update(bw)
49 tick = tick + 1
50 }
51 return 0
52}
53
54func main() -> i64 {
55 gw("=== nx_bwe_gate: sovereign GCC-class bandwidth estimator tracks a moving link (MEASURED) ===\n" as *u8)
56 let N: i64 = 150
57 let rec: *i64 = sys_mmap(8 * N) as *i64
58 run(0, N, rec)
59 let e45: i64 = rec[45] // end of 4000 phase
60 let e50: i64 = rec[50]
61 let e95: i64 = rec[95] // end of 1200 phase (after a drop)
62 let e100: i64 = rec[100]
63 let e145: i64 = rec[145] // end of 3500 phase (after recovery)
64 // find max over run (runaway check)
65 var mx: i64 = 0
66 var i: i64 = 0
67 while i < N { if rec[i] > mx { mx = rec[i] } i = i + 1 }
68 gw(" tracking: est@45(C4000)=" as *u8); gn(e45); gw(" est@95(C1200)=" as *u8); gn(e95); gw(" est@145(C3500)=" as *u8); gn(e145); gw(" max=" as *u8); gn(mx); gw("\n" as *u8)
69
70 let huge: *i64 = sys_mmap(8 * N) as *i64
71 let tiny: *i64 = sys_mmap(8 * N) as *i64
72 run(1, N, huge)
73 run(2, N, tiny)
74 gw(" neg: huge-link ramps to " as *u8); gn(huge[N-1]); gw(" (want 6000 ceiling) tiny-link collapses to " as *u8); gn(tiny[N-1]); gw(" (want 300 floor)\n" as *u8)
75
76 var bad: i64 = 0
77 // TRACK: converge into a band around each true capacity (AIMD sawtooths, so a band not a point)
78 if e45 < 3000 { bad = bad + 1; gw(" FAIL: did not climb to ~4000\n" as *u8) }
79 if e45 > 4600 { bad = bad + 1; gw(" FAIL: overshot 4000\n" as *u8) }
80 if e95 < 900 { bad = bad + 1; gw(" FAIL: undershot 1200\n" as *u8) }
81 if e95 > 1800 { bad = bad + 1; gw(" FAIL: did not back off to ~1200\n" as *u8) }
82 if e145 < 2600 { bad = bad + 1; gw(" FAIL: did not recover toward 3500\n" as *u8) }
83 // BACK OFF on drop, PROBE UP on recovery
84 if e95 >= e50 { bad = bad + 1; gw(" FAIL: no back-off when capacity dropped\n" as *u8) }
85 if e145 <= e100 { bad = bad + 1; gw(" FAIL: no ramp-up when capacity recovered\n" as *u8) }
86 if mx > 6000 { bad = bad + 1; gw(" FAIL: exceeded the max clamp (runaway)\n" as *u8) }
87 // NEG: no hallucinated bandwidth
88 if huge[N-1] != 6000 { bad = bad + 1; gw(" FAIL neg: huge link did not ramp to ceiling\n" as *u8) }
89 if tiny[N-1] != 300 { bad = bad + 1; gw(" FAIL neg: tiny link did not collapse to floor\n" as *u8) }
90
91 if bad == 0 { gw("BWE-GATE verdict=GREEN -- tracks the moving link, backs off on congestion, probes up when clear (GCC-class)\n" as *u8); return 0 }
92 gw("BWE-GATE verdict=RED fails=" as *u8); gn(bad); gw("\n" as *u8)
93 return 1
94}