#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/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 "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