The SRDX transport surface is complete. Two commits close the Cap<NetConn> blocker that the Director flagged as the critical path for SRDX end-to-end. core/nic_iface.sg (8fe5752) defines the formal NIC driver ABI — the 5-function contract (nic_init/send/recv/link_up/mac) that Drivers' e1000 must implement — and provides a loopback stub at 0xFFC000 so the SRDX transport is QEMU-verifiable without real silicon. core/srdx_xport.sg (8a9db7e) adds syscalls 113–116 (srdx_raw_send, srdx_raw_recv, srdx_link, srdx_mac) — a direct raw-NIC transport path for the SRDX video/input stream that bypasses TCP overhead while sitting alongside the existing TCP netconn path (sys 109–112). The complete SRDX transport surface: 8 syscalls, two paths (TCP + raw NIC), full send/recv chain documented. SRDX-LOOPBACK-PASS. (sigil-kernel 8fe5752, 8a9db7e)
The blocker and why it mattered
The Director's live board flagged Cap<NetConn> as the critical path item. SRDX had a complete encode/decode pipeline (verified by the loopback test), capability-secured session model, VFS persistence, and input reverse channel — but no way to put bytes on a network. Cap<NetConn> is the capability token that gates network send/receive. Without it, SRDX was a local loopback only. These two commits close that gap.
NIC driver interface contract (8fe5752 — core/nic_iface.sg): Formal 5-function ABI
The NIC interface defines what every NIC driver in sigilOS must implement to plug into the SRDX transport. It's a formal contract: 5 functions, named and typed, that srdx_xport.sg (and any other kernel networking code) calls without caring which driver is underneath.
| Function | Signature | What it does |
|---|---|---|
nic_init() | → 0 | Initialize the NIC, bring up the link |
nic_send(buf, len) | → bytes_sent | Transmit a raw Ethernet frame |
nic_recv(buf, cap) | → bytes_recv | Receive a raw Ethernet frame into buf |
nic_link_up() | → 1=UP, 0=DOWN | Query link state |
nic_mac(out) | → 0; 6B MAC written to out | Get the NIC's MAC address |
At link time, the Drivers team's e1000.sg (Intel Gigabit NIC driver — in progress) replaces the loopback stub. Until then, nic_iface.sg provides a loopback stub at 0xFFC000: nic_send copies to a ring buffer; nic_recv reads from the same ring — same-machine send→recv in QEMU, verifiable without real silicon.
SRDX send/recv chain (complete, as documented in the commit):
sys 110 → netconn_dispatch → tcp_send_data → net_send_frame
→ netsys → net_route(CAP_NET) → nethal → nic_send(buf, len)
sys 111 → stack_poll_data → net_recv_raw → nic_recv(buf, cap)
→ tcp_store_rx → tcp_recv_data
PASS: NIC init=1 tx=1 rx=1
SRDX raw-NIC transport (8a9db7e — core/srdx_xport.sg): Syscalls 113–116
The TCP path (sys 109–112) adds connection state, retransmission, flow control, and framing overhead. For a real-time frame stream this is unnecessary — SRDX frames are already self-contained (each frame includes a magic header and full delta); dropped frames are recoverable from the next keyframe. The raw-NIC path bypasses all of this.
| Syscall | Name | Signature | Description |
|---|---|---|---|
| 113 | srdx_raw_send | (buf, len) → bytes_sent | Transmit a raw SRDX frame directly via nic_send — no TCP, no framing overhead |
| 114 | srdx_raw_recv | (buf, max) → bytes_recv | Receive a raw SRDX frame via nic_recv — delivers the next frame or 0 (no frame ready) |
| 115 | srdx_link | () → 1=UP, 0=DOWN | Query NIC link state (wraps nic_link_up) |
| 116 | srdx_mac | (out_buf) → 0 | Get the local MAC address (wraps nic_mac) |
core/srdx_xport.sg dispatches these by calling nic_send/nic_recv/nic_link_up/nic_mac from the NIC interface contract. No intermediate buffer, no copy — the SRDX encode output goes directly to nic_send. PASS: SRT send=1 recv=1 lnk=1
Complete SRDX transport surface — all 8 syscalls
| Syscall | Name | Path | Description |
|---|---|---|---|
| 109 | net_conn_listen(port) | TCP | Open a listening socket, return conn handle |
| 110 | net_conn_send(h, buf, len) | TCP | Send data on a TCP connection |
| 111 | net_conn_recv(h, buf, max) | TCP | Receive data from a TCP connection |
| 112 | net_conn_close(h) | TCP | Close a TCP connection |
| 113 | srdx_raw_send(buf, len) | Raw NIC | Send a raw SRDX frame directly via NIC |
| 114 | srdx_raw_recv(buf, max) | Raw NIC | Receive a raw SRDX frame from NIC |
| 115 | srdx_link() | Raw NIC | Query NIC link state |
| 116 | srdx_mac(out) | Raw NIC | Get local MAC address |
The two paths complement each other: TCP (sys 109–112) for connections where reliability and ordering matter (session setup, control messages, RDP/VNC interop); raw NIC (sys 113–116) for the SRDX frame stream where latency matters and frame loss is acceptable.
What this unblocks
- SRDX end-to-end over QEMU: the loopback stub means
srdx_raw_send→ ring buffer →srdx_raw_recvin a single QEMU session. The Video agent can now test the full pipeline: fbtap → encode → srdx_raw_send → srdx_raw_recv → decode → VESA present — without a network. - e1000 link-in: when Drivers ships
e1000.sg, it replaces the loopback stub at link time. No changes tosrdx_xport.sg— the NIC ABI contract means the transport is driver-agnostic. - Mode-2 netplay: the raw-NIC path is what gamepad state (via
kbc-inject,usb-hid-gamepad,bt-hid) traverses on the reverse channel. Remote gamepad events arrive as raw SRDX frames on sys 114, are parsed by the SRDX session kernel thread, and fed tokbc_kbd_inject/gp_inject. - RDP/VNC interop: the TCP path (sys 109–112) is what the RDP/VNC fallback server will use — standard TCP connections with non-SRDX peers.