~kris/9p

9hist

90b0301e162f4cb43e9e0f11319500e0ebaf361b — David du Colombier 34 years ago 98c387c
Plan 9 from Bell Labs 1991-10-30
8 files changed, 92 insertions(+), 158 deletions(-)

M port/devarp.c
M port/devenv.c
M port/devip.c
M port/qlock.c
M port/stil.c
M port/tcpinput.c
M port/tcpoutput.c
M ss/main.c
M port/devarp.c => port/devarp.c +6 -4
@@ 282,7 282,6 @@ arpoput(Queue *q, Block *bp)

	if(bp->type != M_DATA) {
		if(Servq == 0 && streamparse("arpd", bp)) {
print("setting arp channel\n");
			Servq = RD(q);
			freeb(bp);
		}


@@ 298,17 297,20 @@ print("setting arp channel\n");
	}

	eh = (Etherhdr *)bp->rptr;
	if(nhgets(eh->type) != ET_IP) {
		PUTNEXT(q, bp);	
		return;
	}

	iproute(eh->dst, ip);

	/* Send downstream to the ethernet */
	if(arplookup(ip, eh->d)) {
print("arp hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
		PUTNEXT(q, bp);
		return;
	}
print("arp miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);

	/* Return the packet to the arp server for address resolution */
	/* Push the packet up to the arp server for address resolution */
	memmove(eh->d, ip, sizeof(ip));
	PUTNEXT(Servq, bp);
}

M port/devenv.c => port/devenv.c +11 -0
@@ 433,6 433,17 @@ envdump(void)
	for(i = 0; i < EVHASH; i++){
		j = 0;
		for(ev = evhash[i].next; ev; ev = ev->next){
			uchar *t, *s;
			int h, n;

			s = (uchar*)ev->val;
			n = ev->len;
			h = 0;
			for(t = s; t - s < n; t++)
				h = (h << 1) ^ *t;
			h &= EVHASH - 1;
			if(h != i)
				print("hash conflict: %d %d\n", i, h);
			if(j++ == 1000){
				print("hash bucket %d circular\n", i);
				break;

M port/devip.c => port/devip.c +3 -7
@@ 15,8 15,7 @@ enum
	Nipsubdir	= 4,		/* Number of subdirectory entries per connection */
};

int udpsum = 1;

int 	udpsum = 1;
Queue	*Ipoutput;		/* Control message stream for tcp/il */
Ipifc	*ipifc;			/* IP protocol interfaces for stip */
Ipconv	*ipconv[Nrprotocol];	/* Connections for each protocol */


@@ 389,8 388,7 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
		qunlock(&ipalloc);

	}
	else if(strcmp(field[0], "announce") == 0 ||
		strcmp(field[0], "reserve") == 0) {
	else if(strcmp(field[0], "announce") == 0 || strcmp(field[0], "reserve") == 0) {
		if((cp->stproto == &tcpinfo && cp->tcpctl.state != CLOSED) ||
		   (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed))
				error(Edevbusy);


@@ 682,11 680,10 @@ iplisten(Chan *c, Ipconv *s, Ipconv *base)
		qunlock(&s->listenq);
		nexterror();
	}
print("listener on %lux R 0x%lux\n", s, &s->listenr);

	for(;;) {
		sleep(&s->listenr, iphavecon, s);
		poperror();
print("listen awoke\n");
		new = base;
 		for(etab = &base[conf.ip]; new < etab; new++) {
			if(new->newcon) {


@@ 704,7 701,6 @@ print("listen awoke\n");
				pushq(c->stream, new->stproto);
				new->ref--;
				qunlock(&s->listenq);
print("ip listener!\n");
				return;
			}
		}

M port/qlock.c => port/qlock.c +1 -1
@@ 33,7 33,7 @@ int
canqlock(QLock *q)
{
	lock(&q->use);
	if(q->locked) {
	if(q->locked){
		unlock(&q->use);
		return 0;
	}

M port/stil.c => port/stil.c +48 -36
@@ 28,10 28,8 @@ ilopen(Queue *q, Stream *s)
	Ipconv *ipc;
	static int ilkproc;

	/* Start il service processes */
	if(!Ipoutput) {
		Ipoutput = WR(q);
		/* This never goes away - we use this queue to send acks/rejects */
		s->opens++;
		s->inuse++;
	}


@@ 57,6 55,13 @@ ilopen(Queue *q, Stream *s)
void
ilclose(Queue *q)
{
	Ipconv *s;

	s = (Ipconv *)(q->ptr);
	qlock(s);
	s->ref--;
	qunlock(s);
	s->readq = 0;
}

void


@@ 74,7 79,6 @@ iloput(Queue *q, Block *bp)

	switch(ipc->ilctl.state) {
	case Ilclosed:
	case Ilsyncee:
	case Illistening:
	case Ilclosing:
		error(Ehungup);


@@ 123,7 127,6 @@ iloput(Queue *q, Block *bp)
		hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE));

	ilackq(ic, bp);

	PUTNEXT(q, bp);
}



@@ 135,14 138,11 @@ ilackq(Ilcb *ic, Block *bp)
	/* Enqueue a copy on the unacked queue in case this one gets lost */
	np = copyb(bp, blen(bp));

	if(ic->unacked) {
	if(ic->unacked)
		ic->unackedtail->next = np;
		ic->unackedtail = np;
	}
	else {
	else 
		ic->unacked = np;
		ic->unackedtail = np;
	}
	ic->unackedtail = np;
	np->next = 0;
}



@@ 158,6 158,7 @@ ilackto(Ilcb *ic, ulong ackto)
			break;	
		bp = ic->unacked;
		ic->unacked = bp->next;
		bp->next = 0;
		freeb(bp);
	}
}


@@ 172,7 173,7 @@ void
ilrcvmsg(Ipconv *ipc, Block *bp)
{
	Ilhdr *ih;
	int plen;
	int plen, illen;
	Ipconv *s, *etab, *new;
	short sp, dp;
	Ipaddr dst;


@@ 183,7 184,11 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
	if(plen < IL_EHSIZE+IL_HDRSIZE)
		goto drop;

	if(ilcksum && ptcl_csum(bp, IL_EHSIZE, plen) != 0) {
	illen = nhgets(ih->illen);
	if(illen+IL_EHSIZE > plen)
		goto drop;

	if(ilcksum && ptcl_csum(bp, IL_EHSIZE, illen) != 0) {
		print("il: cksum error\n");
		goto drop;
	}


@@ 192,28 197,26 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
	dp = nhgets(ih->ilsrc);
	dst = nhgetl(ih->src);

print("got packet from %d.%d.%d.%d %d %d\n", fmtaddr(dst), sp, dp);

	etab = &ipc[conf.ip];
	for(s = ipc; s < etab; s++) {
		if(s->psrc == sp && s->pdst == dp && s->dst == dst) {
			ilprocess(s, ih, bp);
			return;
		}
			
	}

	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 && s->pdst == 0 && s->dst == 0) {
			/* Do the listener stuff */
			new = ipincoming(ipc);
			if(new == 0)
				goto reset;
			if(ih->iltype != Ilsync)
				goto reset;

			new->newcon = 1;
			new->ipinterface = s->ipinterface;


@@ 243,7 246,8 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
	Block *nb;
	Ilcb *ic;
	Ilhdr *oh;
	ulong id, ack, oid;
	ulong id, ack, oid, dlen;
	int sendack = 0;

	id = nhgetl(h->ilid);
	ack = nhgetl(h->ilack);


@@ 264,8 268,8 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
		break;
	case Ilsyncer:
		if(h->iltype == Ilsync && ic->start == ack) {
			ic->recvd = id;
			ilsendctl(s, 0, Ilack, 0);
			ic->recvd = id+1;
			sendack = 1;
			ic->state = Ilestablished;
		}
		break;


@@ 288,6 292,7 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
		freeb(bp);
		break;
	case Ildataquery:
		sendack = 1;
	case Ildata:
		ilackto(&s->ilctl, ack);
		switch(s->ilctl.state) {


@@ 301,7 306,8 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
				iloutoforder(s, h, bp);
			else {
				s->ilctl.recvd++;
				bp->rptr += IL_EHSIZE+IL_HDRSIZE;
				dlen = nhgets(h->illen)-IL_HDRSIZE;
				bp = btrim(bp, IL_EHSIZE+IL_HDRSIZE, dlen);
				PUTNEXT(s->readq, bp);
			}
		}


@@ 319,7 325,7 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
	}

	/* Process out of order packets */
	if(ic->state == Ilestablished) {
	if(ic->state == Ilestablished && s->readq) {
		while(ic->outoforder) {
			bp = ic->outoforder;
			oh = (Ilhdr*)bp->rptr;


@@ 335,11 341,18 @@ print("recvd = %d outoforder = %d\n", ic->recvd, oid);
print("outoforder %d\n", oid);
				ic->recvd++;
				ic->outoforder = bp->next;
				bp->rptr += IL_EHSIZE+IL_HDRSIZE;
				bp->next = 0;
				dlen = nhgets(oh->illen)-IL_HDRSIZE;
				bp = btrim(bp, IL_EHSIZE+IL_HDRSIZE, dlen);
				PUTNEXT(s->readq, bp);
			}
		}
	}

	if(sendack)
		ilsendctl(s, 0, Ilack, 1);

	print("revd = %d sent = %d\n", ic->recvd, ic->sent);
}




@@ 352,23 365,22 @@ iloutoforder(Ipconv *s, Ilhdr *h, Block *bp)
	uchar *lid;

	ic = &s->ilctl;

	if(ic->outoforder == 0) {
		ic->outoforder = bp;
		bp->next = 0;
		return;
	}

	id = nhgetl(h->id);
	l = &ic->outoforder;
	for(f = *l; f; f = f->next) {
		lid = ((Ilhdr*)(bp->rptr))->ilid;
		if(id < nhgetl(lid))
			break;
		l = &f->next;
	else {
		id = nhgetl(h->id);
		l = &ic->outoforder;
		for(f = *l; f; f = f->next) {
			lid = ((Ilhdr*)(bp->rptr))->ilid;
			if(id > nhgetl(lid))
				break;
			l = &f->next;
		}
		bp->next = *l;
		*l = bp;
	}
	bp->next = *l;
	*l = bp;
}

void

M port/tcpinput.c => port/tcpinput.c +13 -67
@@ 39,7 39,6 @@ tcp_input(Ipconv *ipc, Block *bp)
	Tcphdr *h;
	Tcp seg;
	int hdrlen;	
	Block *oobbp;
	Ipaddr source, dest;
	char tos;
	ushort length;


@@ 293,22 292,9 @@ tcp_input(Ipconv *ipc, Block *bp)
		}

		if ((seg.flags&URG) && seg.up) {
			DPRINT("tcpin: oob: up = %u seq = %u rcv.up = %u\n",
			       seg.up, seg.seq, tcb->rcv.up);
			if (seq_gt(seg.up + seg.seq, tcb->rcv.up)) {
				tcb->rcv.up = seg.up + seg.seq;
				tcb->oobflags &= ~(TCPOOB_HAVEDATA|TCPOOB_HADDATA);
				extract_oob(&bp, &oobbp, &seg);
				if (oobbp) {
					DPRINT("tcpin: oob delivered\n");
					appendb(&tcb->rcvoobq, oobbp);
					tcb->rcvoobcnt += blen(oobbp);
					tcb->oobmark = tcb->rcvcnt;
					tcb->oobflags |= TCPOOB_HAVEDATA;
#ifdef NOTIFY
					urg_signal(s);
#endif
				}
				copyupb(&bp, 0, seg.up);
			}
		} 
		else if (seq_gt(tcb->rcv.nxt, tcb->rcv.up))


@@ 386,7 372,7 @@ tcp_input(Ipconv *ipc, Block *bp)
				goto gotone;
		}
		break;
gotone:;
		gotone:;
	}
output:
	tcp_output(s);


@@ 490,9 476,10 @@ void
update(Ipconv *s, Tcp *seg)
{
	ushort acked;
	ushort oobacked;
	ushort expand;
	Tcpctl *tcb = &s->tcpctl;
	int rtt;
	int abserr;

	if(seq_gt(seg->ack, tcb->snd.nxt)) {
		tcb->flags |= FORCE;


@@ 512,7 499,6 @@ update(Ipconv *s, Tcp *seg)
		return;	

	acked = seg->ack - tcb->snd.una;

	if(tcb->cwind < tcb->snd.wnd) {
		if(tcb->cwind < tcb->ssthresh)
			expand = MIN(acked,tcb->mss);


@@ 521,25 507,19 @@ update(Ipconv *s, Tcp *seg)

		if(tcb->cwind + expand < tcb->cwind)
			expand = 65535 - tcb->cwind;

		if(tcb->cwind + expand > tcb->snd.wnd)
			expand = tcb->snd.wnd - tcb->cwind;

		if(expand != 0)
			tcb->cwind += expand;

	}

	/* Round trip time estimation */
	if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack, tcb->rttseq)) {
		stop_timer(&tcb->rtt_timer);
		if(!(tcb->flags & RETRAN)) {
			int rtt;	/* measured round trip time */
			int abserr;	/* abs(rtt - srtt) */

			rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
			rtt *= MSPTICK;	

			if(rtt > tcb->srtt &&
			  (tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED))
				tcb->srtt = rtt;


@@ 556,28 536,16 @@ update(Ipconv *s, Tcp *seg)
	}

	/* If we're waiting for an ack of our SYN, note it and adjust count */
	if(!(tcb->flags & SYNACK)){
	if((tcb->flags & SYNACK) == 0){
		tcb->flags |= SYNACK;
		acked--;
		tcb->sndcnt--;
	}

	/* Acking some oob data if relevant */
	if(tcb->sndoobq && seq_ge(tcb->snd.up,tcb->snd.una) &&
	   seq_gt(seg->ack, tcb->snd.up)) {
		oobacked = seg->ack - tcb->snd.up;
		acked -= oobacked;
		copyupb(&tcb->sndoobq, 0, oobacked);
		tcb->sndoobcnt -= oobacked;
		DPRINT("update: oobacked = %d\n", oobacked);
	}

	copyupb(&tcb->sndq, 0, acked);

	/* This will include the FIN if there is one */
	tcb->sndcnt -= acked;
	tcb->snd.una = seg->ack;
	/* If ack includes some out-of-band data then update urgent pointer */
	if (seq_gt(seg->ack, tcb->snd.up))
		tcb->snd.up = seg->ack;



@@ 588,9 556,6 @@ update(Ipconv *s, Tcp *seg)
	if(tcb->snd.una != tcb->snd.nxt)
		start_timer(&tcb->timer);

	/* If retransmissions have been occurring, make sure the
	 * send pointer doesn't repeat ancient history
	 */
	if(seq_lt(tcb->snd.ptr, tcb->snd.una))
		tcb->snd.ptr = tcb->snd.una;



@@ 605,8 570,7 @@ update(Ipconv *s, Tcp *seg)
int
in_window(Tcpctl *tcb, int seq)
{
	return seq_within(seq, tcb->rcv.nxt, 
			 (int)(tcb->rcv.nxt+tcb->rcv.wnd-1));
	return seq_within(seq, tcb->rcv.nxt, (int)(tcb->rcv.nxt+tcb->rcv.wnd-1));
}

void


@@ 629,7 593,6 @@ proc_syn(Ipconv *s, char tos, Tcp *seg)
		tcb->mss = seg->mss;

	tcb->max_snd = seg->wnd;

	if((mtu = s->ipinterface->maxmtu) != 0) {
		mtu -= TCP_HDRSIZE + TCP_EHSIZE + TCP_PHDRSIZE; 
		tcb->cwind = tcb->mss = MIN(mtu, tcb->mss);


@@ 677,8 640,7 @@ add_reseq(Tcpctl *tcb, char tos, Tcp *seg, Block *bp, ushort length)
	} 
	else {
		for(;;){
			if(rp1->next == 0 ||
			   seq_lt(seg->seq, rp1->next->seg.seq)) {
			if(rp1->next == 0 || seq_lt(seg->seq, rp1->next->seg.seq)) {
				rp->next = rp1->next;
				rp1->next = rp;
				break;


@@ 688,7 650,6 @@ add_reseq(Tcpctl *tcb, char tos, Tcp *seg, Block *bp, ushort length)
	}
}


void
get_reseq(Tcpctl *tcb, char *tos, Tcp *seg, Block **bp, ushort *length)
{


@@ 729,7 690,8 @@ trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
	if(tcb->rcv.wnd == 0) {
		if(seg->seq == tcb->rcv.nxt && len == 0)
			return 0;
	} else {
	}
	else {
		/* Some part of the segment must be in the window */
		if(in_window(tcb,seg->seq)) {
			accept++;


@@ 771,7 733,7 @@ trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
		}
	}
	excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
	if(excess > 0){
	if(excess > 0) {
		tcb->rerecv += excess;
		*length -= excess;
		nbp = copyb(*bp, *length);


@@ 782,19 744,6 @@ trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
	return 0;
}

void
extract_oob(Block **bp, Block **oobbp, Tcp *seg)

{
	DPRINT("extract_oob: size = %u\n", seg->up);

	if (*oobbp = allocb(seg->up))
		(*oobbp)->wptr = (*oobbp)->wptr +
			         copyupb(bp, (*oobbp)->rptr, seg->up);
	else
		copyupb(bp, 0, seg->up);
}

int
copyupb(Block **bph, uchar *data, int count)
{


@@ 821,7 770,6 @@ copyupb(Block **bph, uchar *data, int count)
			freeb(bp);
		}
	}

	return bytes;
}



@@ 949,7 897,6 @@ close_self(Ipconv *s, int reason)

	tcb->reseq = 0;
	s->err = reason;

	setstate(s, CLOSED);
}



@@ 968,7 915,8 @@ seq_within(int x, int low, int high)
	if(low <= high){
		if(low <= x && x <= high)
			return 1;
	} else {
	}
	else {
		if(low >= x && x >= high)
			return 1;
	}


@@ 1007,7 955,6 @@ setstate(Ipconv *s, char newstate)

	oldstate = tcb->state;
	tcb->state = newstate;

	state_upcall(s, oldstate, newstate);
}



@@ 1107,7 1054,7 @@ ntohtcp(Tcp *tcph, Block **bpp)
	for(optr = h->tcpopt, i = TCP_HDRSIZE; i < hdrlen;) {
		switch(*optr++){
		case EOL_KIND:
			goto eol;
			return hdrlen;
		case NOOP_KIND:
			i++;
			break;


@@ 1119,6 1066,5 @@ ntohtcp(Tcp *tcph, Block **bpp)
			break;
		}
	}
eol:
	return hdrlen;
}

M port/tcpoutput.c => port/tcpoutput.c +9 -42
@@ 8,19 8,16 @@
#include 	"ipdat.h"

extern int tcpdbg;
#define DPRINT if(tcpdbg) print
extern ushort tcp_mss;
int tcptimertype = 0;


#define DPRINT if(tcpdbg) print

void
tcp_output(Ipconv *s)
{
	Block *hbp,*dbp, *sndq;
	ushort ssize, dsize, usable, sent, oobsent;
	ushort ssize, dsize, usable, sent;
	int qlen;
	char doing_oob;	
	Tcphdr ph;
	Tcp seg;
	Tcpctl *tcb;


@@ 32,29 29,11 @@ tcp_output(Ipconv *s)
	case CLOSED:
		return;
	}

	for(;;){
		if (tcb->sndoobq) {
			/* We have pending out-of-band data - use it */
			qlen = tcb->sndoobcnt;
			oobsent = tcb->snd.ptr - tcb->snd.up;
			if (oobsent >= qlen) {
				oobsent = qlen;
				goto normal;
			}
			sndq = tcb->sndoobq;
			sent = oobsent;
			doing_oob = 1;
			DPRINT("tcp_out: oob: qlen = %lux sent = %lux\n",
						qlen, sent);
		} else {
			oobsent = 0;
			normal:
			qlen = tcb->sndcnt;
			sent = tcb->snd.ptr - tcb->snd.una - oobsent;
			sndq = tcb->sndq;
			doing_oob = 0;
			DPRINT("tcp_out: norm: qlen = %lux sent = %lux\n", qlen, sent);
		}
		qlen = tcb->sndcnt;
		sent = tcb->snd.ptr - tcb->snd.una;
		sndq = tcb->sndq;

		/* Don't send anything else until our SYN has been acked */
		if(sent != 0 && !(tcb->flags & SYNACK))


@@ 78,16 57,10 @@ tcp_output(Ipconv *s)
		ssize = MIN(qlen - sent, usable);
		ssize = MIN(ssize, tcb->mss);
		dsize = ssize;

		if (!doing_oob)
			seg.up = 0;
		else {
			seg.up = ssize;
			DPRINT("tcp_out: oob seg.up = %d\n", seg.up);
		}
		seg.up = 0;

		DPRINT("tcp_out: ssize = %lux\n", ssize);
		if(ssize == 0 && !(tcb->flags & FORCE))
		if(ssize == 0 && (tcb->flags & FORCE) == 0)
			break;

		/* Stop ack timer if one will be piggy backed on data */


@@ 110,7 83,6 @@ tcp_output(Ipconv *s)
			if(tcb->snd.ptr == tcb->iss){
				seg.flags |= SYN;
				dsize--;
				/* Also send MSS */
				seg.mss = tcp_mss;
			}
			break;


@@ 119,11 91,6 @@ tcp_output(Ipconv *s)
		seg.ack = tcb->last_ack = tcb->rcv.nxt;
		seg.wnd = tcb->rcv.wnd;

		if (doing_oob) {
			DPRINT("tcp_out: Setting URG (up = %u)\n", seg.up);
			seg.flags |= URG;
		}

		/* Now try to extract some data from the send queue.
		 * Since SYN and FIN occupy sequence space and are reflected
		 * in sndcnt but don't actually sit in the send queue,


@@ 259,7 226,7 @@ void
tcp_acktimer(Ipconv *s)
{
	Tcpctl *tcb = &s->tcpctl;

print("Acktimer!\n");
	qlock(tcb);
	tcb->flags |= FORCE;
	tcprcvwin(s);

M ss/main.c => ss/main.c +1 -1
@@ 266,7 266,7 @@ lancesetup(Lance *lp)
		lp->ea[i] = *cp++;
	kunmap(k);

	lp->lognrrb = 5;
	lp->lognrrb = 7;
	lp->logntrb = 5;
	lp->nrrb = 1<<lp->lognrrb;
	lp->ntrb = 1<<lp->logntrb;