shithub: riscv

Download patch

ref: 729c9c39d9156674f61d086e3306bcc04ce8dfc5
parent: a2e8246ffc12660f8628266e73aae74b52bd86d8
author: cinap_lenrek <[email protected]>
date: Sun Feb 18 14:56:01 EST 2018

devether: mux bridges, portable netconsole

--- a/sys/src/9/kw/ether1116.c
+++ b/sys/src/9/kw/ether1116.c
@@ -643,7 +643,7 @@
 		 * in memory (mv-s104860-u0 §8.3.4.1)
 		 */
 		b->rp += 2;
-		etheriq(ether, b, 1);
+		etheriq(ether, b);
 		etheractive(ether);
 		if (i % (Nrx / 2) == 0) {
 			rxreplenish(ctlr);
--- a/sys/src/9/mtx/ether2114x.c
+++ b/sys/src/9/mtx/ether2114x.c
@@ -468,7 +468,7 @@
 				else if(bp = iallocb(Rbsz)){
 					len = ((des->status & Fl)>>16)-4;
 					des->bp->wp = des->bp->rp+len;
-					etheriq(ether, des->bp, 1);
+					etheriq(ether, des->bp);
 					des->bp = bp;
 					des->addr = PCIWADDR(bp->rp);
 				}
--- a/sys/src/9/omap/ether9221.c
+++ b/sys/src/9/omap/ether9221.c
@@ -642,7 +642,7 @@
 
 			/* and push the Block upstream */
 			if (ctlr->inited)
-				etheriq(edev, bp, 1);
+				etheriq(edev, bp);
 			else
 				freeb(bp);
 
--- a/sys/src/9/pc/ether2114x.c
+++ b/sys/src/9/pc/ether2114x.c
@@ -477,7 +477,7 @@
 				else if(bp = iallocb(Rbsz)){
 					len = ((des->status & Fl)>>16)-4;
 					des->bp->wp = des->bp->rp+len;
-					etheriq(ether, des->bp, 1);
+					etheriq(ether, des->bp);
 					des->bp = bp;
 					des->addr = PCIWADDR(bp->rp);
 				}
--- a/sys/src/9/pc/ether79c970.c
+++ b/sys/src/9/pc/ether79c970.c
@@ -424,7 +424,7 @@
 				if(bb != nil){
 					len = (dre->md2 & 0x0FFF)-4;
 					bb->wp = bb->rp+len;
-					etheriq(ether, bb, 1);
+					etheriq(ether, bb);
 				}
 				dre->addr = PADDR(bp->rp);
 			}
--- a/sys/src/9/pc/ether8139.c
+++ b/sys/src/9/pc/ether8139.c
@@ -583,7 +583,7 @@
 				bp->wp += length;
 			}
 			bp->wp -= 4;
-			etheriq(edev, bp, 1);
+			etheriq(edev, bp);
 		}
 
 		capr = ROUNDUP(capr, 4);
--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -970,7 +970,7 @@
 				bp->flag |= Bipck;
 				break;
 			}
-			etheriq(edev, bp, 1);
+			etheriq(edev, bp);
 		}else{
 			if(!(control & Res))
 				ctlr->frag++;
--- a/sys/src/9/pc/ether82543gc.c
+++ b/sys/src/9/pc/ether82543gc.c
@@ -851,7 +851,7 @@
 			ctlr->rb[rdh] = nil;
 			bp->wp += rdesc->length;
 			bp->next = nil;
-			etheriq(edev, bp, 1);
+			etheriq(edev, bp);
 		}
 
 		if(ctlr->rb[rdh] != nil){
--- a/sys/src/9/pc/ether82557.c
+++ b/sys/src/9/pc/ether82557.c
@@ -655,7 +655,7 @@
 				bp = xbp;
 			}
 			if(pbp != nil)
-				etheriq(ether, pbp, 1);
+				etheriq(ether, pbp);
 		}
 		else{
 			rfd->count = 0;
--- a/sys/src/9/pc/ether82563.c
+++ b/sys/src/9/pc/ether82563.c
@@ -1062,7 +1062,7 @@
 					bp->checksum = rd->checksum;
 					bp->flag |= Bpktck;
 				}
-				etheriq(edev, bp, 1);
+				etheriq(edev, bp);
 			} else
 				freeb(bp);
 			ctlr->rb[rdh] = nil;
--- a/sys/src/9/pc/ether82598.c
+++ b/sys/src/9/pc/ether82598.c
@@ -584,7 +584,7 @@
 		b->checksum = r->cksum;
 	}
 //	r->status = 0;
-	etheriq(e, b, 1);
+	etheriq(e, b);
 	c->rdfree--;
 	rdh = Next(rdh, m);
 	goto loop1;			/* UGH */
--- a/sys/src/9/pc/ether83815.c
+++ b/sys/src/9/pc/ether83815.c
@@ -545,7 +545,7 @@
 						freeb(des->bp);
 					}else{
 						des->bp->wp = des->bp->rp+len;
-						etheriq(ether, des->bp, 1);
+						etheriq(ether, des->bp);
 					}
 					des->bp = bp;
 					des->addr = PADDR(bp->rp);
--- a/sys/src/9/pc/ether8390.c
+++ b/sys/src/9/pc/ether8390.c
@@ -439,7 +439,7 @@
 			/*
 			 * Copy the packet to whoever wants it.
 			 */
-			etheriq(ether, bp, 1);
+			etheriq(ether, bp);
 		}
 
 		/*
--- a/sys/src/9/pc/etherbcm.c
+++ b/sys/src/9/pc/etherbcm.c
@@ -414,7 +414,7 @@
 		if(pkt[3] & FrameError) {
 			freeb(bp); /* dump erroneous packets */ 
 		} else {
-			etheriq(edev, bp, 1);
+			etheriq(edev, bp);
 		}
 	}
 }
--- a/sys/src/9/pc/etherdp83820.c
+++ b/sys/src/9/pc/etherdp83820.c
@@ -839,7 +839,7 @@
 					bp = desc->bp;
 					desc->bp = nil;
 					bp->wp += cmdsts & SizeMASK;
-					etheriq(edev, bp, 1);
+					etheriq(edev, bp);
 				}
 				else if(0 && !(cmdsts & Ok)){
 					iprint("dp83820: rx %8.8uX:", cmdsts);
--- a/sys/src/9/pc/etherelnk3.c
+++ b/sys/src/9/pc/etherelnk3.c
@@ -834,7 +834,7 @@
 		else if(bp = iallocb(sizeof(Etherpkt)+4)){
 			len = pd->control & rxBytes;
 			pd->bp->wp = pd->bp->rp+len;
-			etheriq(ether, pd->bp, 1);
+			etheriq(ether, pd->bp);
 			pd->bp = bp;
 			pd->addr = PADDR(bp->rp);
 			coherence();
@@ -944,7 +944,7 @@
 		if(ctlr->busmaster == 1)
 			ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
 
-		etheriq(ether, ctlr->rbp, 1);
+		etheriq(ether, ctlr->rbp);
 		ctlr->rbp = bp;
 	}
 }
--- a/sys/src/9/pc/etherga620.c
+++ b/sys/src/9/pc/etherga620.c
@@ -626,7 +626,7 @@
 		if(!(rbd->flags & Ferror) && len != 0){
 			bp = rbd->opaque;
 			bp->wp = bp->rp+len;
-			etheriq(edev, bp, 1);
+			etheriq(edev, bp);
 		}
 		else
 			freeb(rbd->opaque);
--- a/sys/src/9/pc/etherigbe.c
+++ b/sys/src/9/pc/etherigbe.c
@@ -1142,7 +1142,7 @@
 					bp->checksum = rd->checksum;
 					bp->flag |= Bpktck;
 				}
-				etheriq(edev, bp, 1);
+				etheriq(edev, bp);
 			}
 			else if(ctlr->rb[rdh] != nil){
 				freeb(ctlr->rb[rdh]);
--- a/sys/src/9/pc/etherm10g.c
+++ b/sys/src/9/pc/etherm10g.c
@@ -1087,7 +1087,7 @@
 		replenish(&c->bg);
 		sleep(&c->rxrendez, rxcansleep, c);
 		while(b = nextblock(c))
-			etheriq(e, b, 1);
+			etheriq(e, b);
 	}
 }
 
--- a/sys/src/9/pc/ethersmc.c
+++ b/sys/src/9/pc/ethersmc.c
@@ -405,7 +405,7 @@
 		bp->wp++;
 	}
 	  
-	etheriq(ether, bp, 1);
+	etheriq(ether, bp);
 	ether->inpackets++;
 	outs(port + MmuCmd, McRelease);
 }
--- a/sys/src/9/pc/ethervgbe.c
+++ b/sys/src/9/pc/ethervgbe.c
@@ -531,7 +531,7 @@
 			/* plant new block, might fail if out of memory */
 			if(vgbenewrx(ctlr, i) == 0){
 				block->wp = block->rp + length;
-				etheriq(edev, block, 1);
+				etheriq(edev, block);
 				continue;
 			}
 		}
--- a/sys/src/9/pc/ethervirtio.c
+++ b/sys/src/9/pc/ethervirtio.c
@@ -325,7 +325,7 @@
 			blocks[i] = nil;
 
 			b->wp = b->rp + u->len - VheaderSize;
-			etheriq(edev, b, 1);
+			etheriq(edev, b);
 			q->lastused++;
 		}
 	}
--- a/sys/src/9/pc/ethervt6102.c
+++ b/sys/src/9/pc/ethervt6102.c
@@ -720,7 +720,7 @@
 		else if(bp = iallocb(Rdbsz+3)){
 			len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
 			ds->bp->wp = ds->bp->rp+len;
-			etheriq(edev, ds->bp, 1);
+			etheriq(edev, ds->bp);
 			bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
 			ds->addr = PCIWADDR(bp->rp);
 			ds->bp = bp;
--- a/sys/src/9/pc/ethervt6105m.c
+++ b/sys/src/9/pc/ethervt6105m.c
@@ -865,7 +865,7 @@
 			}
 			len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
 			ds->bp->wp = ds->bp->rp+len;
-			etheriq(edev, ds->bp, 1);
+			etheriq(edev, ds->bp);
 			bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
 			ds->addr = PCIWADDR(bp->rp);
 			ds->bp = bp;
--- a/sys/src/9/pc/etheryuk.c
+++ b/sys/src/9/pc/etheryuk.c
@@ -1430,7 +1430,7 @@
 	}else{
 		b->wp += l;
 		b->flag |= flag;
-		etheriq(e, b, 1);
+		etheriq(e, b);
 	}
 	unstarve(&c->rxmit);
 }
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -113,7 +113,6 @@
 void	mtrrclock(void);
 int	mtrrprint(char *, long);
 void	mtrrsync(void);
-void	netconsole(void);
 uchar	nvramread(int);
 void	nvramwrite(int, uchar);
 void	outb(int, int);
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -60,7 +60,6 @@
 	}else
 		links();
 	chandevreset();
-	netconsole();
 	pageinit();
 	userinit();
 	schedinit();
--- a/sys/src/9/pc/wavelan.c
+++ b/sys/src/9/pc/wavelan.c
@@ -452,7 +452,7 @@
 	}
 
 	ctlr->nrx++;
-	etheriq(ether,bp,1);
+	etheriq(ether, bp);
 	ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
 	ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
 	return;
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -111,7 +111,6 @@
 void	mtrrclock(void);
 int	mtrrprint(char *, long);
 void	mtrrsync(void);
-void	netconsole(void);
 void	noteret(void);
 uchar	nvramread(int);
 void	nvramwrite(int, uchar);
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -329,7 +329,6 @@
 	}else
 		links();
 	chandevreset();
-	netconsole();
 	preallocpages();
 	pageinit();
 	userinit();
--- a/sys/src/9/port/devether.c
+++ b/sys/src/9/port/devether.c
@@ -11,6 +11,7 @@
 #include "../port/etherif.h"
 
 extern int eipfmt(Fmt*);
+extern ushort ipcsum(uchar *);
 
 static Ether *etherxx[MaxEther];
 
@@ -70,7 +71,12 @@
 static void
 etherclose(Chan* chan)
 {
-	netifclose(etherxx[chan->dev], chan);
+	Ether *ether = etherxx[chan->dev];
+
+	if(NETTYPE(chan->qid.path) == Ndataqid && ether->f[NETID(chan->qid.path)]->bridge)
+		memset(ether->mactab, 0, sizeof(ether->mactab));
+
+	netifclose(ether, chan);
 }
 
 static long
@@ -109,152 +115,154 @@
 static void
 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
 {
-	int i, n;
 	Block *bp;
 
 	if(qwindow(f->in) <= 0)
 		return;
-	if(len > 58)
-		n = 58;
-	else
-		n = len;
 	bp = iallocb(64);
 	if(bp == nil)
 		return;
-	memmove(bp->wp, pkt->d, n);
-	i = TK2MS(MACHP(0)->ticks);
-	bp->wp[58] = len>>8;
-	bp->wp[59] = len;
-	bp->wp[60] = i>>24;
-	bp->wp[61] = i>>16;
-	bp->wp[62] = i>>8;
-	bp->wp[63] = i;
+	memmove(bp->wp, pkt, len < 64 ? len : 64);
+	if(f->type != -2){
+		u32int ms = TK2MS(MACHP(0)->ticks);
+		bp->wp[58] = len>>8;
+		bp->wp[59] = len;
+		bp->wp[60] = ms>>24;
+		bp->wp[61] = ms>>16;
+		bp->wp[62] = ms>>8;
+		bp->wp[63] = ms;
+	}
 	bp->wp += 64;
 	qpass(f->in, bp);
 }
 
-Block*
-etheriq(Ether* ether, Block* bp, int fromwire)
+static Macent*
+macent(Ether *ether, uchar *ea)
 {
-	Etherpkt *pkt;
-	ushort type;
-	int len, multi, tome, fromme;
-	Netfile **ep, *f, **fp, *fx;
+	u32int h = (ea[0] | ea[1]<<8 | ea[2]<<16 | ea[3]<<24) ^ (ea[4] | ea[5]<<8);
+	return &ether->mactab[h % nelem(ether->mactab)];
+}
+
+/*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (tome || from == nil),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+static Block*
+ethermux(Ether *ether, Block *bp, Netfile **from)
+{
 	Block *xbp;
+	Etherpkt *pkt;
+	Netfile *f, *x, **fp;
+	int len, multi, tome, port, type, dispose;
 
-	ether->inpackets++;
-
-	pkt = (Etherpkt*)bp->rp;
 	len = BLEN(bp);
-	type = (pkt->type[0]<<8)|pkt->type[1];
-	fx = 0;
-	ep = &ether->f[Ntypes];
-
-	multi = pkt->d[0] & 1;
-	/* check for valid multicast addresses */
-	if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
-		if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
-			if(fromwire){
-				freeb(bp);
-				bp = 0;
-			}
+	if(len < ETHERHDRSIZE)
+		goto Drop;
+	pkt = (Etherpkt*)bp->rp;
+	if(!(multi = pkt->d[0] & 1)){
+		tome = memcmp(pkt->d, ether->ea, Eaddrlen) == 0;
+		if(!tome && from != nil && ether->prom == 0)
 			return bp;
+	} else {
+		tome = 0;
+		if(from == nil && ether->prom == 0
+		&& memcmp(pkt->d, ether->bcast, Eaddrlen) != 0
+		&& !activemulti(ether, pkt->d, Eaddrlen))
+			goto Drop;
+	}
+
+	port = -1;
+	if(ether->prom){
+		if((from == nil || (*from)->bridge) && (pkt->s[0] & 1) == 0){
+			Macent *t = macent(ether, pkt->s);
+			t->port = from == nil ? 0 : 1+(from - ether->f);
+			memmove(t->ea, pkt->s, Eaddrlen);
 		}
+		if(!tome && !multi){
+			Macent *t = macent(ether, pkt->d);
+			if(memcmp(t->ea, pkt->d, Eaddrlen) == 0)
+				port = t->port;
+		}
 	}
 
-	/* is it for me? */
-	tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
-	fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+	x = nil;
+	type = (pkt->type[0]<<8)|pkt->type[1];
+	dispose = tome || from == nil || port > 0;
 
-	/*
-	 * Multiplex the packet to all the connections which want it.
-	 * If the packet is not to be used subsequently (fromwire != 0),
-	 * attempt to simply pass it into one of the connections, thereby
-	 * saving a copy of the data (usual case hopefully).
-	 */
-	for(fp = ether->f; fp < ep; fp++){
-		if(f = *fp)
-		if(f->type == type || f->type < 0)
-		if(tome || multi || f->prom){
-			/* Don't want to hear loopback or bridged packets */
-			if(f->bridge && (tome || !fromwire && !fromme))
+	for(fp = ether->f; fp < &ether->f[Ntypes]; fp++){
+		if((f = *fp) == nil)
+			continue;
+		if(f->type != type && f->type >= 0)
+			continue;
+		if(!tome && !multi && !f->prom)
+			continue;
+		if(f->bridge){
+			if(tome || fp == from)
 				continue;
-			if(!f->headersonly){
-				if(fromwire && fx == 0)
-					fx = f;
-				else if(xbp = iallocb(len)){
-					memmove(xbp->wp, pkt, len);
-					xbp->wp += len;
-					xbp->flag = bp->flag;
-					if(qpass(f->in, xbp) < 0) {
-						// print("soverflow for f->in\n");
-						ether->soverflows++;
-					}
-				}
-				else {
-					// print("soverflow iallocb\n");
-					ether->soverflows++;
-				}
-			}
-			else
-				etherrtrace(f, pkt, len);
+			if(port >= 0 && port != 1+(fp - ether->f))
+				continue;
 		}
+		if(f->headersonly || f->type == -2){
+			etherrtrace(f, pkt, len);
+			continue;
+		}
+		if(dispose && x == nil)
+			x = f;
+		else if((xbp = iallocb(len)) != nil){
+			memmove(xbp->wp, pkt, len);
+			xbp->wp += len;
+			xbp->flag = bp->flag;
+			if(qpass(f->in, xbp) < 0)
+				ether->soverflows++;
+		} else
+			ether->soverflows++;
 	}
-
-	if(fx){
-		if(qpass(fx->in, bp) < 0) {
-			// print("soverflow for fx->in\n");
+	if(x != nil){
+		if(qpass(x->in, bp) < 0)
 			ether->soverflows++;
-		}
-		return 0;
+		return nil;
 	}
-	if(fromwire){
-		freeb(bp);
-		return 0;
-	}
 
+	if(dispose){
+Drop:		freeb(bp);
+		return nil;
+	}
 	return bp;
 }
 
-static int
-etheroq(Ether* ether, Block* bp)
+void
+etheriq(Ether* ether, Block* bp)
 {
-	int len, loopback;
-	Etherpkt *pkt;
+	ether->inpackets++;
+	ethermux(ether, bp, nil);
+}
 
-	ether->outpackets++;
+static void
+etheroq(Ether* ether, Block* bp, Netfile **from)
+{
+	if((*from)->bridge == 0)
+		memmove(((Etherpkt*)bp->rp)->s, ether->ea, Eaddrlen);
 
-	/*
-	 * Check if the packet has to be placed back onto the input queue,
-	 * i.e. if it's a loopback or broadcast packet or the interface is
-	 * in promiscuous mode.
-	 * If it's a loopback packet indicate to etheriq that the data isn't
-	 * needed and return, etheriq will pass-on or free the block.
-	 * To enable bridging to work, only packets that were originated
-	 * by this interface are fed back.
-	 */
-	pkt = (Etherpkt*)bp->rp;
-	len = BLEN(bp);
-	loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
-	if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
-		if(etheriq(ether, bp, loopback) == 0)
-			return len;
+	bp = ethermux(ether, bp, from);
+	if(bp == nil)
+		return;
 
+	ether->outpackets++;
 	qbwrite(ether->oq, bp);
 	if(ether->transmit != nil)
 		ether->transmit(ether);
-	return len;
 }
 
 static long
 etherwrite(Chan* chan, void* buf, long n, vlong)
 {
-	Ether *ether;
+	Ether *ether = etherxx[chan->dev];
 	Block *bp;
 	int nn, onoff;
 	Cmdbuf *cb;
 
-	ether = etherxx[chan->dev];
 	if(NETTYPE(chan->qid.path) != Ndataqid) {
 		nn = netifwrite(ether, chan, buf, n);
 		if(nn >= 0)
@@ -287,12 +295,11 @@
 		nexterror();
 	}
 	memmove(bp->rp, buf, n);
-	if(!ether->f[NETID(chan->qid.path)]->bridge)
-		memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
 	poperror();
 	bp->wp += n;
 
-	return etheroq(ether, bp);
+	etheroq(ether, bp, &ether->f[NETID(chan->qid.path)]);
+	return n;
 }
 
 static long
@@ -299,9 +306,8 @@
 etherbwrite(Chan* chan, Block* bp, ulong)
 {
 	Ether *ether;
-	long n;
+	long n = BLEN(bp);
 
-	n = BLEN(bp);
 	if(NETTYPE(chan->qid.path) != Ndataqid){
 		if(waserror()) {
 			freeb(bp);
@@ -312,8 +318,8 @@
 		freeb(bp);
 		return n;
 	}
-	ether = etherxx[chan->dev];
 
+	ether = etherxx[chan->dev];
 	if(n > ether->maxmtu){
 		freeb(bp);
 		error(Etoobig);
@@ -322,8 +328,8 @@
 		freeb(bp);
 		error(Etoosmall);
 	}
-
-	return etheroq(ether, bp);
+	etheroq(ether, bp, &ether->f[NETID(chan->qid.path)]);
+	return n;
 }
 
 static struct {
@@ -422,6 +428,8 @@
 	return ether;
 }
 
+static void netconsole(int);
+
 static void
 etherreset(void)
 {
@@ -436,22 +444,23 @@
 		etherxx[ctlrno] = ether;
 	}
 
-	if(getconf("*noetherprobe"))
-		return;
-
-	cardno = ctlrno = 0;
-	while(cards[cardno].type != nil && ctlrno < MaxEther){
-		if(etherxx[ctlrno] != nil){
+	if(getconf("*noetherprobe") == nil){
+		cardno = ctlrno = 0;
+		while(cards[cardno].type != nil && ctlrno < MaxEther){
+			if(etherxx[ctlrno] != nil){
+				ctlrno++;
+				continue;
+			}
+			if((ether = etherprobe(cardno, ctlrno)) == nil){
+				cardno++;
+				continue;
+			}
+			etherxx[ctlrno] = ether;
 			ctlrno++;
-			continue;
 		}
-		if((ether = etherprobe(cardno, ctlrno)) == nil){
-			cardno++;
-			continue;
-		}
-		etherxx[ctlrno] = ether;
-		ctlrno++;
 	}
+
+	netconsole(1);
 }
 
 static void
@@ -460,6 +469,8 @@
 	Ether *ether;
 	int i;
 
+	netconsole(0);
+
 	for(i = 0; i < MaxEther; i++){
 		ether = etherxx[i];
 		if(ether == nil)
@@ -524,9 +535,7 @@
 };
 static Netconsole *netcons;
 
-extern ushort ipcsum(uchar *);
-
-void
+static void
 netconsputc(Uart *, int c)
 {
 	char *p;
@@ -556,13 +565,11 @@
 		netcons->ether->transmit(netcons->ether);
 }
 
-PhysUart netconsphys = {
-	.putc = netconsputc,
-};
-Uart netconsuart = { .phys = &netconsphys };
+static PhysUart netconsphys = { .putc = netconsputc };
+static Uart netconsuart = { .phys = &netconsphys };
 
-void
-netconsole(void)
+static void
+netconsole(int on)
 {
 	char *p;
 	char *r;
@@ -572,8 +579,15 @@
 	u64int dstmac;
 	Netconsole *nc;
 
+	if(!on){
+		if(consuart == &netconsuart)
+			consuart = nil;
+		return;
+	}
+
 	if((p = getconf("console")) == nil || strncmp(p, "net ", 4) != 0)
 		return;
+
 	p += 4;
 	for(i = 0; i < 4; i++){
 		srcip[i] = strtol(p, &r, 0);
--- a/sys/src/9/port/etherif.h
+++ b/sys/src/9/port/etherif.h
@@ -3,6 +3,13 @@
 	Ntypes		= 8,
 };
 
+typedef struct Macent Macent;
+struct Macent
+{
+	uchar	ea[Eaddrlen];
+	ushort	port;
+};
+
 typedef struct Ether Ether;
 struct Ether {
 	ISAConf;			/* hardware info */
@@ -11,7 +18,6 @@
 	int	ctlrno;
 	int	minmtu;
 	int 	maxmtu;
-	uchar	ea[Eaddrlen];
 
 	void	(*attach)(Ether*);	/* filled in by reset routine */
 	void	(*detach)(Ether*);
@@ -25,9 +31,12 @@
 	Queue*	oq;
 
 	Netif;
+
+	uchar	ea[Eaddrlen];
+	Macent	mactab[127];		/* for bridge */
 };
 
-extern Block* etheriq(Ether*, Block*, int);
+extern void etheriq(Ether*, Block*);
 extern void addethercard(char*, int(*)(Ether*));
 extern ulong ethercrc(uchar*, int);
 extern int parseether(uchar*, char*);
--- a/sys/src/9/port/wifi.c
+++ b/sys/src/9/port/wifi.c
@@ -139,7 +139,7 @@
 
 		dmatproxy(b, 0, wifi->ether->ea, &wifi->dmat);
 
-		etheriq(wifi->ether, b, 1);
+		etheriq(wifi->ether, b);
 		return;
 	}
 drop:
--- a/sys/src/9/ppc/etherfcc.c
+++ b/sys/src/9/ppc/etherfcc.c
@@ -367,7 +367,7 @@
 				dczap(b->rp, len);
 				if(nb = iallocb(Bufsize)){
 					b->wp += len;
-					etheriq(ether, b, 1);
+					etheriq(ether, b);
 					b = nb;
 					b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
 					b->wp = b->rp;
--- a/sys/src/9/ppc/ethersaturn.c
+++ b/sys/src/9/ppc/ethersaturn.c
@@ -176,7 +176,7 @@
 				memmove(b->wp, pkt, len+sizeof(ushort));
 				b->rp += sizeof(ushort);
 				b->wp = b->rp + len;
-				etheriq(ether, b, 1);
+				etheriq(ether, b);
 			}else
 				ether->soverflows++;
 			rx=*ersr&Ersr_rxfpmask;
--- a/sys/src/9/sgi/etherseeq.c
+++ b/sys/src/9/sgi/etherseeq.c
@@ -250,7 +250,7 @@
 			b = allocb(n);
 			b->wp += n;
 			memmove(b->rp, p->base+2, n);
-			etheriq(edev, b, 1);
+			etheriq(edev, b);
 		}
 		p->addr = PADDR(p->base);
 		p->count = Ioc|Empty|Rbsize;
--- a/sys/src/9/teg2/ether8169.c
+++ b/sys/src/9/teg2/ether8169.c
@@ -828,7 +828,7 @@
 
 	allcache->invse(bp->rp, len);	/* clear any stale cached packet */
 	ckrderrs(ctlr, bp, control);
-	etheriq(edev, bp, 1);
+	etheriq(edev, bp);
 
 	if(Debug > 1)
 		iprint("R%d ", len);
--- a/sys/src/9/xen/etherxen.c
+++ b/sys/src/9/xen/etherxen.c
@@ -248,7 +248,7 @@
 	bp->list = 0;
 	if (rr->flags & NETRXF_data_validated)
 		bp->flag |= Btcpck|Budpck;
-	etheriq(ether, bp, 1);
+	etheriq(ether, bp);
 	return 0;
 }
 
--- a/sys/src/9/zynq/etherzynq.c
+++ b/sys/src/9/zynq/etherzynq.c
@@ -235,7 +235,7 @@
 		bp->wp = bp->rp + (r[1] & 0x1fff);
 		invaldse(bp->rp, bp->wp);
 		inval2pa(PADDR(bp->rp), PADDR(bp->wp));
-		etheriq(edev, bp, 1);
+		etheriq(edev, bp);
 		c->rxconsi = (c->rxconsi + 1) & (RXRING - 1);
 		replenish(c);
 	}