From 42cf0bcab4a1100665ab131ca7c581881f777f10 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 6 Apr 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-04-06 --- pc/devether.c | 98 ++++++++++++++++++++++++++++---------------- port/devip.c | 3 ++ port/tcpinput.c | 105 ++++++++++++++++++++++++++++++------------------ 3 files changed, 131 insertions(+), 75 deletions(-) diff --git a/pc/devether.c b/pc/devether.c index 661bb77e24febbf9da554f8f069269c6653b756f..d045b498637aa4281c0f37e5c876a2f5fe5c51de 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -2,7 +2,11 @@ * Western Digital ethernet adapter * BUGS: * no more than one controller + * TODO: * fix for different controller types + * output + * deal with stalling and restarting output on input overflow + * fix magic ring constants */ #include "u.h" #include "../port/lib.h" @@ -131,26 +135,24 @@ static Ctlr ctlr[Nctlr]; static void etheroput(Queue *q, Block *bp) { - Ctlr *c; + Ctlr *cp; int len, n; - Pktype *t; + Pktype *pp; Etherpkt *p; Block *nbp; -panic("etheroput\n"); -#ifdef notdef - c = ((Pktype *)q->ptr)->ctlr; + cp = ((Pktype *)q->ptr)->ctlr; if(bp->type == M_CTL){ - t = q->ptr; + pp = q->ptr; if(streamparse("connect", bp)) - t->type = strtol((char *)bp->rptr, 0, 0); + pp->type = strtol((char *)bp->rptr, 0, 0); else if(streamparse("promiscuous", bp)) { - t->prom = 1; - qlock(c); - c->prom++; - if(c->prom == 1) - outb(c->iobase+Rcr, 0x14); /* PRO|AB */ - qunlock(c); + pp->prom = 1; + qlock(cp); + cp->prom++; + if(cp->prom == 1) + outb(cp->iobase+Rcr, 0x14); /* PRO|AB */ + qunlock(cp); } freeb(bp); return; @@ -160,33 +162,30 @@ panic("etheroput\n"); * give packet a local address, return upstream if destined for * this machine. */ - if(BLEN(bp) < ETHERHDRSIZE){ - bp = pullup(bp, ETHERHDRSIZE); - if(bp == 0) - return; - } + if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0) + return; p = (Etherpkt *)bp->rptr; - memmove(p->s, c->ea, sizeof(c->ea)); - if(memcmp(c->ea, p->d, sizeof(c->ea)) == 0){ + memmove(p->s, cp->ea, sizeof(cp->ea)); + if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ len = blen(bp); - bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU); - if(bp){ - putq(&c->rq, bp); - wakeup(&c->rr); + if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ + putq(&cp->rq, bp); + wakeup(&cp->rr); } return; } - if(memcmp(c->ba, p->d, sizeof(c->ba)) == 0){ + if(memcmp(cp->ba, p->d, sizeof(cp->ba)) == 0){ len = blen(bp); nbp = copyb(bp, len); - nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU); - if(nbp){ + if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ nbp->wptr = nbp->rptr+len; - putq(&c->rq, nbp); - wakeup(&c->rr); + putq(&cp->rq, nbp); + wakeup(&cp->rr); } } +panic("etheroput\n"); +#ifdef notdef /* * only one transmitter at a time */ @@ -509,6 +508,18 @@ etherup(Ctlr *cp, Etherpkt *p, int len) } } +static void +printpkt(uchar bnry, ushort len, Etherpkt *p) +{ + int i; + + print("%.2ux: %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)\n", + bnry, len, + p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5], + p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5], + p->type[0], p->type[1]); +} + static int isinput(void *arg) { @@ -534,17 +545,34 @@ etherkproc(void *arg) cp->kproc = 1; for(;;){ sleep(&cp->rr, isinput, cp); + /* + * process any internal loopback packets + */ while(bp = getq(&cp->rq)){ cp->inpackets++; etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); freeb(bp); } -#ifdef foo - bnry = inb(cp->iobase+Bnry); - while(bnry != cp->curr){ - rp = &((Ring *)RAMbase)[bnry]; - } -#endif + /* + * process any received packets + */ + bnry = inb(cp->iobase+Bnry); + while(bnry != cp->curr){ + rp = &((Ring*)RAMbase)[bnry]; +printpkt(bnry, rp->len, (Etherpkt*)rp->data); + cp->inpackets++; + etherup(cp, (Etherpkt*)rp->data, rp->len-4); + bnry = rp->next; + outb(cp->iobase+Bnry, bnry); + } + /* + * if we idled input because of overflow, + * restart + */ + if(cp->ovw){ + cp->ovw = 0; + outb(cp->iobase+Tcr, 0); + } } } diff --git a/port/devip.c b/port/devip.c index b76b1077d282cfa11dcde3324fa816ca1b9ee22a..d6f10ddc6dbbef8c3fa25213221478bd58ffd8e9 100644 --- a/port/devip.c +++ b/port/devip.c @@ -883,6 +883,9 @@ portused(Ipconv *ic, Port port) { Ipconv *ifc, *etab; + if(port == 0) + return 0; + etab = &ic[conf.ip]; for(ifc = ic; ifc < etab; ifc++) if(ifc->psrc == port) diff --git a/port/tcpinput.c b/port/tcpinput.c index b5e8908fb839b51fc249eeaac95cf26bfa5b3e4c..cb512a6fbadee78a5137e3e6302ca52746fa7266 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -79,10 +79,43 @@ reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg) PUTNEXT(Ipoutput, hbp); } +Ipconv* +tcpincoming(Ipconv *ipc, Ipconv *s, Tcp *segp, Ipaddr source) +{ + Ipconv *new; + + if(s->curlog >= s->backlog) + return 0; + + new = ipincoming(ipc, s); + if(new == 0) + return 0; + + qlock(s); + s->curlog++; + qunlock(s); + new->psrc = segp->dest; + new->pdst = segp->source; + new->dst = source; + memmove(&new->tcpctl, &s->tcpctl, sizeof(Tcpctl)); + new->tcpctl.flags &= ~CLONE; + new->tcpctl.timer.arg = new; + new->tcpctl.timer.state = TIMER_STOP; + new->tcpctl.acktimer.arg = new; + new->tcpctl.acktimer.state = TIMER_STOP; + new->newcon = 1; + new->ipinterface = s->ipinterface; + + s->ipinterface->ref++; + wakeup(&s->listenr); + return new; +} + void tcp_input(Ipconv *ipc, Block *bp) { - Ipconv *s, *e, *new; + Ipconv *s, *e; + Ipconv *spec, *gen; Tcpctl *tcb; Tcphdr *h; Tcp seg; @@ -117,48 +150,40 @@ tcp_input(Ipconv *ipc, Block *bp) /* Look for a connection, failing that attempt to establish a listen */ s = ip_conn(ipc, seg.dest, seg.source, source, IP_TCPPROTO); if (s == 0) { - if((seg.flags & SYN) == 0) - goto clear; - - e = &ipc[conf.ip]; - for(s = ipc; s < e; s++) { - if(s->tcpctl.state == Listen) - if(s->pdst == 0) - if(s->dst == 0) { - if(s->curlog >= s->backlog) - goto clear; - - new = ipincoming(ipc, s); - if(new == 0) - goto clear; - - qlock(s); - s->curlog++; - qunlock(s); - new->psrc = seg.dest; - new->pdst = seg.source; - new->dst = source; - memmove(&new->tcpctl, &s->tcpctl, sizeof(Tcpctl)); - new->tcpctl.flags &= ~CLONE; - new->tcpctl.timer.arg = new; - new->tcpctl.timer.state = TIMER_STOP; - new->tcpctl.acktimer.arg = new; - new->tcpctl.acktimer.state = TIMER_STOP; - new->newcon = 1; - new->ipinterface = s->ipinterface; - - s->ipinterface->ref++; - wakeup(&s->listenr); - s = new; - goto process; + if(seg.flags & SYN){ + /* + * find a listener specific to this port (spec) or, + * failing that, a general one (gen) + */ + spec = 0; + gen = 0; + e = &ipc[conf.ip]; + for(s = ipc; s < e; s++) { + if(s->tcpctl.state == Listen) + if(s->pdst == 0) + if(s->dst == 0) { + if(s->psrc == seg.dest){ + spec = s; + break; + } + if(s->psrc == 0) + gen = s; + } } + if(spec) + s = tcpincoming(ipc, spec, &seg, source); + else if(gen) + s = tcpincoming(ipc, gen, &seg, source); + else + s = 0; + } + if(s == 0){ + freeb(bp); + reset(source, dest, tos, length, &seg); + return; } - clear: - freeb(bp); - reset(source, dest, tos, length, &seg); - return; } -process: + /* The rest of the input state machine is run with the control block * locked */