diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-09-16 23:21:54 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-09-16 23:21:54 +0200 |
commit | c937aac59bf77b56e665564092e680159a118115 (patch) | |
tree | 21327ba111408a7edbc1fe5429baf655cbd5878a /sys/src/cmd | |
parent | 7bcbef11eb17d0b5f756acd74762d1a285aa134f (diff) |
nusb/ether: experimental pomisc mode and multicast support for smsc and asix
Diffstat (limited to 'sys/src/cmd')
-rw-r--r-- | sys/src/cmd/nusb/ether/asix.c | 21 | ||||
-rw-r--r-- | sys/src/cmd/nusb/ether/dat.h | 6 | ||||
-rw-r--r-- | sys/src/cmd/nusb/ether/ether.c | 64 | ||||
-rw-r--r-- | sys/src/cmd/nusb/ether/smsc.c | 29 |
4 files changed, 105 insertions, 15 deletions
diff --git a/sys/src/cmd/nusb/ether/asix.c b/sys/src/cmd/nusb/ether/asix.c index 7ef5df64d..560ef12e6 100644 --- a/sys/src/cmd/nusb/ether/asix.c +++ b/sys/src/cmd/nusb/ether/asix.c @@ -262,13 +262,26 @@ asixpromiscuous(Dev *d, int on) int rxctl; rxctl = getrxctl(d); - if(on != 0) + if(on) rxctl |= Rxctlprom; else rxctl &= ~Rxctlprom; return asixset(d, Cwrxctl, rxctl); } +static int +asixmulticast(Dev *d, uchar*, int) +{ + int rxctl; + + rxctl = getrxctl(d); + if(nmulti != 0) + rxctl |= Rxctlamall; + else + rxctl &= ~Rxctlamall; + return asixset(d, Cwrxctl, rxctl); +} + int a88178init(Dev *d) { @@ -316,6 +329,9 @@ a88178init(Dev *d) epreceive = asixreceive; eptransmit = asixtransmit; + eppromiscuous = asixpromiscuous; + epmulticast = asixmulticast; + return 0; } @@ -373,5 +389,8 @@ a88772init(Dev *d) epreceive = asixreceive; eptransmit = asixtransmit; + eppromiscuous = asixpromiscuous; + epmulticast = asixmulticast; + return 0; } diff --git a/sys/src/cmd/nusb/ether/dat.h b/sys/src/cmd/nusb/ether/dat.h index 180e4596e..c2d1dd972 100644 --- a/sys/src/cmd/nusb/ether/dat.h +++ b/sys/src/cmd/nusb/ether/dat.h @@ -44,7 +44,13 @@ int setmac; /* to be filled in by *init() */ uchar macaddr[6]; +int nprom; +int nmulti; +uchar multiaddr[32][6]; + void etheriq(Block*, int wire); int (*epreceive)(Dev*); void (*eptransmit)(Dev*, Block*); +int (*eppromiscuous)(Dev*, int); +int (*epmulticast)(Dev*, uchar*, int); diff --git a/sys/src/cmd/nusb/ether/ether.c b/sys/src/cmd/nusb/ether/ether.c index abdb0f897..c9e95d550 100644 --- a/sys/src/cmd/nusb/ether/ether.c +++ b/sys/src/cmd/nusb/ether/ether.c @@ -82,6 +82,10 @@ Stats stats; Conn conn[32]; int nconn = 0; +int nprom = 0; +int nmulti = 0; + +Dev *epctl; Dev *epin; Dev *epout; @@ -401,9 +405,37 @@ fswrite(Req *r) case Qctl: n = r->ifcall.count; p = (char*)r->ifcall.data; - if((n == 11) && memcmp(p, "promiscuous", 11)==0) - conn[NUM(path)].prom = 1; - if((n > 8) && memcmp(p, "connect ", 8)==0){ + if(n == 11 && memcmp(p, "promiscuous", 11)==0){ + if(conn[NUM(path)].prom == 0){ + conn[NUM(path)].prom = 1; + if(nprom++ == 0 && eppromiscuous != nil) + (*eppromiscuous)(epctl, 1); + } + } else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){ + uchar ea[6]; + int i; + + if(parseether(ea, p+9) < 0){ + respond(r, "bad ether address"); + return; + } + for(i=0; i<nmulti; i++) + if(memcmp(ea, multiaddr[i], 6) == 0) + break; + if(i < nmulti){ + if(*p == 'r'){ + memmove(multiaddr[i], multiaddr[--nmulti], 6); + if(epmulticast != nil) + (*epmulticast)(epctl, ea, 0); + } + } else if(nmulti < nelem(multiaddr)){ + if(*p == 'a'){ + memmove(multiaddr[nmulti++], ea, 6); + if(epmulticast != nil) + (*epmulticast)(epctl, ea, 1); + } + } + } else if(n > 8 && memcmp(p, "connect ", 8)==0){ char x[12]; if(n - 8 >= sizeof(x)){ @@ -546,8 +578,13 @@ fsdestroyfid(Fid *fid) } free(d); } - if(TYPE(fid->qid.path) == Qctl) - c->prom = 0; + if(TYPE(fid->qid.path) == Qctl){ + if(c->prom){ + c->prom = 0; + if(--nprom == 0 && eppromiscuous != nil) + (*eppromiscuous)(epctl, 0); + } + } c->used--; qunlock(c); } @@ -783,7 +820,6 @@ threadmain(int argc, char **argv) { char s[64], *t; int et, ei, eo; - Dev *d; fmtinstall('E', eipfmt); @@ -819,25 +855,25 @@ threadmain(int argc, char **argv) if(argc != 1) usage(); - if((d = getdev(*argv)) == nil) + if((epctl = getdev(*argv)) == nil) sysfatal("getdev: %r"); - if(findendpoints(d, &ei, &eo) < 0) + if(findendpoints(epctl, &ei, &eo) < 0) sysfatal("no endpoints found"); werrstr(""); - if((*ethertype[et].init)(d) < 0) + if((*ethertype[et].init)(epctl) < 0) sysfatal("%s init failed: %r", ethertype[et].name); if(epreceive == nil || eptransmit == nil) sysfatal("bug in init"); - if((epin = openep(d, ei)) == nil) + if((epin = openep(epctl, ei)) == nil) sysfatal("openep: %r"); if(ei == eo){ incref(epin); epout = epin; opendevdata(epin, ORDWR); } else { - if((epout = openep(d, eo)) == nil) + if((epout = openep(epctl, eo)) == nil) sysfatal("openep: %r"); opendevdata(epin, OREAD); opendevdata(epout, OWRITE); @@ -847,9 +883,9 @@ threadmain(int argc, char **argv) atnotify(inote, 1); time0 = time(0); - tab[Qiface].name = smprint("etherU%s", d->hname); - snprint(s, sizeof(s), "%d.ether", d->id); - closedev(d); + tab[Qiface].name = smprint("etherU%s", epctl->hname); + snprint(s, sizeof(s), "%d.ether", epctl->id); + threadpostsharesrv(&fs, nil, "usbnet", s); threadexits(0); diff --git a/sys/src/cmd/nusb/ether/smsc.c b/sys/src/cmd/nusb/ether/smsc.c index deb8aef43..c0d6710ee 100644 --- a/sys/src/cmd/nusb/ether/smsc.c +++ b/sys/src/cmd/nusb/ether/smsc.c @@ -252,6 +252,32 @@ smsctransmit(Dev *ep, Block *b) freeb(b); } +static int +smscpromiscuous(Dev *d, int on) +{ + int rxctl; + + rxctl = rr(d, Maccr); + if(on) + rxctl |= Prms; + else + rxctl &= ~Prms; + return wr(d, Maccr, rxctl); +} + +static int +smscmulticast(Dev *d, uchar *, int) +{ + int rxctl; + + rxctl = rr(d, Maccr); + if(nmulti != 0) + rxctl |= Mcpas; + else + rxctl &= ~Mcpas; + return wr(d, Maccr, rxctl); +} + int smscinit(Dev *d) { @@ -289,5 +315,8 @@ smscinit(Dev *d) eptransmit = smsctransmit; epreceive = smscreceive; + eppromiscuous = smscpromiscuous; + epmulticast = smscmulticast; + return 0; } |