// SPDX-License-Identifier: GPL-2.0-or-later // // lwIP network interfaces over the netdev class. // // The seam, and it is deliberately driver-agnostic: everything about IP, ARP // and TCP lives in lwIP, everything about descriptors and registers lives in a // driver, and this file knows only that a network device can transmit a frame, // receive a frame and state its MAC address. It was `netif_e1000.c` and called // `e1000_transmit` directly, which meant the second NIC driver would have // arrived with a second near-identical copy of this file. See include/dev/netdev.h. // // One netif per bound interface, up to NETIF_MAX. Two NICs is an ordinary // machine -- a laptop with Ethernet and the virtual one QEMU adds is already // two -- and the limit exists only because a fixed array is simpler than // allocation for something enumerated once at boot. #include "core/types.h" #include "core/defs.h" #include "core/param.h" #include "dev/device.h" #include "dev/netdev.h" #include "lwip/opt.h" #include "lwip/netif.h" #include "lwip/pbuf.h" #include "lwip/etharp.h" #include "lwip/ethip6.h" #include "netif/ethernet.h" #define ETH_MTU 1500 #define ETH_FRAMESZ 1518 // 1500 payload + 14 header + 4 FCS allowance struct eth_if { struct netif netif; struct device *dev; // Frames in and out, for /proc/netif. Counted at this seam rather than in // the driver on purpose: a frame the driver received and this file dropped // never reached the stack, and a counter one layer down would say it did. uint64 rx_frames, tx_frames; int used; }; static struct eth_if ifs[NETIF_MAX]; static int nifs; // One staging buffer each, not one per call: a frame is 1518 bytes and the // kernel stack is 4096 in total, so a local of this size on a path that is // several frames deep is exactly the overflow the kstack canary exists to // catch. Safe as a single static because every caller holds the lwIP lock -- // which is also why one pair serves every interface. static char txframe[ETH_FRAMESZ]; static char rxframe[ETH_FRAMESZ]; // Send one packet. lwIP hands over a pbuf chain; a driver wants one flat // buffer, so this walks the chain into txframe. static err_t eth_linkoutput(struct netif *netif, struct pbuf *p) { struct eth_if *e = netif->state; if (p->tot_len > sizeof(txframe)) return ERR_IF; u16_t off = 0; for (struct pbuf *q = p; q != NULL; q = q->next) { if (off + q->len > sizeof(txframe)) return ERR_IF; memmove(txframe + off, q->payload, q->len); off += q->len; } // A full transmit ring is congestion, not failure. Reporting ERR_IF would // make lwIP drop the segment and wait for a retransmission timer; // ERR_WOULDBLOCK lets it try again, which for TCP is the difference between // a stall of milliseconds and one of seconds. if (netdev_transmit(e->dev, txframe, off) != 0) return ERR_WOULDBLOCK; e->tx_frames++; return ERR_OK; } // Bring one interface up. Called by netif_add, once per device. static err_t eth_netif_init(struct netif *netif) { struct eth_if *e = netif->state; const unsigned char *mac = netdev_mac(e->dev); netif->name[0] = 'e'; netif->name[1] = 'n'; netif->output = etharp_output; // IP -> ARP -> linkoutput netif->linkoutput = eth_linkoutput; netif->mtu = ETH_MTU; netif->hwaddr_len = 6; for (int i = 0; i < 6; i++) netif->hwaddr[i] = mac ? mac[i] : 0; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; return ERR_OK; } // Attach one network device. Returns its interface index, or -1. // // No address: DHCP fills that in, and an interface that came up with a // hardcoded one would be wrong on every network but the one it was written on. int net_eth_attach(struct device *dev) { ip4_addr_t any; if (nifs >= NETIF_MAX || dev == 0) return -1; struct eth_if *e = &ifs[nifs]; e->dev = dev; e->used = 1; IP4_ADDR(&any, 0, 0, 0, 0); if (netif_add(&e->netif, &any, &any, &any, e, eth_netif_init, netif_input) == NULL) { e->used = 0; return -1; } // The first one is the default route. With one interface that is the only // possible answer; with two it is a policy decision that belongs to a // routing table this kernel does not have yet, and picking the first is at // least a rule rather than an accident of enumeration order. if (nifs == 0) netif_set_default(&e->netif); netif_set_up(&e->netif); if (netdev_link_up(dev)) netif_set_link_up(&e->netif); else netif_set_link_down(&e->netif); return nifs++; } // An interface whose device has gone away. // // The missing half of net_eth_attach, and it went missing because nothing had // ever taken a device back. /dev/pci does: the kernel's e1000 driver hands the // NIC to a process, and until this existed the interface stayed in lwIP -- // up, holding an address, holding the route to its subnet, and attached to a // driver that now refuses every frame. Packets went to it and stopped, which // looks exactly like a driver that is not working. // // The slot is left occupied rather than compacted. Interface indices are // visible in /proc/netif and in the names the stack has already handed out, // and renumbering them because a device left would be worse than a gap. int net_eth_detach(struct device *dev) { int i; for (i = 0; i < nifs; i++) { if (!ifs[i].used || ifs[i].dev != dev) continue; // Down first, then out. netif_remove() does stop DHCP and send the // release, but a netif removed while still up leaves lwIP's default // route pointing at freed storage if this was interface 0. netif_set_link_down(&ifs[i].netif); netif_set_down(&ifs[i].netif); if (netif_default == &ifs[i].netif) netif_set_default(NULL); netif_remove(&ifs[i].netif); ifs[i].used = 0; ifs[i].dev = 0; // Something else becomes the default, if anything can. A machine with // a second interface should not lose its route because the first one // was handed to a driver in a process. if (netif_default == NULL) { int j; for (j = 0; j < nifs; j++) if (ifs[j].used) { netif_set_default(&ifs[j].netif); break; } } return i; } return -1; } int net_eth_count(void) { return nifs; } struct netif * net_eth_netif(int i) { if (i < 0 || i >= nifs) return 0; return &ifs[i].netif; } struct device * net_eth_device(int i) { if (i < 0 || i >= nifs) return 0; return ifs[i].dev; } void net_eth_counts(int i, uint64 *rx, uint64 *tx) { if (i < 0 || i >= nifs) { *rx = *tx = 0; return; } *rx = ifs[i].rx_frames; *tx = ifs[i].tx_frames; } // Take whatever the drivers have and push it into lwIP. Returns how many // frames moved across all interfaces, so the caller can tell a busy poll from // an idle one. // // Bounded per interface rather than draining: a receive loop with no limit // starves everything else on a busy network, and the caller comes straight // back anyway. int net_eth_poll(void) { int moved = 0; for (int k = 0; k < nifs; k++) { struct eth_if *e = &ifs[k]; for (int i = 0; i < 32; i++) { int len = netdev_receive(e->dev, rxframe, sizeof(rxframe)); if (len <= 0) break; // PBUF_POOL, so this comes from lwIP's own pool rather than a heap // it does not have. A null return means the pool is exhausted, // which is a dropped packet -- entirely normal under load, and what // the protocol above is designed to survive. struct pbuf *p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); if (p == NULL) break; pbuf_take(p, rxframe, (u16_t)len); // netif->input is netif_input, set at netif_add: it dispatches on // the Ethernet type. Ownership of the pbuf passes with the call, // including when it fails, so there is nothing to free here. if (e->netif.input(p, &e->netif) != ERR_OK) pbuf_free(p); e->rx_frames++; moved++; } } return moved; }