~kris/9p

9hist

a8a153f27e80ca51e1717690adf1755ea7b08ac9 — David du Colombier 34 years ago 7076153
Plan 9 from Bell Labs 1991-11-22
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 */