M boot/boot.c => boot/boot.c +0 -1
@@ 40,7 40,6 @@ boot(int argc, char *argv[])
Method *mp;
char *cmd, cmdbuf[64], *iargv[16];
char rootbuf[64];
- char flags[6];
int islocal, ishybrid, iargc;
char *rp;
M ip/devip.c => ip/devip.c +18 -20
@@ 754,29 754,27 @@ setladdrport(Conv* c, char* str, int announcing)
}
c->lport = 0;
- if(announcing){
- if(p == nil){
+ if(p == nil){
+ if(announcing)
ipmove(c->laddr, IPnoaddr);
- lport = atoi(str);
- } else {
- if(strcmp(str, "*") == 0)
- ipmove(c->laddr, IPnoaddr);
- else
- parseip(c->laddr, str);
- lport = atoi(p);
- }
- } else {
- if(p == nil){
+ else
setladdr(c);
- lport = atoi(str);
- } else {
- if(strcmp(str, "*") == 0)
- setladdr(c);
- else
- parseip(c->laddr, str);
- lport = atoi(p);
- }
+ p = str;
+ } else {
+ if(strcmp(str, "*") == 0)
+ ipmove(c->laddr, IPnoaddr);
+ else
+ parseip(c->laddr, str);
}
+
+ /* one process can get all connections */
+ if(announcing && strcmp(p, "*") == 0){
+ if(!iseve())
+ error(Eperm);
+ return setluniqueport(c, 0);
+ }
+
+ lport = atoi(p);
if(lport <= 0)
setlport(c);
else
M ip/il.c => ip/il.c +67 -91
@@ 183,17 183,19 @@ static char *statnames[] =
typedef struct Ilpriv Ilpriv;
struct Ilpriv
{
+ Ipht ht;
+
ulong stats[Nstats];
- ulong csumerr; /* checksum errors */
- ulong hlenerr; /* header length error */
- ulong lenerr; /* short packet */
- ulong order; /* out of order */
- ulong rexmit; /* retransmissions */
- ulong dup;
- ulong dupb;
+ ulong csumerr; /* checksum errors */
+ ulong hlenerr; /* header length error */
+ ulong lenerr; /* short packet */
+ ulong order; /* out of order */
+ ulong rexmit; /* retransmissions */
+ ulong dup;
+ ulong dupb;
- Rendez ilr;
+ Rendez ilr;
/* keeping track of the ack kproc */
int ackprocstarted;
@@ 222,7 224,7 @@ int ilnextqt(Ilcb*);
void ilcbinit(Ilcb*);
int later(ulong, ulong, char*);
void ilreject(Fs*, Ilhdr*);
-
+void illocalclose(Conv *c);
int ilcksum = 1;
static int initseq = 25001;
static ulong scalediv, scalemul;
@@ 280,6 282,20 @@ ilannounce(Conv *c, char **argv, int argc)
return nil;
}
+void
+illocalclose(Conv *c)
+{
+ Ilcb *ic;
+ Ilpriv *ipriv;
+
+ ipriv = c->p->priv;
+ ic = (Ilcb*)c->ptcl;
+ ic->state = Ilclosed;
+ iphtrem(&ipriv->ht, c);
+ ipmove(c->laddr, IPnoaddr);
+ c->lport = 0;
+}
+
static void
ilclose(Conv *c)
{
@@ 303,9 319,7 @@ ilclose(Conv *c)
ilsendctl(c, nil, Ilclose, ic->next, ic->recvd, 0);
break;
case Illistening:
- ic->state = Ilclosed;
- ipmove(c->laddr, IPnoaddr);
- c->lport = 0;
+ illocalclose(c);
break;
}
ilfreeq(ic);
@@ 516,7 530,7 @@ iliput(Proto *il, uchar*, Block *bp)
uchar laddr[IPaddrlen];
ushort sp, dp, csum;
int plen, illen;
- Conv *s, **p, *new, *spec, *gen;
+ Conv *s;
Ilpriv *ipriv;
ipriv = il->priv;
@@ 539,6 553,7 @@ iliput(Proto *il, uchar*, Block *bp)
sp = nhgets(ih->ildst);
dp = nhgets(ih->ilsrc);
v4tov6(raddr, ih->src);
+ v4tov6(laddr, ih->dst);
if((csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) {
if(ih->iltype < 0 || ih->iltype > Ilclose)
@@ 552,96 567,55 @@ iliput(Proto *il, uchar*, Block *bp)
}
qlock(il);
-
- for(p = il->conv; *p; p++) {
- s = *p;
- if(s->lport == sp)
- if(s->rport == dp)
- if(ipcmp(s->raddr, raddr) == 0) {
- qlock(s);
- qunlock(il);
- if(waserror()){
- qunlock(s);
- nexterror();
- }
- ilprocess(s, ih, bp);
- qunlock(s);
- poperror();
- return;
- }
- }
-
- if(ih->iltype != Ilsync){
+ s = iphtlook(&ipriv->ht, raddr, dp, laddr, sp);
+ if(s == nil){
qunlock(il);
- if(ih->iltype < 0 || ih->iltype > Ilclose)
- st = "?";
- else
- st = iltype[ih->iltype];
- ilreject(il->f, ih); /* no channel and not sync */
- netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
- st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
goto raise;
}
- gen = nil;
- spec = nil;
- for(p = il->conv; *p; p++) {
- s = *p;
- ic = (Ilcb*)s->ptcl;
- if(ic->state != Illistening)
- continue;
-
- if(s->rport == 0 && ipcmp(s->raddr, IPnoaddr) == 0) {
- if(s->lport == sp) {
- spec = s;
- break;
- }
- if(s->lport == 0)
- gen = s;
+ ic = (Ilcb*)s->ptcl;
+ if(ic->state == Illistening){
+ if(ih->iltype != Ilsync){
+ qunlock(il);
+ if(ih->iltype < 0 || ih->iltype > Ilclose)
+ st = "?";
+ else
+ st = iltype[ih->iltype];
+ ilreject(il->f, ih); /* no channel and not sync */
+ netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
+ st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
+ goto raise;
}
- }
-
- if(spec)
- s = spec;
- else
- if(gen)
- s = gen;
- else {
- qunlock(il);
- ilreject(il->f, ih); /* no listener */
- goto raise;
- }
- v4tov6(laddr, ih->dst);
- new = Fsnewcall(s, raddr, dp, laddr, sp);
- if(new == nil){
- qunlock(il);
- netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
- ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
- goto raise;
+ s = Fsnewcall(s, raddr, dp, laddr, sp);
+ if(s == nil){
+ qunlock(il);
+ netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
+ ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
+ goto raise;
+ }
+
+ ic = (Ilcb*)s->ptcl;
+
+ ic->conv = s;
+ ic->state = Ilsyncee;
+ ilcbinit(ic);
+ ic->rstart = nhgetl(ih->ilid);
+ iphtadd(&ipriv->ht, s);
}
- ic = (Ilcb*)new->ptcl;
-
- ic->conv = new;
- ic->state = Ilsyncee;
- ilcbinit(ic);
- ic->rstart = nhgetl(ih->ilid);
-
- qlock(new);
+ qlock(s);
qunlock(il);
if(waserror()){
- qunlock(new);
+ qunlock(s);
nexterror();
}
- ilprocess(new, ih, bp);
- qunlock(new);
+ ilprocess(s, ih, bp);
+ qunlock(s);
poperror();
return;
-
raise:
freeblist(bp);
- return;
}
void
@@ 695,9 669,9 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp)
default:
break;
case Ilsync:
- if(id != ic->rstart || ack != 0)
- ic->state = Ilclosed;
- else {
+ if(id != ic->rstart || ack != 0){
+ illocalclose(s);
+ } else {
ic->recvd = id;
ilsendctl(s, nil, Ilsync, ic->start, ic->recvd, 0);
}
@@ 867,7 841,7 @@ ilhangup(Conv *s, char *msg)
ic = (Ilcb*)s->ptcl;
callout = ic->state == Ilsyncer;
- ic->state = Ilclosed;
+ illocalclose(s);
qhangup(s->rq, msg);
qhangup(s->wq, msg);
@@ 1264,9 1238,11 @@ ilstart(Conv *c, int type, int fasttimeout)
break;
case IL_LISTEN:
ic->state = Illistening;
+ iphtadd(&ipriv->ht, c);
break;
case IL_CONNECT:
ic->state = Ilsyncer;
+ iphtadd(&ipriv->ht, c);
ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0);
break;
}
M ip/ip.h => ip/ip.h +30 -0
@@ 11,6 11,8 @@ typedef struct Ipmulti Ipmulti;
typedef struct Ipmux Ipmux;
typedef struct IProuter IProuter;
typedef struct Ipifc Ipifc;
+typedef struct Iphash Iphash;
+typedef struct Ipht Ipht;
typedef struct Netlog Netlog;
typedef struct Ifclog Ifclog;
typedef struct Medium Medium;
@@ 196,6 198,34 @@ struct Ipmulti
};
/*
+ * hash table for 2 ip addresses + 2 ports
+ */
+enum
+{
+ Nipht= 521, /* convenient prime */
+
+ IPmatchexact= 0, /* match on 4 tuple */
+ IPmatchany, /* *!* */
+ IPmatchport, /* *!port */
+ IPmatchaddr, /* addr!* */
+ IPmatchpa, /* addr!port */
+};
+struct Iphash
+{
+ Iphash *next;
+ Conv *c;
+ int match;
+};
+struct Ipht
+{
+ Lock;
+ Iphash *tab[Nipht];
+};
+void iphtadd(Ipht*, Conv*);
+void iphtrem(Ipht*, Conv*);
+Conv* iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp);
+
+/*
* one per multiplexed protocol
*/
struct Proto
M ip/ipaux.c => ip/ipaux.c +148 -6
@@ 249,15 249,23 @@ isv4(uchar *ip)
return memcmp(ip, v4prefix, IPv4off) == 0;
}
+/*
+ * since we call v4tov6 so often (per packet in), avoiding the memmove's is
+ * useful. However, we need to check allignment for processors
+ * without unalligned moves.
+ */
void
v4tov6(uchar *v6, uchar *v4)
{
-// memmove(v6, v4prefix, IPv4off);
-// memmove(v6 + IPv4off, v4, IPv4addrlen);
- *(ulong*)v6 = *(ulong*)v4prefix;
- *(ulong*)(v6+4) = *(ulong*)(v4prefix+4);
- *(ulong*)(v6+8) = *(ulong*)(v4prefix+8);
- *(ulong*)(v6+12) = *(ulong*)v4;
+ if((((ulong)v6) & 0x3) != 0 || (((ulong)v4) & 0x3) != 0){
+ memmove(v6, v4prefix, IPv4off);
+ memmove(v6 + IPv4off, v4, IPv4addrlen);
+ } else {
+ *(ulong*)v6 = *(ulong*)v4prefix;
+ *(ulong*)(v6+4) = *(ulong*)(v4prefix+4);
+ *(ulong*)(v6+8) = *(ulong*)(v4prefix+8);
+ *(ulong*)(v6+12) = *(ulong*)v4;
+ }
}
int
@@ 392,3 400,137 @@ parsemac(uchar *to, char *from, int len)
}
return i;
}
+
+/*
+ * hashing tcp, udp, ... connections
+ */
+ulong
+iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
+{
+ return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
+}
+
+void
+iphtadd(Ipht *ht, Conv *c)
+{
+ ulong hv;
+ Iphash *h;
+
+ hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
+ h = smalloc(sizeof(*h));
+ if(ipcmp(c->raddr, IPnoaddr) != 0)
+ h->match = IPmatchexact;
+ else {
+ if(ipcmp(c->laddr, IPnoaddr) != 0){
+ if(c->lport == 0)
+ h->match = IPmatchaddr;
+ else
+ h->match = IPmatchpa;
+ } else {
+ if(c->lport == 0)
+ h->match = IPmatchany;
+ else
+ h->match = IPmatchport;
+ }
+ }
+ h->c = c;
+ lock(ht);
+ h->next = ht->tab[hv];
+ ht->tab[hv] = h;
+ unlock(ht);
+}
+
+void
+iphtrem(Ipht *ht, Conv *c)
+{
+ ulong hv;
+ Iphash **l, *h;
+
+ hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
+ lock(ht);
+ for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next)
+ if((*l)->c == c){
+ h = *l;
+ (*l) = h->next;
+ free(h);
+ break;
+ }
+ unlock(ht);
+}
+
+/* look for a matching conversation with the following precedence
+ * connected && raddr,rport,laddr,lport
+ * announced && laddr,lport
+ * announced && *,lport
+ * announced && laddr,*
+ * announced && *,*
+ */
+Conv*
+iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp)
+{
+ ulong hv;
+ Iphash *h;
+ Conv *c;
+
+ /* exact 4 pair match (connection) */
+ hv = iphash(sa, sp, da, dp);
+ lock(ht);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchexact)
+ continue;
+ c = h->c;
+ if(sp == c->rport && dp == c->lport
+ && ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match local address and port */
+ hv = iphash(IPnoaddr, 0, da, dp);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchpa)
+ continue;
+ c = h->c;
+ if(dp == c->lport && ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match just port */
+ hv = iphash(IPnoaddr, 0, IPnoaddr, dp);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchport)
+ continue;
+ c = h->c;
+ if(dp == c->lport){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match local address */
+ hv = iphash(IPnoaddr, 0, da, 0);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchaddr)
+ continue;
+ c = h->c;
+ if(ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* look for something that matches anything */
+ hv = iphash(IPnoaddr, 0, IPnoaddr, 0);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchany)
+ continue;
+ c = h->c;
+ unlock(ht);
+ return c;
+ }
+ unlock(ht);
+ return nil;
+}
M ip/rudp.c => ip/rudp.c +17 -28
@@ 147,6 147,7 @@ typedef struct Rudppriv Rudppriv;
struct Rudppriv
{
Rendez vous;
+ Ipht ht;
/* MIB counters */
Rudpstats ustats;
@@ 214,10 215,13 @@ static char*
rudpconnect(Conv *c, char **argv, int argc)
{
char *e;
+ Rudppriv *upriv;
+ upriv = c->p->priv;
rudpstartackproc(c->p);
e = Fsstdconnect(c, argv, argc);
Fsconnected(c, e);
+ iphtadd(&upriv->ht, c);
return e;
}
@@ 243,12 247,15 @@ static char*
rudpannounce(Conv *c, char** argv, int argc)
{
char *e;
+ Rudppriv *upriv;
+ upriv = c->p->priv;
rudpstartackproc(c->p);
e = Fsstdannounce(c, argv, argc);
if(e != nil)
return e;
Fsconnected(c, nil);
+ iphtadd(&upriv->ht, c);
return nil;
}
@@ 265,6 272,10 @@ rudpclose(Conv *c)
{
Rudpcb *ucb;
Reliable *r, *nr;
+ Rudppriv *upriv;
+
+ upriv = c->p->priv;
+ iphtrem(&upriv->ht, c);
/* force out any delayed acks */
ucb = (Rudpcb*)c->ptcl;
@@ 468,7 479,7 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
{
int len, olen, ottl;
Udphdr *uh;
- Conv *c, **p;
+ Conv *c;
Rudpcb *ucb;
uchar raddr[IPaddrlen], laddr[IPaddrlen];
ushort rport, lport;
@@ 509,33 520,12 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
qlock(rudp);
- /* Look for a conversation structure for this port */
- c = nil;
- for(p = rudp->conv; *p; p++) {
- c = *p;
- if(c->inuse == 0)
- continue;
- if(c->lport == lport){
- ucb = (Rudpcb*)c->ptcl;
-
- /* with headers turned on, descriminate only on local port */
- if(ucb->headers)
- break;
-
- /* otherwise discriminate on lport, rport, and raddr */
- if(c->rport == 0 || c->rport == rport)
- if(ipisbm(c->raddr) || ipcmp(c->raddr, IPnoaddr) == 0
- || ipcmp(c->raddr, raddr) == 0)
- break;
- }
- }
-
- if(*p == nil) {
- qunlock(rudp);
+ c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
+ if(c == nil){
+ /* no converstation found */
upriv->ustats.rudpNoPorts++;
- netlog(f, Logrudp, "rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
- laddr, lport);
- DPRINT("rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
+ qunlock(rudp);
+ netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
laddr, lport);
uh->Unused = ottl;
hnputs(uh->udpplen, olen);
@@ 543,7 533,6 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
freeblist(bp);
return;
}
-
ucb = (Rudpcb*)c->ptcl;
qlock(ucb);
qunlock(rudp);
M ip/tcp.c => ip/tcp.c +29 -66
@@ 245,6 245,9 @@ struct Tcppriv
QLock tl; /* Protect timer list */
Rendez tcpr; /* used by tcpackproc */
+ /* hash table for matching conversations */
+ Ipht ht;
+
ulong stats[Nstats];
/* for keeping track of tcpackproc */
@@ 604,6 607,8 @@ localclose(Conv *s, char *reason) /* called with tcb locked */
tpriv = s->p->priv;
tcb = (Tcpctl*)s->ptcl;
+ iphtrem(&tpriv->ht, s);
+
tcphalt(tpriv, &tcb->timer);
tcphalt(tpriv, &tcb->rtt_timer);
tcphalt(tpriv, &tcb->acktimer);
@@ 711,6 716,7 @@ tcpstart(Conv *s, int mode, ushort window)
tcb->window = window;
tcb->rcv.wnd = window;
+ iphtadd(&tpriv->ht, s);
switch(mode) {
case TCP_LISTEN:
tpriv->stats[PassiveOpens]++;
@@ 983,6 989,7 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst)
Conv *new;
Tcpctl *tcb;
Tcphdr *h;
+ Tcppriv *tpriv;
new = Fsnewcall(s, src, segp->source, dst, segp->dest);
if(new == nil)
@@ 1008,6 1015,9 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst)
v6tov4(h->tcpsrc, dst);
v6tov4(h->tcpdst, src);
+ tpriv = new->p->priv;
+ iphtadd(&tpriv->ht, new);
+
return new;
}
@@ 1218,7 1228,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
Tcpctl *tcb;
ushort length;
uchar source[IPaddrlen], dest[IPaddrlen];
- Conv *spec, *gen, *s, **p;
+ Conv *s;
Fs *f;
Tcppriv *tpriv;
@@ 1229,9 1239,9 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
h = (Tcphdr*)(bp->rp);
+ length = nhgets(h->length);
v4tov6(dest, h->tcpdst);
v4tov6(source, h->tcpsrc);
- length = nhgets(h->length);
h->Unused = 0;
hnputs(h->tcplen, length-TCP_PKT);
@@ 1265,77 1275,30 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
/* lock protocol while searching for a conversation */
qlock(tcp);
- /* Look for a connection. failing that look for a listener. */
- for(p = tcp->conv; *p; p++) {
- s = *p;
- tcb = (Tcpctl*)s->ptcl;
- if(s->rport == seg.source)
- if(s->lport == seg.dest)
- if(tcb->state != Closed)
- if(ipcmp(s->raddr, source) == 0)
- break;
- }
- s = *p;
- if(s){
- /* can't send packets to a listener */
- tcb = (Tcpctl*)s->ptcl;
- if(tcb->state == Listen){
- qunlock(tcp);
- freeblist(bp);
- return;
- }
+ /* Look for a matching conversation */
+ s = iphtlook(&tpriv->ht, source, seg.source, dest, seg.dest);
+ if(s == nil){
+reset:
+ qunlock(tcp);
+ sndrst(tcp, source, dest, length, &seg);
+ freeblist(bp);
+ return;
}
- if(s == nil && (seg.flags & SYN)) {
- /*
- * dump packets with bogus flags
- */
- if(seg.flags & RST){
- qunlock(tcp);
- freeblist(bp);
- return;
- }
- if(seg.flags & ACK) {
+ /* if it's a listener, look for the right flags and get a new conv */
+ tcb = (Tcpctl*)s->ptcl;
+ if(tcb->state == Listen){
+ if(seg.flags & RST){
qunlock(tcp);
- sndrst(tcp, source, dest, length, &seg);
freeblist(bp);
return;
}
+ if((seg.flags & SYN) == 0 || (seg.flags & ACK) != 0)
+ goto reset;
- /*
- * find a listener specific to this port (spec) or,
- * failing that, a general one (gen)
- */
- gen = nil;
- spec = nil;
- for(p = tcp->conv; *p; p++) {
- s = *p;
- tcb = (Tcpctl*)s->ptcl;
- if((tcb->flags & CLONE) == 0)
- continue;
- if(tcb->state != Listen)
- continue;
- if(s->rport == 0 && ipcmp(s->raddr, IPnoaddr) == 0) {
- if(s->lport == seg.dest){
- spec = s;
- break;
- }
- if(s->lport == 0)
- gen = s;
- }
- }
- s = nil;
- if(spec != nil)
- s = tcpincoming(spec, &seg, source, dest);
- else
- if(gen != nil)
- s = tcpincoming(gen, &seg, source, dest);
- }
- if(s == nil) {
- qunlock(tcp);
- sndrst(tcp, source, dest, length, &seg);
- freeblist(bp);
- return;
+ s = tcpincoming(s, &seg, source, dest);
+ if(s == nil)
+ goto reset;
}
/* The rest of the input state machine is run with the control block
M ip/udp.c => ip/udp.c +39 -75
@@ 58,6 58,8 @@ struct Udpstats
typedef struct Udppriv Udppriv;
struct Udppriv
{
+ Ipht ht;
+
/* MIB counters */
Udpstats ustats;
@@ 80,9 82,12 @@ static char*
udpconnect(Conv *c, char **argv, int argc)
{
char *e;
+ Udppriv *upriv;
+ upriv = c->p->priv;
e = Fsstdconnect(c, argv, argc);
Fsconnected(c, e);
+ iphtadd(&upriv->ht, c);
return e;
}
@@ 98,11 103,14 @@ static char*
udpannounce(Conv *c, char** argv, int argc)
{
char *e;
+ Udppriv *upriv;
+ upriv = c->p->priv;
e = Fsstdannounce(c, argv, argc);
if(e != nil)
return e;
Fsconnected(c, nil);
+ iphtadd(&upriv->ht, c);
return nil;
}
@@ 118,6 126,10 @@ static void
udpclose(Conv *c)
{
Udpcb *ucb;
+ Udppriv *upriv;
+
+ upriv = c->p->priv;
+ iphtrem(&upriv->ht, c);
c->state = 0;
qclose(c->rq);
@@ 245,7 257,7 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
{
int len, olen, ottl;
Udphdr *uh;
- Conv *c, **p, *gen;
+ Conv *c;
Udpcb *ucb;
uchar raddr[IPaddrlen], laddr[IPaddrlen];
ushort rport, lport;
@@ 283,85 295,37 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
qlock(udp);
- gen = nil;
-
- /* look for an announced port with headers (most likely) */
- for(p = udp->conv; *p; p++){
- c = *p;
- ucb = (Udpcb*)c->ptcl;
- if(c->inuse == 0 || c->state != Announced || ucb->headers == 0)
- continue;
-
- if(c->lport != lport)
- continue;
-
- if(ipcmp(c->laddr, laddr) == 0)
- goto found;
-
- if(ipcmp(c->laddr, IPnoaddr) == 0 || ipcmp(c->laddr, v4prefix) == 0)
- gen = c;
- }
- if(gen != nil){
- c = gen;
- goto found;
- }
-
- /* look for a connected port */
- for(p = udp->conv; *p; p++){
- c = *p;
- if(c->inuse == 0 || c->state != Connected)
- continue;
- if(c->lport == lport
- && c->rport == rport
- && (ipcmp(c->laddr, laddr) == 0)
- && ipcmp(c->raddr, raddr) == 0 || ipisbm(c->raddr))
- goto found;
+ c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
+ if(c == nil){
+ /* no converstation found */
+ upriv->ustats.udpNoPorts++;
+ qunlock(udp);
+ netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
+ laddr, lport);
+ uh->Unused = ottl;
+ hnputs(uh->udpplen, olen);
+ icmpnoconv(f, bp);
+ freeblist(bp);
+ return;
}
+ ucb = (Udpcb*)c->ptcl;
- /* finally, look for a listener */
- for(p = udp->conv; *p; p++){
- c = *p;
- ucb = (Udpcb*)c->ptcl;
- if(c->inuse == 0 || c->state != Announced || ucb->headers != 0)
- continue;
-
- if(c->lport != lport)
- continue;
-
- if(ipcmp(c->laddr, laddr) == 0)
- break;
-
- if(ipcmp(c->laddr, IPnoaddr) == 0)
- gen = c;
- }
- c = *p;
- if(c == nil)
- c = gen;
- if(c != nil){
- if(ipforme(f, laddr) != Runi)
- v4tov6(laddr, ia);
- c = Fsnewcall(gen, raddr, rport, laddr, lport);
- if(c == nil){
- freeblist(bp);
- return;
+ if(c->state == Announced){
+ if(ucb->headers == 0){
+ /* create a new conversation */
+ if(ipforme(f, laddr) != Runi)
+ v4tov6(laddr, ia);
+ c = Fsnewcall(c, raddr, rport, laddr, lport);
+ if(c == nil){
+ qunlock(udp);
+ freeblist(bp);
+ return;
+ }
+ iphtadd(&upriv->ht, c);
+ ucb = (Udpcb*)c->ptcl;
}
- c->state = Connected;
- goto found;
}
- /* no converstation found */
- upriv->ustats.udpNoPorts++;
- qunlock(udp);
- netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
- laddr, lport);
- uh->Unused = ottl;
- hnputs(uh->udpplen, olen);
- icmpnoconv(f, bp);
- freeblist(bp);
- return;
-
-found:
- ucb = (Udpcb*)c->ptcl;
qlock(c);
qunlock(udp);
M pc/ether82557.c => pc/ether82557.c +23 -8
@@ 90,8 90,6 @@ enum { /* Ecr */
EEstart = 0x04, /* start bit */
EEread = 0x02, /* read opcode */
-
- EEaddrsz = 6, /* bits of address */
};
enum { /* Mcr */
@@ 190,7 188,8 @@ typedef struct Ctlr {
int state;
int port;
- ushort eeprom[0x40];
+ int eepromsz; /* address size in bits */
+ ushort* eeprom;
Lock miilock;
@@ 440,7 439,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold);
len += snprint(p+len, READSTR-len, "eeprom:");
- for(i = 0; i < 0x40; i++){
+ for(i = 0; i < (1<<ctlr->eepromsz); i++){
if(i && ((i & 0x07) == 0))
len += snprint(p+len, READSTR-len, "\n ");
len += snprint(p+len, READSTR-len, " %4.4uX", ctlr->eeprom[i]);
@@ 825,7 824,7 @@ miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
static int
hy93c46r(Ctlr* ctlr, int r)
{
- int i, op, data;
+ int data, i, op, size;
/*
* Hyundai HY93C46 or equivalent serial EEPROM.
@@ 833,6 832,7 @@ hy93c46r(Ctlr* ctlr, int r)
* in the EEPROM is taken straight from Section
* 3.3.4.2 of the Intel 82557 User's Guide.
*/
+reread:
csr16w(ctlr, Ecr, EEcs);
op = EEstart|EEread;
for(i = 2; i >= 0; i--){
@@ 844,8 844,14 @@ hy93c46r(Ctlr* ctlr, int r)
microdelay(1);
}
- for(i = EEaddrsz-1; i >= 0; i--){
- data = (((r>>i) & 0x01)<<2)|EEcs;
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->eepromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ data = (((r>>size) & 0x01)<<2)|EEcs;
csr16w(ctlr, Ecr, data);
csr16w(ctlr, Ecr, data|EEsk);
delay(1);
@@ 867,6 873,12 @@ hy93c46r(Ctlr* ctlr, int r)
csr16w(ctlr, Ecr, 0);
+ if(ctlr->eepromsz == 0){
+ ctlr->eepromsz = 8-size;
+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+ goto reread;
+ }
+
return data;
}
@@ 1022,9 1034,12 @@ reset(Ether* ether)
/*
* Read the EEPROM.
+ * Do a dummy read first to get the size
+ * and allocate ctlr->eeprom.
*/
+ hy93c46r(ctlr, 0);
sum = 0;
- for(i = 0; i < 0x40; i++){
+ for(i = 0; i < (1<<ctlr->eepromsz); i++){
x = hy93c46r(ctlr, i);
ctlr->eeprom[i] = x;
sum += x;