ref: 62612f92fb7cc773c41096d50e02abaf2b22a37e
parent: 1e0f61fbb332c08a643855c49bf0c00992b9afbb
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 15 14:00:17 EDT 2026
devether: inhibit transmission when link is down When the link is explicitely set down, bypass Ether.oq with a drop() function. This also flushes the transmit queue when link is being set down. The Ether.transmit() function is basically Queue.kick(), which already handles bypass case. So use it like that instead. Those drivers that create the Ether.oq themselfs need to be adjusted to pass their transmit function and Ether* arg to qopen(). Introduce initial Ether.link == -1 that signifies initial "unknown" link state. This is here to ensure that drivers which do not handle link management by calling ethersetlink() continue to work.
--- a/sys/src/9/mtx/ether2114x.c
+++ b/sys/src/9/mtx/ether2114x.c
@@ -604,7 +604,7 @@
bp->wp += sizeof(bi)*16;
ctlr->setupbp = bp;
- ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ ether->oq = qopen(256*1024, Qmsg, (void (*)(void*))transmit, ether);
transmit(ether);
}
--- a/sys/src/9/pc/ether2114x.c
+++ b/sys/src/9/pc/ether2114x.c
@@ -627,7 +627,7 @@
bp->wp += sizeof(bi)*16;
ctlr->setupbp = bp;
- ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ ether->oq = qopen(256*1024, Qmsg, (void (*)(void*))transmit, ether);
transmit(ether);
}
--- a/sys/src/9/pc/ether82557.c
+++ b/sys/src/9/pc/ether82557.c
@@ -1292,7 +1292,7 @@
* Load the chip configuration and start it off.
*/
if(ether->oq == 0)
- ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ ether->oq = qopen(256*1024, Qmsg, (void (*)(void*))transmit, ether);
configure(ether, 0);
command(ctlr, CUstart, PADDR(&ctlr->cbr->status));
--- a/sys/src/9/port/devether.c
+++ b/sys/src/9/port/devether.c
@@ -24,6 +24,12 @@
static int etheroqsize(Ether*);
static int etheriqsize(Ether*);
+static void
+drop(void*, Block *b)
+{+ freeb(b);
+}
+
Chan*
etherattach(char* spec)
{@@ -98,6 +104,7 @@
if(f->bridge || f->bypass)
memset(ether->mactab, 0, sizeof(ether->mactab));
if(f->bypass){+ qsetbypass(ether->oq, ether->link? nil: drop);
qsetlimit(ether->oq, etheroqsize(ether));
netifsetlimit(ether, etheriqsize(ether));
}
@@ -292,8 +299,6 @@
}
ether->outpackets++;
qbwrite(ether->oq, bp);
- if(ether->transmit != nil)
- ether->transmit(ether);
}
static long
@@ -307,9 +312,11 @@
if(NETTYPE(chan->qid.path) != Ndataqid) {nn = netifwrite(ether, chan, buf, n);
if(nn >= 0){- /* ignore mbps and use large input queue size when bypassed */
+ /* got bypassed? */
if(ether->f[NETID(chan->qid.path)]->bypass){- qflush(ether->oq);
+ /* flush and bypass output queue */
+ qsetbypass(ether->oq, drop);
+ /* ignore mbps and use large input queue size */
netifsetlimit(ether, MB);
}
return nn;
@@ -431,7 +438,7 @@
ether->irq = -1;
ether->ctlrno = ctlrno;
ether->mbps = 10;
- ether->link = 0;
+ ether->link = -1; /* unknown state */
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
@@ -470,7 +477,7 @@
q = etheroqsize(ether);
if(ether->oq == nil){- ether->oq = qopen(q, Qmsg, 0, 0);
+ ether->oq = qopen(q, Qmsg, (void (*)(void*))ether->transmit, ether);
if(ether->oq == nil)
panic("etherreset %s: can't allocate output queue", ether->name); } else {@@ -497,19 +504,22 @@
}
void
-ethersetlink(Ether *ether, int link)
+ethersetlink(Ether *ether, int new)
{- link = !!link;
- if(!!ether->link == link)
+ int old = ether->link;
+
+ new = !!new;
+ if(old == new)
return;
- ether->link = link;
+ ether->link = new;
if(ether->f == nil || ether->bypass)
return;
memset(ether->mactab, 0, sizeof(ether->mactab));
- if(link)
+ qsetbypass(ether->oq, ether->link? nil: drop);
+ if(ether->link)
print("#l%d: %s: link up: %dMbps\n",ether->ctlrno, ether->type, ether->mbps);
- else
+ else if(old > 0)
print("#l%d: %s: link down\n",ether->ctlrno, ether->type);
}
@@ -647,8 +657,6 @@
qiwrite(netcons->ether->oq, p, netcons->n);
netcons->n = PktHdr;
iunlock(netcons);
- if(netcons->ether->transmit != nil)
- netcons->ether->transmit(netcons->ether);
}
static PhysUart netconsphys = { .putc = netconsputc };--
⑨