nx_modelprobe.nx source
↩ module page · 96 lines · 4467 B
1// nx_modelprobe.nx -- MEASURE /v1/models. NEVER BELIEVE IT.
2//
3// swarm_nodes.conf states the rule for changing a worker address in its own words: "measure
4// /v1/models from the NAS, then uncomment with the address that actually answered -- never with one
5// that is merely believed." This organ IS that measurement, so a repoint is decided by bytes.
6//
7// WHY IT EXISTS, measured 2026-09-05. nx_netprobe_ladder proved 192.168.8.192:7861 refuses TCP at
8// every bound from 500 ms to 15 s, with 192.168.8.193 UP as a positive control and 192.168.8.253 DOWN
9// as a neg-control -- so the probe is neither blind nor credulous. Against that, nx_worker_dispatch
10// reported HTTP 200 for .192 WHILE PRINTING ARENA-OVERRUN prev_alloc_size=256 in the same output. A
11// verdict from an instrument announcing memory corruption does not outrank a controlled one, so the
12// tie is broken by asking the application layer directly.
13//
14// COMPOSES THE INCUMBENT: nx_http_client (nx_http_client_get + nx_http_client_sockaddr_ipv4) is the
15// sovereign HTTP/1.1 GET client and it already carries NAMED verdicts -- OK, SOCKET_FAIL,
16// CONNECT_FAIL, SEND_FAIL, RECV_FAIL. That is precisely what np_probe_up lacks, and the contrast is
17// the point: the estate solved name-which-negative here and the liveness probe never inherited it.
18// license_tier: ORIGINAL No hw writes (Rule 26).
19import "nx_syscalls.nx"
20import "nx_http_client.nx"
21
22const MP_CAP: i64 = 65536
23const MP_PORT: i64 = 7861
24const MP_HEADLINE: i64 = 96
25
26func mp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
27func mp_puts(s: *u8) -> i64 { sys_write(1, s, mp_slen(s)); return 0 }
28func mp_putn(v: i64) -> i64 {
29 let b: *u8 = sys_mmap(32)
30 var m: i64 = v
31 if m < 0 { mp_puts("-" as *u8); m = 0 - m }
32 if m == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 }
33 let t: *u8 = sys_mmap(32)
34 var k: i64 = 0
35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
36 var w: i64 = 0
37 while k > 0 { k = k - 1; b[w] = t[k]; w = w + 1 }
38 sys_write(1, b, w)
39 return 0
40}
41
42func mp_verdict_name(v: i64) -> i64 {
43 if v == NX_HTTP_C_VERDICT_OK { mp_puts("OK" as *u8); return 0 }
44 if v == NX_HTTP_C_VERDICT_SOCKET_FAIL { mp_puts("SOCKET_FAIL" as *u8); return 0 }
45 if v == NX_HTTP_C_VERDICT_CONNECT_FAIL { mp_puts("CONNECT_FAIL" as *u8); return 0 }
46 if v == NX_HTTP_C_VERDICT_SEND_FAIL { mp_puts("SEND_FAIL" as *u8); return 0 }
47 if v == NX_HTTP_C_VERDICT_RECV_FAIL { mp_puts("RECV_FAIL" as *u8); return 0 }
48 mp_puts("UNKNOWN" as *u8)
49 return 0
50}
51
52// print the response status line, clamped -- the headline is the evidence, the body is not needed
53func mp_head(buf: *u8, n: i64) -> i64 {
54 var i: i64 = 0
55 var lim: i64 = n
56 if lim > MP_HEADLINE { lim = MP_HEADLINE }
57 while i < lim {
58 if buf[i] == (13 as u8) { i = lim }
59 else { if buf[i] == (10 as u8) { i = lim } else { sys_write(1, (buf as i64 + i) as *u8, 1); i = i + 1 } }
60 }
61 return 0
62}
63
64func mp_one(a: i64, b: i64, c: i64, d: i64, label: *u8) -> i64 {
65 let sa: *u8 = sys_mmap(16)
66 nx_http_client_sockaddr_ipv4(sa, a, b, c, d, MP_PORT)
67 let host: *u8 = sys_mmap(64)
68 var ho: i64 = 0
69 ho = ho + 0
70 let buf: *u8 = sys_mmap(MP_CAP)
71 let vp: *i64 = sys_mmap(16) as *i64
72 vp[0] = 0
73 let path: *u8 = "/v1/models" as *u8
74 let hname: *u8 = "worker" as *u8
75 let got: i64 = nx_http_client_get(sa, path, mp_slen(path), hname, mp_slen(hname), buf, MP_CAP, vp)
76 mp_puts(label)
77 mp_puts(" addr=" as *u8); mp_putn(a); mp_puts("." as *u8); mp_putn(b)
78 mp_puts("." as *u8); mp_putn(c); mp_puts("." as *u8); mp_putn(d)
79 mp_puts(":" as *u8); mp_putn(MP_PORT)
80 mp_puts(" verdict=" as *u8); mp_verdict_name(vp[0])
81 mp_puts(" bytes=" as *u8); mp_putn(got)
82 mp_puts(" head=" as *u8)
83 if got > 0 { mp_head(buf, got) } else { mp_puts("(none)" as *u8) }
84 mp_puts("\n" as *u8)
85 return vp[0]
86}
87
88func main(argc: i64, argv: *i64) -> i64 {
89 mp_puts("NX-MODELPROBE -- GET /v1/models, the check swarm_nodes.conf requires before any repoint\n" as *u8)
90 let v1: i64 = mp_one(192, 168, 8, 192, "CONF-ADDR gpu-image " as *u8)
91 let v2: i64 = mp_one(192, 168, 8, 193, "CANDIDATE gpu-found-1" as *u8)
92 mp_puts("SUMMARY conf_verdict=" as *u8); mp_putn(v1)
93 mp_puts(" candidate_verdict=" as *u8); mp_putn(v2)
94 mp_puts(" (1=OK 2=SOCKET_FAIL 3=CONNECT_FAIL 4=SEND_FAIL 5=RECV_FAIL)\n" as *u8)
95 return 0
96}