nusb/ether: mux bridges, bring in line with devether

This commit is contained in:
cinap_lenrek 2018-02-18 19:56:58 +01:00
parent 729c9c39d9
commit 986278e04d
8 changed files with 207 additions and 117 deletions

View file

@ -227,10 +227,10 @@ asixreceive(Dev *ep)
if((n != hd) || (n > BLEN(b))) if((n != hd) || (n > BLEN(b)))
break; break;
if(n == BLEN(b)){ if(n == BLEN(b)){
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }
etheriq(copyblock(b, n), 1); etheriq(copyblock(b, n));
b->rp += n; b->rp += n;
} }
freeb(b); freeb(b);
@ -309,7 +309,7 @@ a88178init(Dev *d)
asixset(d, Creset, Rippd|Rprl); asixset(d, Creset, Rippd|Rprl);
sleep(150); sleep(150);
asixset(d, Cwrxctl, 0); asixset(d, Cwrxctl, 0);
if(asixget(d, Crmac, macaddr, 6) < 0) if(asixget(d, Crmac, macaddr, Eaddrlen) < 0)
return -1; return -1;
asixphy = getphy(d); asixphy = getphy(d);
if(ee17 < 0 || (ee17 & 0x7) == 0){ if(ee17 < 0 || (ee17 & 0x7) == 0){
@ -364,7 +364,7 @@ a88772init(Dev *d)
getrxctl(d); getrxctl(d);
if(asixset(d, Cwrxctl, 0) < 0) if(asixset(d, Cwrxctl, 0) < 0)
return -1; return -1;
if(asixget(d, Crmac, macaddr, 6) < 0) if(asixget(d, Crmac, macaddr, Eaddrlen) < 0)
return -1; return -1;
if(asixset(d, Creset, Rprl) < 0) if(asixset(d, Creset, Rprl) < 0)
return -1; return -1;

View file

@ -186,7 +186,7 @@ auereceive(Dev *ep)
return 0; return 0;
} }
b->wp = b->rp + n; b->wp = b->rp + n;
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }

View file

@ -23,7 +23,7 @@ cdcreceive(Dev *ep)
return -1; return -1;
} }
b->wp += n; b->wp += n;
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }

View file

@ -1,8 +1,6 @@
typedef struct Block Block; typedef struct Block Block;
struct Block struct Block
{ {
Ref;
Block *next; Block *next;
uchar *rp; uchar *rp;
@ -15,20 +13,29 @@ struct Block
#define BLEN(s) ((s)->wp - (s)->rp) #define BLEN(s) ((s)->wp - (s)->rp)
Block* allocb(int size); Block* allocb(int size);
void freeb(Block*);
Block* copyblock(Block*, int); Block* copyblock(Block*, int);
#define freeb(b) free(b)
typedef struct Ehdr Ehdr;
struct Ehdr
{
uchar d[6];
uchar s[6];
uchar type[2];
};
enum { enum {
Ehdrsz = 6+6+2, Eaddrlen= 6,
Maxpkt = 2000, ETHERHDRSIZE= 14, /* size of an ethernet header */
Maxpkt= 2000,
};
typedef struct Macent Macent;
struct Macent
{
uchar ea[Eaddrlen];
ushort port;
};
typedef struct Etherpkt Etherpkt;
struct Etherpkt
{
uchar d[Eaddrlen];
uchar s[Eaddrlen];
uchar type[2];
uchar data[1500];
}; };
enum enum
@ -41,14 +48,16 @@ enum
int debug; int debug;
int setmac; int setmac;
/* to be filled in by *init() */
uchar macaddr[6];
int nprom; int nprom;
int nmulti; 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*); int (*epreceive)(Dev*);
void (*eptransmit)(Dev*, Block*); void (*eptransmit)(Dev*, Block*);

View file

@ -68,6 +68,7 @@ struct Conn
int type; int type;
int prom; int prom;
int bridge; int bridge;
int headersonly;
Dq *dq; Dq *dq;
}; };
@ -78,6 +79,8 @@ struct Stats
int out; int out;
}; };
uchar bcast[Eaddrlen] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
Stats stats; Stats stats;
Conn conn[32]; Conn conn[32];
int nconn = 0; int nconn = 0;
@ -267,6 +270,9 @@ readconndata(Req *r)
qunlock(d); qunlock(d);
} }
static void
etheroq(Block*, Conn*);
static void static void
writeconndata(Req *r) writeconndata(Req *r)
{ {
@ -292,33 +298,14 @@ writeconndata(Req *r)
/* copy in the ethernet packet */ /* copy in the ethernet packet */
memmove(b->wp, p, r->ifcall.count); 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; b->wp += r->ifcall.count;
etheriq(b, 0); etheroq(b, &conn[NUM(r->fid->qid.path)]);
r->ofcall.count = r->ifcall.count; r->ofcall.count = r->ifcall.count;
respond(r, nil); 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 static void
fsread(Req *r) fsread(Req *r)
{ {
@ -384,6 +371,17 @@ fsread(Req *r)
} }
} }
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 static void
fswrite(Req *r) fswrite(Req *r)
{ {
@ -399,6 +397,8 @@ fswrite(Req *r)
p = (char*)r->ifcall.data; p = (char*)r->ifcall.data;
if(n >= 6 && memcmp(p, "bridge", 6)==0){ if(n >= 6 && memcmp(p, "bridge", 6)==0){
conn[NUM(path)].bridge = 1; 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){ } else if(n >= 11 && memcmp(p, "promiscuous", 11)==0){
if(conn[NUM(path)].prom == 0){ if(conn[NUM(path)].prom == 0){
conn[NUM(path)].prom = 1; conn[NUM(path)].prom = 1;
@ -406,25 +406,23 @@ fswrite(Req *r)
(*eppromiscuous)(epctl, 1); (*eppromiscuous)(epctl, 1);
} }
} else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){ } else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){
uchar ea[6]; uchar ea[Eaddrlen];
int i; int i;
if(parseether(ea, p+9) < 0){ if(parseether(ea, p+9) < 0){
respond(r, "bad ether address"); respond(r, "bad ether address");
return; return;
} }
for(i=0; i<nmulti; i++) i = activemulti(ea);
if(memcmp(ea, multiaddr[i], 6) == 0) if(i >= 0){
break;
if(i < nmulti){
if(*p == 'r'){ if(*p == 'r'){
memmove(multiaddr[i], multiaddr[--nmulti], 6); memmove(multiaddr[i], multiaddr[--nmulti], Eaddrlen);
if(epmulticast != nil) if(epmulticast != nil)
(*epmulticast)(epctl, ea, 0); (*epmulticast)(epctl, ea, 0);
} }
} else if(nmulti < nelem(multiaddr)){ } else if(nmulti < nelem(multiaddr)){
if(*p == 'a'){ if(*p == 'a'){
memmove(multiaddr[nmulti++], ea, 6); memmove(multiaddr[nmulti++], ea, Eaddrlen);
if(epmulticast != nil) if(epmulticast != nil)
(*epmulticast)(epctl, ea, 1); (*epmulticast)(epctl, ea, 1);
} }
@ -508,6 +506,7 @@ fsopen(Req *r)
c->type = 0; c->type = 0;
c->prom = 0; c->prom = 0;
c->bridge = 0; c->bridge = 0;
c->headersonly = 0;
} }
if(d != nil){ if(d != nil){
d->next = c->dq; d->next = c->dq;
@ -580,6 +579,8 @@ fsdestroyfid(Fid *fid)
(*eppromiscuous)(epctl, 0); (*eppromiscuous)(epctl, 0);
} }
} }
if(TYPE(fid->qid.path) == Qdata && c->bridge)
memset(mactab, 0, sizeof(mactab));
c->used--; c->used--;
qunlock(c); qunlock(c);
} }
@ -684,68 +685,156 @@ inote(void *, char *msg)
return 0; return 0;
} }
void static void
etheriq(Block *b, int wire) cpass(Conn *c, Block *bp)
{ {
int i, t, tome, fromme, multi;
Block *q;
Conn *c;
Dq *d; Dq *d;
Ehdr *h;
if(BLEN(b) < Ehdrsz){ qlock(c);
freeb(b); for(d = c->dq; d != nil; d = d->next){
return; qlock(d);
} if(d->size < 100000){
Block *q;
h = (Ehdr*)b->rp; if(d->next == nil) {
t = (h->type[0]<<8)|h->type[1]; q = bp;
bp = nil;
multi = h->d[0]&1; } else
tome = memcmp(h->d, macaddr, sizeof(macaddr)) == 0; q = copyblock(bp, BLEN(bp));
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);
q->next = nil; q->next = nil;
*d->qt = q; *d->qt = q;
d->qt = &q->next; d->qt = &q->next;
d->size += BLEN(q); d->size += BLEN(q);
matchrq(d); matchrq(d);
qunlock(d);
} }
next: qunlock(d);
qunlock(c);
} }
if(wire) { qunlock(c);
freeb(b);
stats.in++; 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 { } else {
/* transmit frees buffer */ tome = 0;
(*eptransmit)(epout, b); if(from == nil && nprom == 0
stats.out++; && 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 static void
@ -776,7 +865,7 @@ usbreadproc(void *)
Srv fs = Srv fs =
{ {
.attach= fsattach, .attach= fsattach,
.destroyfid= fsdestroyfid, .destroyfid= fsdestroyfid,
.walk1= fswalk1, .walk1= fswalk1,
.open= fsopen, .open= fsopen,
@ -900,17 +989,9 @@ allocb(int size)
b->rp = b->base; b->rp = b->base;
b->wp = b->base; b->wp = b->base;
b->next = nil; b->next = nil;
b->ref = 1;
return b; return b;
} }
void
freeb(Block *b)
{
if(decref(b) == 0)
free(b);
}
Block* Block*
copyblock(Block *b, int count) copyblock(Block *b, int count)
{ {

View file

@ -75,13 +75,13 @@ rndisreceive(Dev *ep)
else{ else{
doff = GET4(b->rp+8); doff = GET4(b->rp+8);
dlen = GET4(b->rp+12); 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); werrstr("bad packet: doff %d, dlen %d, len %d", doff, dlen, len);
else{ else{
b->rp += 8 + doff; b->rp += 8 + doff;
b->wp = b->rp + dlen; b->wp = b->rp + dlen;
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }
} }
@ -150,10 +150,10 @@ rndisinit(Dev *d)
else { else {
sz = GET4(res+16); sz = GET4(res+16);
off = GET4(res+20); 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); werrstr("invalid mac: off %d, sz %d, len %d", off, sz, r);
else{ else{
memcpy(macaddr, res+8+off, 6); memcpy(macaddr, res+8+off, Eaddrlen);
/* set the filter */ /* set the filter */
if(rndisout(d, 0, mfilter, sizeof(mfilter)) < 0) if(rndisout(d, 0, mfilter, sizeof(mfilter)) < 0)
werrstr("send filter: %r"); werrstr("send filter: %r");

View file

@ -228,10 +228,10 @@ smscreceive(Dev *ep)
break; break;
if((hd & Rxerror) == 0){ if((hd & Rxerror) == 0){
if(n == BLEN(b)){ if(n == BLEN(b)){
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }
etheriq(copyblock(b, n), 1); etheriq(copyblock(b, n));
} }
b->rp += (n + 3) & ~3; b->rp += (n + 3) & ~3;
} }
@ -284,7 +284,7 @@ smscinit(Dev *d)
if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst)) if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst))
return -1; return -1;
if(!setmac) if(!setmac)
if(eepromr(d, MACoffset, macaddr, 6) < 0) if(eepromr(d, MACoffset, macaddr, Eaddrlen) < 0)
return -1; return -1;
wr(d, Addrl, GET4(macaddr)); wr(d, Addrl, GET4(macaddr));
wr(d, Addrh, GET2(macaddr+4)); wr(d, Addrh, GET2(macaddr+4));

View file

@ -282,7 +282,7 @@ urlreceive(Dev *ep)
if((hd & Vpm) == 0) if((hd & Vpm) == 0)
freeb(b); freeb(b);
else else
etheriq(b, 1); etheriq(b);
return 0; return 0;
} }