SchOS/include/net/netuser.h
Nexoniarz a1c965da1e include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2026-10-23 15:05:12 +02:00

64 lines
2.5 KiB
C

#pragma once
// /dev/netdev -- being a network interface, from a process.
//
// docs/architecture/ldls.md calls this "the class bridge", and it is the one
// kernel interface LDLS needed that did not already exist. A driver hosted by LDLS produces packets
// in a process; the network stack consumes them through `struct netdev_ops` in
// the kernel. This is what joins the two.
//
// It is the exact analogue of what `display_ops` is for the GPU, and
// include/dev/netdev.h's own opening comment already anticipated the shape:
//
// "the stack should ask for the network interfaces and get whatever is
// bound -- today an e1000, tomorrow a virtio-net or an rtl8139 -- exactly
// as a compositor asks for the display and does not care which driver
// answers."
//
// The interface is four calls wide because `netdev_ops` is, and it is
// deliberately not a superset of it. Nothing here knows what a driver is:
//
// ioctl(NETUSERIOC_CREATE) become an interface, with this MAC
// read() a frame the stack wants sent
// write() a frame that arrived on the wire
// ioctl(NETUSERIOC_RELEASE) stop being one; exiting does this too
//
// **A process is the wire.** Whether there is real hardware on the other side
// of it is the process's business, which is what makes this usable by an
// LDLS-hosted Linux driver and equally by a test program with no hardware at
// all -- and the second one is how the first is debugged.
#include "core/types.h"
#define NETUSER_MAJOR 11
// One Ethernet frame, with room for the 1500-byte payload, the header and a
// VLAN tag. Frames larger than this are refused rather than truncated: a short
// frame handed to a protocol stack is a corrupt packet, which is worse than a
// dropped one.
#define NETUSER_MTU 1536
// Frames buffered in each direction. Small on purpose -- this is a queue for
// smoothing a scheduling gap, not for absorbing a burst, and a deep queue on a
// network path adds latency instead of throughput.
#define NETUSER_QLEN 16
struct netuser_create {
uint8 mac[6];
uint8 pad[2];
// The interface's base name; the device model appends an index, so "ldls"
// becomes "ldls0". Empty means "eth".
char name[16];
};
// Counters, for `schdbg net` and for answering "is anything moving".
struct netuser_stat {
uint64 tx_frames, tx_bytes, tx_dropped;
uint64 rx_frames, rx_bytes, rx_dropped;
int attached; // a process holds it
int pad;
};
#define NETUSERIOC_CREATE 0x4e01
#define NETUSERIOC_RELEASE 0x4e02
#define NETUSERIOC_STAT 0x4e03