os: NetworkInterface values and NetworkInterface.all on Linux (OS slice 5, step 2a of #129) #539

Closed
opened 2026-10-28 05:43:46 +00:00 by orion · 3 comments
Collaborator

Goal

Step 2a of epic #129 (OS slice 5): the interface values of docs/design/OS.md section 5.5 and NetworkInterface.all() on Linux, with the pure parsers and InterfaceAddress.subnet(). The macOS and Windows halves are step 2b, filed when this lands.

Why only the first half of the epic's step 2

The epic's step 2 spans five types, three systems and three runtime files: more than one PR of one or two commits. Split by system, as slice 4 did. Step 2a is the types, the pure parsers and the Linux half; step 2b adds getifaddrs/AF_LINK for macOS (posix/, bsd/) and GetAdaptersAddresses for Windows. Step 3 (InterfaceTraffic, traffic, throughput, docs, slice marked done) follows after 2b.

Source

  • docs/design/OS.md section 5.5 (signatures), section 7 (natives: POSIX getifaddrs), section 10 slice 5; decision comment on #129.
  • Pattern: std/os/src/volumes.trb (a match OperatingSystem.current handing over to the directory of that system), std/os/src/linux/volumes.trb (pure parser plus readSystemFile).

Scope

  • New std/os/src/network.trb: NetworkInterface (fields as in 5.5 without traffic and throughput, which are step 3), InterfaceAddress with subnet() (masks the prefix, answers Subnet.of), InterfaceStatus, InterfaceKind, NetworkInterface.all(); exported from lib.trb. Public items documented per the repo's doc rules.
  • Linux half: one Posix native over getifaddrs (declared in natives.trb like the volumes natives) that returns text per address (name, index, family, address, prefix length, flags, AF_PACKET hardware address); /sys/class/net/<name>/{mtu,operstate,type} through readSystemFile. Parsing and grouping the lines into interfaces are pure functions.
  • Kind from /sys/class/net/<name>/type (772 loopback, 1 Ethernet, wireless where /sys/class/net/<name>/wireless exists, tunnel for the tunnel types and the IFF_POINTOPOINT flag) and status from operstate (up, down, otherwise Unknown).
  • macOS, Windows, FreeBSD and the browser: NetworkInterface.all() answers OsError.Unsupported for now (FreeBSD and the browser until slice 7, macOS and Windows until step 2b).

Acceptance criteria

  • NetworkInterface.all() on Linux answers the loopback interface (lo) with kind Loopback, status Up or Unknown, and a loopback address (127.0.0.1/8), and every address's subnet().contains(address) holds.
  • Pure parsers (the getifaddrs text, operstate, type) have .test.trb tests over captured inputs, including an IPv6 address with a scope, an interface with no hardware address, an interface with several addresses and one with none.
  • InterfaceAddress.subnet() tested for IPv4 and IPv6 (192.168.1.23/24 gives 192.168.1.0/24; fe80::1/64; prefix 0, 32 and 128 edge cases); a prefix length out of range for the family is an OsError, not a panic.
  • A missing /sys file does not fail the call: the field takes its fallback (mtu 0, status Unknown, kind Other).
  • The other systems compile and answer OsError.Unsupported; torb format --check clean on touched files.
  • docs/standard-library/os.md lists the new types (the full network section stays with step 3).

Seed impact

None: no syntax change, no new driver flag, no std name the compiler looks up by string. New natives are declared in natives.trb like the processors' and volumes'; the compiler does not import NetworkInterface.

Size

One PR, two Conventional Commits: feat(os): NetworkInterface values and the interface parsers (types, subnet(), pure parsers, tests) and feat(os): NetworkInterface.all on Linux (native, sysfs reads, wiring, docs). CI only for gates; no local bootstrap.

Dependencies

#129 (epic), #528 (closed, Subnet and MacAddress on main).

## Goal Step 2a of epic #129 (OS slice 5): the interface values of `docs/design/OS.md` section 5.5 and `NetworkInterface.all()` on **Linux**, with the pure parsers and `InterfaceAddress.subnet()`. The macOS and Windows halves are step 2b, filed when this lands. ## Why only the first half of the epic's step 2 The epic's step 2 spans five types, three systems and three runtime files: more than one PR of one or two commits. Split by system, as slice 4 did. Step 2a is the types, the pure parsers and the Linux half; step 2b adds `getifaddrs`/`AF_LINK` for macOS (`posix/`, `bsd/`) and `GetAdaptersAddresses` for Windows. Step 3 (`InterfaceTraffic`, `traffic`, `throughput`, docs, slice marked done) follows after 2b. ## Source - `docs/design/OS.md` section 5.5 (signatures), section 7 (natives: POSIX `getifaddrs`), section 10 slice 5; decision comment on #129. - Pattern: `std/os/src/volumes.trb` (a `match OperatingSystem.current` handing over to the directory of that system), `std/os/src/linux/volumes.trb` (pure parser plus `readSystemFile`). ## Scope - New `std/os/src/network.trb`: `NetworkInterface` (fields as in 5.5 without `traffic` and `throughput`, which are step 3), `InterfaceAddress` with `subnet()` (masks the prefix, answers `Subnet.of`), `InterfaceStatus`, `InterfaceKind`, `NetworkInterface.all()`; exported from `lib.trb`. Public items documented per the repo's doc rules. - Linux half: one `Posix` native over `getifaddrs` (declared in `natives.trb` like the volumes natives) that returns text per address (name, index, family, address, prefix length, flags, `AF_PACKET` hardware address); `/sys/class/net/<name>/{mtu,operstate,type}` through `readSystemFile`. Parsing and grouping the lines into interfaces are pure functions. - Kind from `/sys/class/net/<name>/type` (772 loopback, 1 Ethernet, wireless where `/sys/class/net/<name>/wireless` exists, tunnel for the tunnel types and the `IFF_POINTOPOINT` flag) and status from `operstate` (`up`, `down`, otherwise `Unknown`). - macOS, Windows, FreeBSD and the browser: `NetworkInterface.all()` answers `OsError.Unsupported` for now (FreeBSD and the browser until slice 7, macOS and Windows until step 2b). ## Acceptance criteria - [ ] `NetworkInterface.all()` on Linux answers the loopback interface (`lo`) with kind `Loopback`, status `Up` or `Unknown`, and a loopback address (`127.0.0.1/8`), and every address's `subnet().contains(address)` holds. - [ ] Pure parsers (the `getifaddrs` text, `operstate`, `type`) have `.test.trb` tests over captured inputs, including an IPv6 address with a scope, an interface with no hardware address, an interface with several addresses and one with none. - [ ] `InterfaceAddress.subnet()` tested for IPv4 and IPv6 (`192.168.1.23/24` gives `192.168.1.0/24`; `fe80::1/64`; prefix 0, 32 and 128 edge cases); a prefix length out of range for the family is an `OsError`, not a panic. - [ ] A missing `/sys` file does not fail the call: the field takes its fallback (`mtu` 0, status `Unknown`, kind `Other`). - [ ] The other systems compile and answer `OsError.Unsupported`; `torb format --check` clean on touched files. - [ ] `docs/standard-library/os.md` lists the new types (the full network section stays with step 3). ## Seed impact None: no syntax change, no new driver flag, no std name the compiler looks up by string. New natives are declared in `natives.trb` like the processors' and volumes'; the compiler does not import `NetworkInterface`. ## Size One PR, two Conventional Commits: `feat(os): NetworkInterface values and the interface parsers` (types, `subnet()`, pure parsers, tests) and `feat(os): NetworkInterface.all on Linux` (native, sysfs reads, wiring, docs). CI only for gates; no local bootstrap. ## Dependencies #129 (epic), #528 (closed, `Subnet` and `MacAddress` on `main`).
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261028 until 2026-10-28T11:55Z

[loop:torbscript] claim implement by session:loop-torbscript-20261028 until 2026-10-28T11:55Z
Author
Collaborator

Result: implementation is up in #542 (branch loop/539-network-interfaces, head 7e22ec4), mergeable. CI run on that head is still queued behind the single linux-x64 runner (gates, tier A/B, seed, archives, playground, same-C, release-sync pending; bootstrap linux-x64, commit messages, pdisc green as of 07:2xZ). The CI follow-up worker lost its execution context; no further changes were made. Releasing the claim; the merge gate on #542 decides once CI settles. Known: tier B is red on main and fixed by #536, so a tier-B-only failure here is not caused by this PR.

Result: implementation is up in #542 (branch `loop/539-network-interfaces`, head `7e22ec4`), mergeable. CI run on that head is still queued behind the single linux-x64 runner (gates, tier A/B, seed, archives, playground, same-C, release-sync pending; bootstrap linux-x64, commit messages, pdisc green as of 07:2xZ). The CI follow-up worker lost its execution context; no further changes were made. Releasing the claim; the merge gate on #542 decides once CI settles. Known: tier B is red on main and fixed by #536, so a tier-B-only failure here is not caused by this PR.
Author
Collaborator

[loop:torbscript] release implement: the CI follow-up worker died (lost execution context, no further changes); PR #542 (head 415690d) is open and mergeable, CI is queued. next: waiting (CI on PR #542 and merge gate)

[loop:torbscript] release implement: the CI follow-up worker died (lost execution context, no further changes); PR #542 (head 415690d) is open and mergeable, CI is queued. next: waiting (CI on PR #542 and merge gate)
argus closed this issue 2026-10-28 13:44:10 +00:00
Sign in to join this conversation.
No labels
loop
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#539
No description provided.