ref: 986278e04d34ff62aaa8d24726e2540cfbd463cd
parent: 729c9c39d9156674f61d086e3306bcc04ce8dfc5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Feb 18 14:56:58 EST 2018
nusb/ether: mux bridges, bring in line with devether
--- a/sys/src/cmd/nusb/ether/asix.c
+++ b/sys/src/cmd/nusb/ether/asix.c
@@ -227,10 +227,10 @@
if((n != hd) || (n > BLEN(b)))
break;
if(n == BLEN(b)){
- etheriq(b, 1);
+ etheriq(b);
return 0;
}
- etheriq(copyblock(b, n), 1);
+ etheriq(copyblock(b, n));
b->rp += n;
}
freeb(b);
@@ -309,7 +309,7 @@
asixset(d, Creset, Rippd|Rprl);
sleep(150);
asixset(d, Cwrxctl, 0);
- if(asixget(d, Crmac, macaddr, 6) < 0)
+ if(asixget(d, Crmac, macaddr, Eaddrlen) < 0)
return -1;
asixphy = getphy(d);
if(ee17 < 0 || (ee17 & 0x7) == 0){
@@ -364,7 +364,7 @@
getrxctl(d);
if(asixset(d, Cwrxctl, 0) < 0)
return -1;
- if(asixget(d, Crmac, macaddr, 6) < 0)
+ if(asixget(d, Crmac, macaddr, Eaddrlen) < 0)
return -1;
if(asixset(d, Creset, Rprl) < 0)
return -1;
--- a/sys/src/cmd/nusb/ether/aue.c
+++ b/sys/src/cmd/nusb/ether/aue.c
@@ -186,7 +186,7 @@
return 0;
}
b->wp = b->rp + n;
- etheriq(b, 1);
+ etheriq(b);
return 0;
}
--- a/sys/src/cmd/nusb/ether/cdc.c
+++ b/sys/src/cmd/nusb/ether/cdc.c
@@ -23,7 +23,7 @@
return -1;
}
b->wp += n;
- etheriq(b, 1);
+ etheriq(b);
return 0;
}
--- a/sys/src/cmd/nusb/ether/dat.h
+++ b/sys/src/cmd/nusb/ether/dat.h
@@ -1,8 +1,6 @@
typedef struct Block Block;
struct Block
{
- Ref;
-
Block *next;
uchar *rp;
@@ -15,20 +13,29 @@
#define BLEN(s) ((s)->wp - (s)->rp)
Block* allocb(int size);
-void freeb(Block*);
Block* copyblock(Block*, int);
+#define freeb(b) free(b)
-typedef struct Ehdr Ehdr;
-struct Ehdr
+enum {
+ Eaddrlen= 6,
+ ETHERHDRSIZE= 14, /* size of an ethernet header */
+ Maxpkt= 2000,
+};
+
+typedef struct Macent Macent;
+struct Macent
{
- uchar d[6];
- uchar s[6];
- uchar type[2];
+ uchar ea[Eaddrlen];
+ ushort port;
};
-enum {
- Ehdrsz = 6+6+2,
- Maxpkt = 2000,
+typedef struct Etherpkt Etherpkt;
+struct Etherpkt
+{
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
};
enum
@@ -41,14 +48,16 @@
int debug;
int setmac;
-/* to be filled in by *init() */
-uchar macaddr[6];
-
int nprom;
int nmulti;
-uchar multiaddr[32][6];
+uchar multiaddr[32][Eaddrlen];
-void etheriq(Block*, int wire);
+/* to be filled in by *init() */
+uchar macaddr[Eaddrlen];
+
+Macent mactab[127];
+
+void etheriq(Block*);
int (*epreceive)(Dev*);
void (*eptransmit)(Dev*, Block*);
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -68,6 +68,7 @@
int type;
int prom;
int bridge;
+ int headersonly;
Dq *dq;
};
@@ -78,6 +79,8 @@
int out;
};
+uchar bcast[Eaddrlen] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
Stats stats;
Conn conn[32];
int nconn = 0;
@@ -268,6 +271,9 @@
}
static void
+etheroq(Block*, Conn*);
+
+static void
writeconndata(Req *r)
{
void *p;
@@ -292,33 +298,14 @@
/* copy in the ethernet packet */
memmove(b->wp, p, r->ifcall.count);
-
- /* fill source mac address if not bridged */
- if(!conn[NUM(r->fid->qid.path)].bridge)
- memmove(b->wp+6, macaddr, 6);
-
b->wp += r->ifcall.count;
- etheriq(b, 0);
+ etheroq(b, &conn[NUM(r->fid->qid.path)]);
r->ofcall.count = r->ifcall.count;
respond(r, nil);
}
-static char*
-mac2str(uchar *m)
-{
- int i;
- char *t = "0123456789abcdef";
- static char buf[13];
- buf[13] = 0;
- for(i=0; i<6; i++){
- buf[i*2] = t[m[i]>>4];
- buf[i*2+1] = t[m[i]&0xF];
- }
- return buf;
-}
-
static void
fsread(Req *r)
{
@@ -384,6 +371,17 @@
}
}
+static int
+activemulti(uchar *ea)
+{
+ int i;
+
+ for(i=0; i<nmulti; i++)
+ if(memcmp(ea, multiaddr[i], Eaddrlen) == 0)
+ return i;
+ return -1;
+}
+
static void
fswrite(Req *r)
{
@@ -399,6 +397,8 @@
p = (char*)r->ifcall.data;
if(n >= 6 && memcmp(p, "bridge", 6)==0){
conn[NUM(path)].bridge = 1;
+ } else if(n >= 11 && memcmp(p, "headersonly", 11)==0){
+ conn[NUM(path)].headersonly = 1;
} else if(n >= 11 && memcmp(p, "promiscuous", 11)==0){
if(conn[NUM(path)].prom == 0){
conn[NUM(path)].prom = 1;
@@ -406,7 +406,7 @@
(*eppromiscuous)(epctl, 1);
}
} else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){
- uchar ea[6];
+ uchar ea[Eaddrlen];
int i;
if(parseether(ea, p+9) < 0){
@@ -413,18 +413,16 @@
respond(r, "bad ether address");
return;
}
- for(i=0; i<nmulti; i++)
- if(memcmp(ea, multiaddr[i], 6) == 0)
- break;
- if(i < nmulti){
+ i = activemulti(ea);
+ if(i >= 0){
if(*p == 'r'){
- memmove(multiaddr[i], multiaddr[--nmulti], 6);
+ memmove(multiaddr[i], multiaddr[--nmulti], Eaddrlen);
if(epmulticast != nil)
(*epmulticast)(epctl, ea, 0);
}
} else if(nmulti < nelem(multiaddr)){
if(*p == 'a'){
- memmove(multiaddr[nmulti++], ea, 6);
+ memmove(multiaddr[nmulti++], ea, Eaddrlen);
if(epmulticast != nil)
(*epmulticast)(epctl, ea, 1);
}
@@ -508,6 +506,7 @@
c->type = 0;
c->prom = 0;
c->bridge = 0;
+ c->headersonly = 0;
}
if(d != nil){
d->next = c->dq;
@@ -580,6 +579,8 @@
(*eppromiscuous)(epctl, 0);
}
}
+ if(TYPE(fid->qid.path) == Qdata && c->bridge)
+ memset(mactab, 0, sizeof(mactab));
c->used--;
qunlock(c);
}
@@ -684,71 +685,159 @@
return 0;
}
-void
-etheriq(Block *b, int wire)
+static void
+cpass(Conn *c, Block *bp)
{
- int i, t, tome, fromme, multi;
- Block *q;
- Conn *c;
Dq *d;
- Ehdr *h;
- if(BLEN(b) < Ehdrsz){
- freeb(b);
- return;
- }
+ qlock(c);
+ for(d = c->dq; d != nil; d = d->next){
+ qlock(d);
+ if(d->size < 100000){
+ Block *q;
- h = (Ehdr*)b->rp;
- t = (h->type[0]<<8)|h->type[1];
-
- multi = h->d[0]&1;
- tome = memcmp(h->d, macaddr, sizeof(macaddr)) == 0;
- fromme = memcmp(h->s, macaddr, sizeof(macaddr)) == 0;
-
- for(i=0; i<nconn; i++){
- c = &conn[i];
- qlock(c);
- if(!c->used)
- goto next;
- if(c->bridge && (tome || !wire && !fromme))
- goto next;
- if(c->type > 0 && c->type != t)
- goto next;
- if(!c->prom && !multi && !tome)
- goto next;
- for(d=c->dq; d; d=d->next){
- if(d->size > 100000)
- continue;
- if(c->type == -2) {
- q = copyblock(b, 64);
- } else if(wire && b->ref == 1) {
- incref(b);
- q = b;
- } else {
- q = copyblock(b, BLEN(b));
- }
- qlock(d);
+ if(d->next == nil) {
+ q = bp;
+ bp = nil;
+ } else
+ q = copyblock(bp, BLEN(bp));
q->next = nil;
*d->qt = q;
d->qt = &q->next;
d->size += BLEN(q);
matchrq(d);
- qunlock(d);
}
-next:
- qunlock(c);
+ qunlock(d);
}
- if(wire) {
- freeb(b);
- stats.in++;
+ qunlock(c);
+
+ if(bp != nil)
+ freeb(bp);
+}
+
+static void
+etherrtrace(Conn *c, Etherpkt *pkt, int len)
+{
+ Block *bp;
+
+ bp = allocb(64);
+ memmove(bp->wp, pkt, len < 64 ? len : 64);
+ if(c->type != -2){
+ u32int ms = nsec()/1000000LL;
+ 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;
+ cpass(c, bp);
+}
+
+static Macent*
+macent(uchar *ea)
+{
+ u32int h = (ea[0] | ea[1]<<8 | ea[2]<<16 | ea[3]<<24) ^ (ea[4] | ea[5]<<8);
+ return &mactab[h % nelem(mactab)];
+}
+
+static Block*
+ethermux(Block *bp, Conn *from)
+{
+ Etherpkt *pkt;
+ Conn *c, *x;
+ int len, multi, tome, port, type, dispose;
+
+ len = BLEN(bp);
+ if(len < ETHERHDRSIZE)
+ goto Drop;
+ pkt = (Etherpkt*)bp->rp;
+ if(!(multi = pkt->d[0] & 1)){
+ tome = memcmp(pkt->d, macaddr, Eaddrlen) == 0;
+ if(!tome && from != nil && nprom == 0)
+ return bp;
} else {
- /* transmit frees buffer */
- (*eptransmit)(epout, b);
- stats.out++;
+ tome = 0;
+ if(from == nil && nprom == 0
+ && memcmp(pkt->d, bcast, Eaddrlen) != 0
+ && activemulti(pkt->d) < 0)
+ goto Drop;
}
+
+ port = -1;
+ if(nprom){
+ if((from == nil || from->bridge) && (pkt->s[0] & 1) == 0){
+ Macent *t = macent(pkt->s);
+ t->port = from == nil ? 0 : 1+(from - conn);
+ memmove(t->ea, pkt->s, Eaddrlen);
+ }
+ if(!tome && !multi){
+ Macent *t = macent(pkt->d);
+ if(memcmp(t->ea, pkt->d, Eaddrlen) == 0)
+ port = t->port;
+ }
+ }
+
+ x = nil;
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ dispose = tome || from == nil || port > 0;
+
+ for(c = conn; c < &conn[nconn]; c++){
+ if(!c->used)
+ continue;
+ if(c->type != type && c->type >= 0)
+ continue;
+ if(!tome && !multi && !c->prom)
+ continue;
+ if(c->bridge){
+ if(tome || c == from)
+ continue;
+ if(port >= 0 && port != 1+(c - conn))
+ continue;
+ }
+ if(c->headersonly || c->type == -2){
+ etherrtrace(c, pkt, len);
+ continue;
+ }
+ if(dispose && x == nil)
+ x = c;
+ else
+ cpass(c, copyblock(bp, len));
+ }
+ if(x != nil){
+ cpass(x, bp);
+ return nil;
+ }
+
+ if(dispose){
+Drop: freeb(bp);
+ return nil;
+ }
+ return bp;
}
+void
+etheriq(Block *bp)
+{
+ stats.in++;
+ ethermux(bp, nil);
+}
+
static void
+etheroq(Block *bp, Conn *from)
+{
+ if(!from->bridge)
+ memmove(((Etherpkt*)bp->rp)->s, macaddr, Eaddrlen);
+ bp = ethermux(bp, from);
+ if(bp == nil)
+ return;
+ stats.out++;
+ /* transmit frees buffer */
+ (*eptransmit)(epout, bp);
+}
+
+static void
usbreadproc(void *)
{
char err[ERRMAX];
@@ -776,7 +865,7 @@
Srv fs =
{
-.attach= fsattach,
+.attach= fsattach,
.destroyfid= fsdestroyfid,
.walk1= fswalk1,
.open= fsopen,
@@ -900,15 +989,7 @@
b->rp = b->base;
b->wp = b->base;
b->next = nil;
- b->ref = 1;
return b;
-}
-
-void
-freeb(Block *b)
-{
- if(decref(b) == 0)
- free(b);
}
Block*
--- a/sys/src/cmd/nusb/ether/rndis.c
+++ b/sys/src/cmd/nusb/ether/rndis.c
@@ -75,13 +75,13 @@
else{
doff = GET4(b->rp+8);
dlen = GET4(b->rp+12);
- if((len = GET4(b->rp+4)) != n || 8+doff+dlen > len || dlen < Ehdrsz)
+ if((len = GET4(b->rp+4)) != n || 8+doff+dlen > len || dlen < ETHERHDRSIZE)
werrstr("bad packet: doff %d, dlen %d, len %d", doff, dlen, len);
else{
b->rp += 8 + doff;
b->wp = b->rp + dlen;
- etheriq(b, 1);
+ etheriq(b);
return 0;
}
}
@@ -150,10 +150,10 @@
else {
sz = GET4(res+16);
off = GET4(res+20);
- if(8+off+sz > r || sz != 6)
+ if(8+off+sz > r || sz != Eaddrlen)
werrstr("invalid mac: off %d, sz %d, len %d", off, sz, r);
else{
- memcpy(macaddr, res+8+off, 6);
+ memcpy(macaddr, res+8+off, Eaddrlen);
/* set the filter */
if(rndisout(d, 0, mfilter, sizeof(mfilter)) < 0)
werrstr("send filter: %r");
--- a/sys/src/cmd/nusb/ether/smsc.c
+++ b/sys/src/cmd/nusb/ether/smsc.c
@@ -228,10 +228,10 @@
break;
if((hd & Rxerror) == 0){
if(n == BLEN(b)){
- etheriq(b, 1);
+ etheriq(b);
return 0;
}
- etheriq(copyblock(b, n), 1);
+ etheriq(copyblock(b, n));
}
b->rp += (n + 3) & ~3;
}
@@ -284,7 +284,7 @@
if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst))
return -1;
if(!setmac)
- if(eepromr(d, MACoffset, macaddr, 6) < 0)
+ if(eepromr(d, MACoffset, macaddr, Eaddrlen) < 0)
return -1;
wr(d, Addrl, GET4(macaddr));
wr(d, Addrh, GET2(macaddr+4));
--- a/sys/src/cmd/nusb/ether/url.c
+++ b/sys/src/cmd/nusb/ether/url.c
@@ -282,7 +282,7 @@
if((hd & Vpm) == 0)
freeb(b);
else
- etheriq(b, 1);
+ etheriq(b);
return 0;
}