net: an interface that appears after boot starts the stack
With the native r8169 out of the registry, the TUF A15 boots with no network device; netinit() saw none and left the stack off, and net_attach_late() then refused every interface that came later -- its comment assumed netinit() was still to run. Linux's r8169 under LDLS got as far as registering ldls0 and was turned away. A late interface now starts the stack, whose first act is to attach every device there is; net_eth_attach() refuses a device it already has, for the window in which both could offer it. LDLS says which refusal it got: EBUSY is another process, anything else is the kernel. Tested in QEMU with -nic none and netecho: no interface at boot, then ldls0 with a DHCP lease and ping answered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
d437e42b49
commit
a9d2e14004
3 changed files with 21 additions and 4 deletions
|
|
@ -110,6 +110,11 @@ net_eth_attach(struct device *dev)
|
|||
|
||||
if (nifs >= NETIF_MAX || dev == 0)
|
||||
return -1;
|
||||
// Once only: a device that appears while netd is starting can be offered
|
||||
// both by netd's boot-time walk and by net_attach_late.
|
||||
for (int i = 0; i < nifs; i++)
|
||||
if (ifs[i].used && ifs[i].dev == dev)
|
||||
return -1;
|
||||
|
||||
struct eth_if *e = &ifs[nifs];
|
||||
e->dev = dev;
|
||||
|
|
|
|||
|
|
@ -194,8 +194,16 @@ net_attach_late(struct device *d)
|
|||
{
|
||||
int idx;
|
||||
|
||||
if (!net_ready)
|
||||
return -1; // netinit() has not run; it will pick this up
|
||||
// No stack yet. Either netinit() is still to run, or it ran on a machine
|
||||
// with no network device and left the stack off -- which is every boot
|
||||
// now that the laptop's RTL8168 is driven by a process (LDLS) that only
|
||||
// appears later. Start it: net_thread's first act is to attach every
|
||||
// network device there is, and that now includes this one.
|
||||
if (!net_ready) {
|
||||
if (!net_started)
|
||||
netinit();
|
||||
return net_started ? 0 : -1;
|
||||
}
|
||||
|
||||
lwip_sys_lock();
|
||||
idx = net_eth_attach(d);
|
||||
|
|
|
|||
|
|
@ -220,8 +220,12 @@ kpi_register_netdev(void *dev)
|
|||
c.pad[0] = c.pad[1] = 0;
|
||||
c.name[0] = 'l'; c.name[1] = 'd'; c.name[2] = 'l'; c.name[3] = 's';
|
||||
|
||||
if (ioctl(kpi.netfd, NETUSERIOC_CREATE, &c) < 0) {
|
||||
kpi_log("kpi: /dev/netdev is already somebody else's\n");
|
||||
int r = ioctl(kpi.netfd, NETUSERIOC_CREATE, &c);
|
||||
if (r < 0) {
|
||||
// -16 EBUSY is another process; anything else is the kernel refusing.
|
||||
kpi_log(r == -16 ? "kpi: /dev/netdev is already somebody else's\n"
|
||||
: "kpi: the kernel would not take the interface, error ");
|
||||
if (r != -16) { kpi_lognum(r); kpi_log("\n"); }
|
||||
close(kpi.netfd);
|
||||
kpi.netfd = -1;
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue