test: the network is checked by the suite now, and /proc/netif says what it did
The TCP/IP stack landed with its end-to-end test performed by hand: start a listener, boot, type nettest, read the output. That is evidence once and nothing afterwards, and it is exactly the kind of check that quietly stops being run. bootcheck -Net does the whole exchange. A listener runs on this host on a port picked by binding one and letting go, the guest is told to connect out to 10.0.2.2 at that port, and both ends are asserted: the guest reports what it received, the listener reports what arrived. One side alone proves much less than it looks -- a stack that completes a handshake and then drops every byte satisfies any check made from inside the guest. The listener is a background job, a separate process, because this harness has one hard rule: nothing may block the writer feeding QEMU's stdin. A socket accept is precisely the wait that deadlocked two earlier attempts at reading QEMU's output. It answers the protocol nettest speaks and then closes -- the close is load-bearing, since nettest reads until end of file and a listener that stayed open would hang the guest rather than fail it. The NIC is spelled out (-netdev user + -device e1000) rather than left to QEMU's default. Other runs can take the default and still answer "did a driver bind"; a run that asserts on an address should be reading its own configuration. /proc/netif is new, and the address is why. Until now the only report was a line on the console at boot, which userland cannot read and a test can only find by scraping the transcript. It gives interface, MAC, state, address, netmask, gateway, MTU and frame counts. Named netif rather than net on purpose: /proc/net is a *directory* on Linux, and a plain file there would give ENOTDIR to anything reaching for /proc/net/dev, which is worse than not having it. The counters are kept at the lwIP seam rather than in the driver, because a frame the driver received and the netif dropped never reached the stack. Verified: 38 [ok], no failures. Eleven of them are new -- lwIP up, DHCP obtaining 10.0.2.15 from SLIRP (a number nothing in the guest knows in advance, so it is the exchange completing rather than a guess), the four /proc/netif fields, frames counted in both directions, the handshake, the reply read back, and the listener confirming HELLO-FROM-SCHOS arrived. One bug found by writing it: $netPort was chosen after the command list was built, so the guest ran `nettest 10.0.2.2` with no port and printed its usage. An unset PowerShell variable interpolates to nothing rather than failing, which is worth remembering next time a command in this file looks right and behaves oddly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c0806d1b64
commit
f46fb41966
6 changed files with 268 additions and 1 deletions
|
|
@ -24,6 +24,19 @@
|
|||
|
||||
static struct netif e1000_netif;
|
||||
|
||||
// Frames in and out, for /proc/netif. Counted here rather than in the driver
|
||||
// because this is the seam lwIP actually uses: a frame the driver received and
|
||||
// this file dropped never reached the stack, and a counter kept one layer down
|
||||
// would say otherwise. Only the network thread touches them, so no lock.
|
||||
static uint64 rx_frames, tx_frames;
|
||||
|
||||
void
|
||||
net_e1000_counts(uint64 *rx, uint64 *tx)
|
||||
{
|
||||
*rx = rx_frames;
|
||||
*tx = tx_frames;
|
||||
}
|
||||
|
||||
// One staging buffer, 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.
|
||||
|
|
@ -56,6 +69,7 @@ e1000_linkoutput(struct netif *netif, struct pbuf *p)
|
|||
if (e1000_transmit(txframe, off) != 0)
|
||||
return ERR_WOULDBLOCK;
|
||||
|
||||
tx_frames++;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +145,7 @@ net_e1000_poll(void)
|
|||
if (e1000_netif.input(p, &e1000_netif) != ERR_OK)
|
||||
pbuf_free(p);
|
||||
|
||||
rx_frames++;
|
||||
moved++;
|
||||
}
|
||||
return moved;
|
||||
|
|
|
|||
Loading…
Reference in a new issue