ref: c937aac59bf77b56e665564092e680159a118115
parent: 7bcbef11eb17d0b5f756acd74762d1a285aa134f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Sep 16 19:21:54 EDT 2016
nusb/ether: experimental pomisc mode and multicast support for smsc and asix
--- a/sys/src/cmd/nusb/ether/asix.c
+++ b/sys/src/cmd/nusb/ether/asix.c
@@ -262,7 +262,7 @@
int rxctl;
rxctl = getrxctl(d);
- if(on != 0)
+ if(on)
rxctl |= Rxctlprom;
else
rxctl &= ~Rxctlprom;
@@ -269,6 +269,19 @@
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 @@
epreceive = asixreceive;
eptransmit = asixtransmit;
+ eppromiscuous = asixpromiscuous;
+ epmulticast = asixmulticast;
+
return 0;
}
@@ -373,5 +389,8 @@
epreceive = asixreceive;
eptransmit = asixtransmit;
+ eppromiscuous = asixpromiscuous;
+ epmulticast = asixmulticast;
+
return 0;
}
--- a/sys/src/cmd/nusb/ether/dat.h
+++ b/sys/src/cmd/nusb/ether/dat.h
@@ -44,7 +44,13 @@
/* 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);
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -82,6 +82,10 @@
Conn conn[32];
int nconn = 0;
+int nprom = 0;
+int nmulti = 0;
+
+Dev *epctl;
Dev *epin;
Dev *epout;
@@ -401,9 +405,37 @@
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 @@
}
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 @@
{
char s[64], *t;
int et, ei, eo;
- Dev *d;
fmtinstall('E', eipfmt);
@@ -819,18 +855,18 @@
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);
@@ -837,7 +873,7 @@
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 @@
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);
--- a/sys/src/cmd/nusb/ether/smsc.c
+++ b/sys/src/cmd/nusb/ether/smsc.c
@@ -252,6 +252,32 @@
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 @@
eptransmit = smsctransmit;
epreceive = smscreceive;
+ eppromiscuous = smscpromiscuous;
+ epmulticast = smscmulticast;
+
return 0;
}