#pragma once // The network class: what the TCP/IP stack talks to instead of a driver. // // 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. // Without this the first driver's name spreads: kernel/net/net.c called // e1000_present(), the lwIP glue was named netif_e1000.c and called // e1000_transmit(), and adding a second NIC would have meant editing the // protocol stack to add it. That is the mistake include/device.h was written // to prevent, made once anyway because the net class did not exist yet -- // kernel/drivers/net/e1000/e1000.c even said so, with `.ops = 0, // no class // vtable yet`. // // A driver publishes one of these and is then finished with the network stack // forever: it never mentions lwIP, and the stack never mentions it. // // Found with device_find_class(DEVCLASS_NET) or, when there may be more than // one, netdev_at(); see include/device.h. #include "device.h" struct netdev_ops { // Queue one frame for transmission. Returns 0, or -1 if the ring is full -- // which is congestion, not failure, and the caller is expected to retry. int (*transmit)(struct device *, const void *frame, int len); // Take one received frame if there is one. Returns its length, or 0 when // nothing is waiting. Never blocks: the caller decides how to wait. int (*receive)(struct device *, void *out, int cap); // The station address, six bytes. Every Ethernet interface has one and the // stack needs it before it can send anything, so this is not optional. const unsigned char *(*mac)(struct device *); // Whether the link is up. Optional -- a driver that cannot tell leaves this // null and is treated as connected, which is the assumption that was made // before any driver could report it. int (*link_up)(struct device *); }; // The i-th bound network device, or 0 past the end. Dense over interfaces // that have both a driver and a vtable, so the stack can simply count up. struct device *netdev_at(int i); int netdev_count(void); // Wrappers with the null checks in one place, so no caller is written around // a vtable that may be absent or partly filled in. int netdev_transmit(struct device *, const void *frame, int len); int netdev_receive(struct device *, void *out, int cap); const unsigned char *netdev_mac(struct device *); int netdev_link_up(struct device *); // Tell the network stack a frame has arrived, from a driver's interrupt handler. // // The driver does not deliver the frame here and must not: the stack pulls with // .receive, from a thread that can sleep, and an interrupt handler cannot. This // only ends the thread's wait early, so the frame is taken now rather than at // the next clock tick -- which is up to 10 ms away. // // Safe to call with interrupts off; see the note above netdev_rx_signal in // kernel/net/net.c for why the wait is on the tick and not a channel of its own. void netdev_rx_signal(void); // Send an ARP request by hand and wait for the reply. `echo n > /proc/sysrq`. // // It proves the whole driver path at once -- descriptor formats, the DD // handshake, tail bookkeeping, DMA addresses, the receive ring hand-back and // the MAC filter -- because an ARP reply is addressed to this station and does // not arrive if the filter is wrong. Written for the e1000 before there was a // stack to test it with; it belongs to the class rather than to that driver, // since it is the check every new NIC driver will want first. void netdev_selftest(void);