From 0b8779b500b4f282d896ab42441e2e8dd3a59178 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 1 Mar 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-03-01 --- boot/boot.c | 1 - ip/devip.c | 38 ++++++------ ip/il.c | 158 ++++++++++++++++++++---------------------------- ip/ip.h | 30 +++++++++ ip/ipaux.c | 154 ++++++++++++++++++++++++++++++++++++++++++++-- ip/rudp.c | 45 ++++++-------- ip/tcp.c | 95 +++++++++-------------------- ip/udp.c | 114 ++++++++++++---------------------- pc/ether82557.c | 31 +++++++--- 9 files changed, 371 insertions(+), 295 deletions(-) diff --git a/boot/boot.c b/boot/boot.c index 6248561eb26c591ab7da8e061044c8a353f6a05c..bf84fb3086525dfeba4857f0461abb00afcd7522 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -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; diff --git a/ip/devip.c b/ip/devip.c index c724b378c00f1cd288c6d52c49492b39458f4519..747d9eeb65efeea40b9064b47e90be9cfba31679 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -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 diff --git a/ip/il.c b/ip/il.c index 3c3fd3b3eb0d55216ee93267003766d76f18ddda..17947d61201af7ea172652b2f0c2340617e3006e 100644 --- a/ip/il.c +++ b/ip/il.c @@ -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; } diff --git a/ip/ip.h b/ip/ip.h index 67bcf25e8c63daaa244748a5cb4f4c5f16bb848b..23ffb8bdcd4cbe02e60f014463d77fb7dbb8b1c1 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -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; @@ -195,6 +197,34 @@ struct Ipmulti Ipmulti *next; }; +/* + * 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 */ diff --git a/ip/ipaux.c b/ip/ipaux.c index 4bc7f69eb02d05f87483e44616baba5253120221..c09811689b8c805d3a7bd02d8de351be37a5cac6 100644 --- a/ip/ipaux.c +++ b/ip/ipaux.c @@ -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; +} diff --git a/ip/rudp.c b/ip/rudp.c index a704c9709217fd23ca5b1109b59a8426974301f6..75fe75319c24b8f2d8476cd64755dc34c3342b20 100644 --- a/ip/rudp.c +++ b/ip/rudp.c @@ -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); diff --git a/ip/tcp.c b/ip/tcp.c index 6b0f9c16ad05da98f66af5a8d3f3ac9594e19fb1..9f8b8964595008e7f506b3220b023bd6dd5dc67f 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -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 diff --git a/ip/udp.c b/ip/udp.c index b0b791e3df0290feccea87c3539e9648293ff214..80b849599dd24466460dcb12fd19d021f5f7a34f 100644 --- a/ip/udp.c +++ b/ip/udp.c @@ -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); diff --git a/pc/ether82557.c b/pc/ether82557.c index 0d83fda86469cdf33a9e30c4b0e2fcdb8710f492..3429bb480051abdeb957c3d4e89ff3b9a88a6610 100644 --- a/pc/ether82557.c +++ b/pc/ether82557.c @@ -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<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<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<eepromsz); i++){ x = hy93c46r(ctlr, i); ctlr->eeprom[i] = x; sum += x;