M gnot/devincon.c => gnot/devincon.c +29 -7
@@ 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;
M port/devdk.c => port/devdk.c +3 -1
@@ 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;
M port/fault.c => port/fault.c +8 -2
@@ 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 */
M port/net.c => port/net.c +1 -1
@@ 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)
M port/page.c => port/page.c +9 -7
@@ 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);
}
M port/portdat.h => port/portdat.h +2 -0
@@ 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 */
M port/portfns.h => port/portfns.h +1 -0
@@ 248,3 248,4 @@ Mhead* newmnthead(void);
void mountfree(Mount*);
void mntheadfree(Mhead*);
void unmount(Chan*, Chan*);
+void urpfillstats(Chan*, char*, int);
M port/segment.c => port/segment.c +7 -1
@@ 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*
M port/stil.c => port/stil.c +72 -24
@@ 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;
}
}
M port/stream.c => port/stream.c +1 -0
@@ 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->rptr<size && size<4096)
M port/sturp.c => port/sturp.c +19 -2
@@ 23,7 23,7 @@ typedef struct Urp Urp;
struct urpstat {
ulong input; /* bytes read from urp */
ulong output; /* bytes output to urp */
- ulong rxmit; /* retransmit rejected urp msg */
+ ulong rexmit; /* retransmit rejected urp msg */
ulong rjtrs; /* reject, trailer size */
ulong rjpks; /* reject, packet size */
ulong rjseq; /* reject, sequence number */
@@ 286,6 286,7 @@ urpciput(Queue *q, Block *bp)
*/
if(BLEN(bp)>0 && 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);
+}
M port/tcpinput.c => port/tcpinput.c +16 -7
@@ 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 */