From a8a153f27e80ca51e1717690adf1755ea7b08ac9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 22 Nov 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-11-22 --- gnot/devincon.c | 36 +++++++++++++++---- port/devdk.c | 4 ++- port/fault.c | 10 ++++-- port/net.c | 2 +- port/page.c | 16 +++++---- port/portdat.h | 2 ++ port/portfns.h | 1 + port/segment.c | 8 ++++- port/stil.c | 96 ++++++++++++++++++++++++++++++++++++------------- port/stream.c | 1 + port/sturp.c | 21 +++++++++-- port/tcpinput.c | 23 ++++++++---- 12 files changed, 168 insertions(+), 52 deletions(-) diff --git a/gnot/devincon.c b/gnot/devincon.c index 522290959737da5167ac5a0e69280864028e49f9..aede0684fbf1f1ea049897d1f58d885250f09906 100644 --- a/gnot/devincon.c +++ b/gnot/devincon.c @@ -24,7 +24,9 @@ enum { Nincon= 1, /* number of incons */ Nin= 32, /* Blocks in the input ring */ Bsize= 128, /* size of an input ring block */ - Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */ + Mfifo= 0xff, /* a mask, must be 2^n-1, must be > Nin */ + + Qstats= 1, /* qid of the statistics file */ }; /* @@ -78,6 +80,7 @@ struct Incon { ulong crc; /* crc errors */ ulong in; /* bytes in */ ulong out; /* bytes out */ + ulong wait; /* wait time in milliseconds */ }; Incon incon[Nincon]; @@ -141,6 +144,10 @@ Qinfo inconinfo = int incondebug; +Dirtab incondir[]={ + "stats", {Qstats}, 0, 0444, +}; + /* * set the incon parameters */ @@ -354,19 +361,19 @@ inconclone(Chan *c, Chan *nc) int inconwalk(Chan *c, char *name) { - return devwalk(c, name, 0, 0, streamgen); + return devwalk(c, name, incondir, 1, streamgen); } void inconstat(Chan *c, char *dp) { - devstat(c, dp, 0, 0, streamgen); + devstat(c, dp, incondir, 1, streamgen); } Chan* inconopen(Chan *c, int omode) { - if(c->qid.path == CHDIR){ + if(c->qid.path == CHDIR || c->qid.path == Qstats){ if(omode != OREAD) error(Eperm); }else @@ -393,7 +400,18 @@ inconclose(Chan *c) long inconread(Chan *c, void *buf, long n, ulong offset) { - return streamread(c, buf, n); + char b[256]; + Incon *i; + + if(c->qid.path == CHDIR) + return devdirread(c, buf, n, incondir, 1, streamgen); + else if(c->qid.path == Qstats){ + i = &incon[c->dev]; + sprint(b, "in: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n", i->in, + i->out, i->overflow, i->crc, i->wait); + return stringread(buf, n, b, offset); + } else + return streamread(c, buf, n); } long @@ -486,7 +504,7 @@ inconoput(Queue *q, Block *bp) { Device *dev; Incon *ip; - ulong end; + ulong start, end; int chan; int ctl; int n, size; @@ -548,7 +566,8 @@ inconoput(Queue *q, Block *bp) /* * spin till there is room */ - for(end = NOW+1000; dev->status & TX_FULL;){ + start = NOW; + for(n = 0, end = start+1000; dev->status & TX_FULL; n++){ nop(); /* make sure we don't optimize too much */ if(NOW > end){ print("incon output stuck\n"); @@ -557,6 +576,7 @@ inconoput(Queue *q, Block *bp) return; } } + ip->wait = (n + ip->wait)>>1; /* * put in next packet @@ -566,6 +586,7 @@ inconoput(Queue *q, Block *bp) n = 16; size = n; dev->cdata = chan; + ip->out += n; while(n--){ *(uchar *)&dev->data_cntl = *bp->rptr++; } @@ -689,6 +710,7 @@ inconkproc(void *arg) */ while(ip->ri != ip->wi){ bp = ip->inb[ip->ri]; + ip->in += BLEN(bp); PUTNEXT(ip->rq, bp); bp = ip->inb[ip->ri] = allocb(Bsize); bp->wptr += 3; diff --git a/port/devdk.c b/port/devdk.c index 2c04cfd64242384a59ff3c78be1267a17ffce952..f238d97a1f7a2ce0482cba9d8e39907787fade98 100644 --- a/port/devdk.c +++ b/port/devdk.c @@ -300,13 +300,15 @@ dkalloc(char *name, int ncsc, int lines) dp->net.listen = dklisten; dp->net.clone = dkcloneline; dp->net.prot = dp->prot; - dp->net.ninfo = 3; + dp->net.ninfo = 4; dp->net.info[0].name = "addr"; dp->net.info[0].fill = dkfilladdr; dp->net.info[1].name = "raddr"; dp->net.info[1].fill = dkfillraddr; dp->net.info[2].name = "ruser"; dp->net.info[2].fill = dkfillruser; + dp->net.info[3].name = "stats"; + dp->net.info[3].fill = urpfillstats; unlock(&dklock); return dp; diff --git a/port/fault.c b/port/fault.c index 8b89e7a7815d5ef09b742fe250595bc9980f3ea5..860a6edee3c7b68cc5a2a760a862e5afee91865b 100644 --- a/port/fault.c +++ b/port/fault.c @@ -46,7 +46,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) { ulong mmuphys=0, soff; Page **pg, *lkp, *new = 0; - Pte **p; + Pte **p, *etp; int type; addr &= ~(BY2PG-1); @@ -55,9 +55,15 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) if(*p == 0) *p = ptealloc(); - pg = &(*p)->pages[(soff&(PTEMAPMEM-1))/BY2PG]; + etp = *p; + pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG]; type = s->type&SG_TYPE; + if(pg < etp->first) + etp->first = pg; + if(pg > etp->last) + etp->last = pg; + switch(type) { case SG_TEXT: if(pagedout(*pg)) /* No data - must demand load */ diff --git a/port/net.c b/port/net.c index c9dc4bad0259bde979debd1cfb32503bc4afd20b..ce6fc1cc42b4562fcae3b10555f0161298e11644 100644 --- a/port/net.c +++ b/port/net.c @@ -170,7 +170,7 @@ netwstat(Chan *c, char *db, Network *np) Chan * netopen(Chan *c, int omode, Network *np) { - int id; + int id = 0; if(c->qid.path & CHDIR){ if(omode != OREAD) diff --git a/port/page.c b/port/page.c index 0d5c98b48a75370ee6595fcbf8dc9cbc5cf9f167..4fccbe178506dd83b193769652ca1569e628085d 100644 --- a/port/page.c +++ b/port/page.c @@ -433,9 +433,9 @@ ptecpy(Pte *old) Pte *new; new = ptealloc(); - - end = &old->pages[PTEPERTAB]; - for(src = old->pages, dst = new->pages; src < end; src++, dst++) + dst = &new->pages[old->first-old->pages]; + new->first = dst; + for(src = old->first; src <= old->last; src++, dst++) if(*src) { if(onswap(*src)) dupswap(*src); @@ -444,6 +444,7 @@ ptecpy(Pte *old) (*src)->ref++; unlockpage(*src); } + new->last = dst; *dst = *src; } @@ -461,7 +462,7 @@ ptealloc(void) while(ptealloclk.free == 0) { unlock(&ptealloclk); - k = kmap(newpage(1, 0, 0)); + k = kmap(newpage(0, 0, 0)); new = (Pte*)VA(k); n = (BY2PG/sizeof(Pte))-1; for(i = 0; i < n; i++) @@ -477,6 +478,8 @@ ptealloc(void) ptealloclk.free = new->next; unlock(&ptealloclk); memset(new->pages, 0, sizeof(new->pages)); + new->first = &new->pages[PTEPERTAB]; + new->last = new->pages; return new; } @@ -485,16 +488,15 @@ freepte(Segment *s, Pte *p) { Page **pg, **ptop; - ptop = &p->pages[PTEPERTAB]; - switch(s->type&SG_TYPE) { case SG_PHYSICAL: + ptop = &p->pages[PTEPERTAB]; for(pg = p->pages; pg < ptop; pg++) if(*pg) (*s->pgfree)(*pg); break; default: - for(pg = p->pages; pg < ptop; pg++) + for(pg = p->first; pg <= p->last; pg++) if(*pg) putpage(*pg); } diff --git a/port/portdat.h b/port/portdat.h index 74dd2de6fc4c1b39063c5df693335206109d0866..e330b27bbfca50813d95a2a2c0c984899d4a9d8a 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -323,6 +323,8 @@ struct Pte Pte *next; /* Free list */ Page *pages[PTEPERTAB]; /* Page map for this chunk of pte */ }; + Page **first; /* First used entry */ + Page **last; /* Last used entry */ }; /* Segment types */ diff --git a/port/portfns.h b/port/portfns.h index 25c9a41d1734f7615c4268fdadc5b74f2b56c8f4..aee61b4e8287b27dfcb42e8ad1c759771a209c49 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -248,3 +248,4 @@ Mhead* newmnthead(void); void mountfree(Mount*); void mntheadfree(Mhead*); void unmount(Chan*, Chan*); +void urpfillstats(Chan*, char*, int); diff --git a/port/segment.c b/port/segment.c index 3a5314af9a57de3214c5b8eebff90008277fa495..e72908bb8ca4359a01a456791718d7e57b953df1 100644 --- a/port/segment.c +++ b/port/segment.c @@ -186,6 +186,7 @@ segpage(Segment *s, Page *p) { Pte **pte; ulong off; + Page **pg; if(p->va < s->base || p->va >= s->top) panic("segpage"); @@ -195,7 +196,12 @@ segpage(Segment *s, Page *p) if(*pte == 0) *pte = ptealloc(); - (*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG] = p; + pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG]; + *pg = p; + if(pg < (*pte)->first) + (*pte)->first = pg; + if(pg > (*pte)->last) + (*pte)->last = pg; } Image* diff --git a/port/stil.c b/port/stil.c index f19ea90bc00fc7a14e974f5ef5aaedb8c68ac53f..a494548cc17c1a717ddfc83ba80155bd266cb3d0 100644 --- a/port/stil.c +++ b/port/stil.c @@ -11,7 +11,7 @@ #include "arp.h" #include "ipdat.h" -#define DBG if(1)print +#define DBG if(0)print int ilcksum = 1; static int initseq = 25000; static Rendez ilackr; @@ -21,8 +21,9 @@ char *iltype[] = { "sync", "data", "dataquerey", "ack", "querey", "state", "clo enum { - Slowtime = 20, - Fasttime = 1, + Mstime = 200, + Slowtime = Mstime*20, + Fasttime = Mstime, }; void ilrcvmsg(Ipconv*, Block*); @@ -31,9 +32,13 @@ void ilsendctl(Ipconv*, Ilhdr*, int); void ilackq(Ilcb*, Block*); void ilprocess(Ipconv*, Ilhdr*, Block*); void ilpullup(Ipconv*); -void ilhangup(Ipconv*); +void ilhangup(Ipconv*, char*); void ilfreeq(Ilcb*); +char Crefused[] = "connection refused"; +char Ctimedout[] = "connection timed out"; +char Creset[] = "connection reset by peer"; + void ilopen(Queue *q, Stream *s) { @@ -85,8 +90,9 @@ ilclose(Queue *q) ic->state = Ilclosing; ilsendctl(s, 0, Ilclose); break; - Illistening: + case Illistening: ic->state = Ilclosed; + s->psrc = 0; break; } netdisown(&s->ipinterface->net, s->index); @@ -154,8 +160,8 @@ iloput(Queue *q, Block *bp) /* Checksum of ilheader plus data (not ip & no pseudo header) */ if(ilcksum) hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE)); + ilackq(ic, bp); - delay(100); PUTNEXT(q, bp); } @@ -233,7 +239,10 @@ ilrcvmsg(Ipconv *ipc, Block *bp) etab = &ipc[conf.ip]; for(s = ipc; s < etab; s++) - if(s->psrc == sp && s->pdst == dp && s->dst == dst) { + if(s->ilctl.state != Ilclosed) + if(s->psrc == sp) + if(s->pdst == dp) + if(s->dst == dst) { ilprocess(s, ih, bp); return; } @@ -241,17 +250,18 @@ ilrcvmsg(Ipconv *ipc, Block *bp) if(ih->iltype != Ilsync) goto drop; - if(s->curlog > s->backlog) - goto reset; - /* Look for a listener */ for(s = ipc; s < etab; s++) { if(s->ilctl.state == Illistening) if(s->pdst == 0) if(s->dst == 0) { + if(s->curlog > s->backlog) + goto reset; new = ipincoming(ipc, s); - if(new == 0) + if(new == 0) { + print("incoming\n"); goto reset; + } new->newcon = 1; new->ipinterface = s->ipinterface; @@ -297,6 +307,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) ack = nhgetl(h->ilack); ic = &s->ilctl; + ic->timeout = 0; switch(ic->state) { default: panic("il unknown state"); @@ -310,7 +321,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) case Ilsync: if(ack != ic->start) { ic->state = Ilclosed; - ilhangup(s); + ilhangup(s, Crefused); } else { ic->recvd = id; @@ -323,7 +334,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) case Ilclose: if(ack == ic->start) { ic->state = Ilclosed; - ilhangup(s); + ilhangup(s, Crefused); } break; } @@ -350,7 +361,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) case Ilclose: if(ack == ic->start) { ic->state = Ilclosed; - ilhangup(s); + ilhangup(s, Crefused); } break; } @@ -361,7 +372,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) case Ilsync: if(id != ic->start) { ic->state = Ilclosed; - ilhangup(s); + ilhangup(s, Creset); } else ilsendctl(s, 0, Ilack); @@ -423,7 +434,7 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp) ic->recvd = id; if(ack == ic->next) { ic->state = Ilclosed; - ilhangup(s); + ilhangup(s, 0); } ilsendctl(s, 0, Ilclose); break; @@ -442,23 +453,31 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp) Ilcb *ic = &s->ilctl; USED(ic); - DBG("%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ", + DBG("%-11s rcv %d/%d snt %d/%d pkt(%-6s id %d ack %d %d->%d) ", ilstate[ic->state], ic->rstart, ic->recvd, ic->start, ic->next, iltype[h->iltype], nhgetl(h->ilid), nhgetl(h->ilack), nhgets(h->ilsrc), nhgets(h->ildst)); _ilprocess(s, h, bp); - DBG("%11s rcv %d snt %d\n", ilstate[ic->state], ic->recvd, ic->next); + DBG("%-11s rcv %d snt %d\n", ilstate[ic->state], ic->recvd, ic->next); } void -ilhangup(Ipconv *s) +ilhangup(Ipconv *s, char *msg) { Block *nb; + ulong l; if(s->readq) { - nb = allocb(0); + if(msg) { + l = strlen(msg); + nb = allocb(l); + strcpy((char*)nb->wptr, msg); + nb->wptr += l; + } + else + nb = allocb(0); nb->type = M_HANGUP; nb->flags |= S_DELIM; PUTNEXT(s->readq, nb); @@ -588,22 +607,51 @@ ilackproc(void *a) base = (Ipconv*)a; end = &base[conf.ip]; - for(;;) { - tsleep(&ilackr, return0, 0, 250); + tsleep(&ilackr, return0, 0, Mstime); for(s = base; s < end; s++) { ic = &s->ilctl; switch(ic->state) { - case Ilclosed: - case Illistening: + default: break; case Ilclosing: + ic->timeout++; + if(ic->timeout >= Slowtime) { + ic->state = Ilclosed; + ilhangup(s, 0); + } break; case Ilsyncee: + ic->timeout++; + if(ic->timeout >= Slowtime) { + ic->state = Ilclosed; + ilhangup(s, Ctimedout); + break; + } +print("Rxmit %d/%d %s", s->psrc, s->pdst, ilstate[ic->state]); + ilsendctl(s, 0, Ilsync); break; case Ilsyncer: + ic->timeout++; + if(ic->timeout >= Slowtime) { + ic->state = Ilclosed; + ilhangup(s, Ctimedout); + break; + } +print("Rxmit %d/%d %s", s->psrc, s->pdst, ilstate[ic->state]); + ilsendctl(s, 0, Ilsync); break; case Ilestablished: + ic->timeout++; + if(ic->unacked == 0) + break; + if(ic->timeout >= Slowtime) { + ic->state = Ilclosed; + ilhangup(s, Ctimedout); + break; + } +print("Rxmit %d/%d %s", s->psrc, s->pdst, ilstate[ic->state]); + ilsendctl(s, 0, Ilstate); break; } } diff --git a/port/stream.c b/port/stream.c index 67a0ed707e18fc30beb567351d34fadd5ba8dca1..db42bb3caf782fdbde1518c890efc0f8f7be0095 100644 --- a/port/stream.c +++ b/port/stream.c @@ -215,6 +215,7 @@ allocb(ulong size) bp->flags = bcp - bclass; bp->rptr = bp->wptr = bp->base; bp->next = 0; + bp->list = 0; bp->type = M_DATA; bp->flags &= S_CLASS; if(bp->lim-bp->rptr0 && q->next->len<2*Streamhi && q->next->nb<2*Streambhi){ bp->flags |= S_DELIM; + urpstat.input += BLEN(bp); PUTNEXT(q, bp); } else freeb(bp); @@ -506,8 +507,10 @@ urpiput(Queue *q, Block *bp) if(q->first) { if(up->trbuf[0] != BOTM) q->last->flags |= S_DELIM; - while(bp = getq(q)) + while(bp = getq(q)){ + urpstat.input += BLEN(bp); PUTNEXT(q, bp); + } } else { bp = allocb(0); if(up->trbuf[0] != BOTM) @@ -656,6 +659,7 @@ output(Urp *up) * if a retransmit is requested, move next back to * the unacked blocks */ + urpstat.rexmit++; up->rexmit = 0; up->next = up->unacked; } else if(up->unechoed!=up->next && NOW>up->timer){ @@ -665,6 +669,7 @@ output(Urp *up) */ up->timer = NOW + MSrexmit; up->state &= ~REJECTING; + urpstat.enqsx++; sendctl(up, ENQ); goto out; } @@ -1005,3 +1010,15 @@ urpdump(void) if(up->rq) urpvomit("", up); } + +void +urpfillstats(Chan *c, char *buf, int len) +{ + char b[256]; + + USED(c); + sprint(b, "in: %d\nout: %d\nrexmit: %d\nrjtrs: %d\nrjpks: %d\nrjseq: %d\nenqsx: %d\nenqsr: %d\n", + urpstat.input, urpstat.output, urpstat.rexmit, urpstat.rjtrs, + urpstat.rjpks, urpstat.rjseq, urpstat.enqsr, urpstat.enqsr); + strncpy(buf, b, len); +} diff --git a/port/tcpinput.c b/port/tcpinput.c index 1f51f115814a499f1d021e7421947217820e0e55..109f7d0167500464bc629686f580d06b0a8e0e0e 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -800,22 +800,31 @@ dupb(Block **hp, Block *bp, int offset, int count) Block * copyb(Block *bp, int count) { - Block *nbp; + Block *nbp, *head, *tail; int i; - nbp = allocb(count); - if(nbp == 0) - return 0; - + head = 0; while(bp && count) { - i = MIN(count, BLEN(bp)); + i = BLEN(bp); + nbp = allocb(i); + if(i > nbp->lim-nbp->wptr) { + if(head) + freeb(head); + return 0; + } memmove(nbp->wptr, bp->rptr, i); nbp->wptr += i; count -= i; + if(head == 0) + head = nbp; + else + tail->next = nbp; + + tail = nbp; bp = bp->next; } - return nbp; + return head; } ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent with SYN */