L4 was listed as "free -- H2 built all of this" and never actually tested,
which is a claim rather than a result. Tested now, and it holds:
ldlsd running ping 2/2; holds index 7 and DMA slots 3 and 4
killed interface DOWN, device released, bus mastering
cleared, DMA reclaimed -- back to vgpud's 3 blocks
ping fails honestly: sendto: -5
a second ldlsd ping 3/3, and the arena hands back the same addresses
pciuser_release_all() and netuser_release_all() sit beside each other in
exit() for the same reason, and that they apply unchanged to a foreign driver
is the whole point of having built them against our own.
With that, every milestone on ldls.md is done, so it leaves docs/plan/ for
docs/architecture/ -- the rule docs/plan/README.md states and the one that
keeps the two directories meaning different things. The new document describes
what is, not what was planned: the five rules, the four pieces, what it costs
(polling, no stack protector, locks that are no-ops), that it can be killed,
and a "what it does not do" that leads with one driver, one kernel version,
tried once.
Sixteen source files pointed at docs/plan/ldls.md and would have been dangling
the moment it moved. All repointed, and the milestone references -- which the
architecture doc deliberately does not have -- rewritten to name sections
instead, so a reader lands somewhere real.
The register row closes with it. hybrid.md freed a slot, ldls.md took it, and
it is now free again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
64 lines
2.5 KiB
C
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/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
|