nusb/ether: experimental pomisc mode and multicast support for smsc and asix

This commit is contained in:
cinap_lenrek 2016-09-16 23:21:54 +02:00
parent 7bcbef11eb
commit c937aac59b
4 changed files with 105 additions and 15 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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;
}