Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/ip/il.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname ip/il.c 1997/0327
## diff -e /dev/null /n/emeliedump/1997/0327/sys/src/brazil/ip/il.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#include	"ip.h"

char	*ilstates[] = 
{ 
	"Closed",
	"Syncer",
	"Syncee",
	"Established",
	"Listening",
	"Closing" 
};

char	*iltype[] = 
{	
	"sync",
	"data",
	"dataquerey",
	"ack",
	"querey",
	"state",
	"close" 
};
static char *etime = "connection timed out";

enum				/* Packet types */
{
	Ilsync,
	Ildata,
	Ildataquery,
	Ilack,
	Ilquerey,
	Ilstate,
	Ilclose,
};

enum				/* Connection state */
{
	Ilclosed,
	Ilsyncer,
	Ilsyncee,
	Ilestablished,
	Illistening,
	Ilclosing,
};

typedef struct Ilcb Ilcb;
struct Ilcb			/* Control block */
{
	int	state;		/* Connection state */
	Conv	*conv;
	QLock	ackq;		/* Unacknowledged queue */
	Block	*unacked;
	Block	*unackedtail;
	QLock	outo;		/* Out of order packet queue */
	Block	*outoforder;
	ulong	next;		/* Id of next to send */
	ulong	recvd;		/* Last packet received */
	ulong	start;		/* Local start id */
	ulong	rstart;		/* Remote start id */
	int	timeout;	/* Time out counter */
	int	slowtime;	/* Slow time counter */
	int	fasttime;	/* Retransmission timer */
	int	acktime;	/* Acknowledge timer */
	int	querytime;	/* Query timer */
	int	deathtime;	/* Time to kill connection */
	int	rtt;		/* Average round trip time */
	ulong	rttack;		/* The ack we are waiting for */
	ulong	ackms;		/* Time we issued */
	int	window;		/* Maximum receive window */
};

enum
{
	IL_IPSIZE 	= 20,
	IL_HDRSIZE	= 18,	
	IL_LISTEN	= 0,
	IL_CONNECT	= 1,
	IP_ILPROTO	= 40,
};

typedef struct Ilhdr Ilhdr;
struct Ilhdr
{
	byte	vihl;		/* Version and header length */
	byte	tos;		/* Type of service */
	byte	length[2];	/* packet length */
	byte	id[2];		/* Identification */
	byte	frag[2];	/* Fragment information */
	byte	ttl;		/* Time to live */
	byte	proto;		/* Protocol */
	byte	cksum[2];	/* Header checksum */
	byte	src[4];		/* Ip source */
	byte	dst[4];		/* Ip destination */
	byte	ilsum[2];	/* Checksum including header */
	byte	illen[2];	/* Packet length */
	byte	iltype;		/* Packet type */
	byte	ilspec;		/* Special */
	byte	ilsrc[2];	/* Src port */
	byte	ildst[2];	/* Dst port */
	byte	ilid[4];	/* Sequence id */
	byte	ilack[4];	/* Acked sequence */
};

/* Always Acktime < Fasttime < Slowtime << Ackkeepalive */
enum
{
	Seconds		= 1000,
	Iltickms 	= 100,		/* time base */

	Ackkeepalive	= 6000*Iltickms,
	Acktime		= 2*Iltickms,	/* max time twixt message rcvd & ack sent */

	Slowtime 	= 90*Seconds,	/* min time waiting for an ack before hangup */
	Fasttime 	= 4*Iltickms,	/* min time between rexmit */
	Querytime	= 5*Seconds,	/* time between subsequent queries */
	Keepalivetime	= 60*Seconds,	/* time before first query */
	Deathtime	= 120*Seconds,	/* time between first query and hangup */

	Defaultwin	= 20,
	ILgain		= 8,
};

void	ilrcvmsg(Conv*, Block*);
void	ilsendctl(Conv*, Ilhdr*, int, ulong, ulong);
void	ilackq(Ilcb*, Block*);
void	ilprocess(Conv*, Ilhdr*, Block*);
void	ilpullup(Conv*);
void	ilhangup(Conv*, char*);
void	ilfreeq(Ilcb*);
void	ilrexmit(Ilcb*);
void	ilbackoff(Ilcb*);
void	iltimers(Ilcb*);
char*	ilstart(Conv*, int, int);
void	ilackproc();
void	iloutoforder(Conv*, Ilhdr*, Block*);
void	iliput(Block*);
void	iladvise(Block*, char*);

#define DBG(x)	if((logmask & Logilmsg) && (iponly == 0 || x == iponly))netlog

	Proto	il;
	int 	ilcksum = 1;
static 	int 	initseq = 25001;
extern	Fs	fs;

static char*
ilconnect(Conv *c, char **argv, int argc)
{
	char *e;

	e = ilstart(c, IL_CONNECT, 20);
	if(e != nil)
		return e;
	return Fsstdconnect(c, argv, argc);
}

int
ilstate(char **msg, Conv *c)
{
	Ilcb *ic;
	int isclose;

	ic = (Ilcb*)(c->ptcl);

	isclose = 0;
	if(ic->state == Ilclosed) 
		isclose = 1;

	*msg = ilstates[ic->state];
	return isclose;
}

/* called with c locked */
static void
ilannounce(Conv *c)
{
	char *e;

	e = ilstart(c, IL_LISTEN, 20);
	Fsconnected(&fs, c, e);
}

static void
ilclose(Conv *c)
{
	Ilcb *ic;

	ic = (Ilcb*)c->ptcl;

	qclose(c->rq);
	qclose(c->wq);
	qclose(c->eq);

	switch(ic->state) {
	case Ilclosing:
	case Ilclosed:
		break;
	case Ilsyncer:
	case Ilsyncee:
	case Ilestablished:
		ilfreeq(ic);
		ic->state = Ilclosing;
		ilsendctl(c, nil, Ilclose, ic->next, ic->recvd);
		break;
	case Illistening:
		ic->state = Ilclosed;
		c->laddr = 0;
		c->lport = 0;
		break;
	}
	unlock(c);
}

void
ilkick(Conv *c, int l)
{
	Ilhdr *ih;
	Ilcb *ic;
	int dlen;
	ulong id;
	Block *bp;

	USED(l);

	ic = (Ilcb*)c->ptcl;

	bp = qget(c->wq);
	if(bp == nil)
		return;

	switch(ic->state) {
	case Ilclosed:
	case Illistening:
	case Ilclosing:
		freeblist(bp);
		qhangup(c->rq, nil);
		return;
	}

	dlen = blocklen(bp);

	/* Make space to fit il & ip */
	bp = padblock(bp, IL_IPSIZE+IL_HDRSIZE);
	ih = (Ilhdr *)(bp->rp);

	/* Ip fields */
	ih->frag[0] = 0;
	ih->frag[1] = 0;
	hnputl(ih->dst, c->raddr);
	hnputl(ih->src, c->laddr);
	ih->proto = IP_ILPROTO;

	/* Il fields */
	hnputs(ih->illen, dlen+IL_HDRSIZE);
	hnputs(ih->ilsrc, c->lport);
	hnputs(ih->ildst, c->rport);

	qlock(&ic->ackq);
	id = ic->next++;
	hnputl(ih->ilid, id);

	hnputl(ih->ilack, ic->recvd);
	ih->iltype = Ildata;
	ih->ilspec = 0;
	ih->ilsum[0] = 0;
	ih->ilsum[1] = 0;

	/* Checksum of ilheader plus data (not ip & no pseudo header) */
	if(ilcksum)
		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, dlen+IL_HDRSIZE));

	ilackq(ic, bp);
	qunlock(&ic->ackq);

	/* Start the round trip timer for this packet if the timer is free */
	if(ic->rttack == 0) {
		ic->rttack = id;
		ic->ackms = msec;
	}
	ic->acktime = Ackkeepalive;

	ipoput(bp, 0, c->ttl);
}

static void
ilcreate(Conv *c)
{
	c->rq = qopen(64*1024, 0, 0, c);
	c->wq = qopen(64*1024, 0, 0, 0);
}

void
ilinit(Fs *fs)
{
	il.name = "il";
	il.kick = ilkick;
	il.connect = ilconnect;
	il.announce = ilannounce;
	il.state = ilstate;
	il.create = ilcreate;
	il.close = ilclose;
	il.rcv = iliput;
	il.ctl = nil;
	il.advise = iladvise;
	il.ipproto = IP_ILPROTO;
	il.nc = Nchans;
	il.ptclsize = sizeof(Ilcb);

	kproc("ilack", ilackproc, 0);

	Fsproto(fs, &il);
}

void
ilackq(Ilcb *ic, Block *bp)
{
	Block *np;

	/* Enqueue a copy on the unacked queue in case this one gets lost */
	np = copyblock(bp, blocklen(bp));
	if(ic->unacked)
		ic->unackedtail->list = np;
	else {
		/* Start timer since we may have been idle for some time */
		iltimers(ic);
		ic->unacked = np;
	}
	ic->unackedtail = np;
	np->list = nil;
}

void
ilackto(Ilcb *ic, ulong ackto)
{
	Ilhdr *h;
	Block *bp;
	ulong id, t;

	if(ic->rttack == ackto) {
		t = msec - ic->ackms;
		/* Guard against the ulong zero wrap of MACHP(0)->ticks */
		if(t < 120000)
			ic->rtt = (ic->rtt*(ILgain-1)+t)/ILgain;
		if(ic->rtt < Iltickms)
			ic->rtt = Iltickms;
	}

	/* Cancel if we lost the packet we were interested in */
	if(ic->rttack <= ackto)
		ic->rttack = 0;

	qlock(&ic->ackq);
	while(ic->unacked) {
		h = (Ilhdr *)ic->unacked->rp;
		id = nhgetl(h->ilid);
		if(ackto < id)
			break;

		bp = ic->unacked;
		ic->unacked = bp->list;
		bp->list = nil;
		freeblist(bp);
	}
	qunlock(&ic->ackq);
}

void
iliput(Block *bp)
{
	char *st;
	Ilcb *ic;
	Ilhdr *ih;
	Ipaddr dst;
	ushort sp, dp, csum;
	int plen, illen;
	Conv *s, **p, *new, *spec, *gen;

	ih = (Ilhdr *)bp->rp;
	plen = blocklen(bp);
	if(plen < IL_IPSIZE+IL_HDRSIZE){
		netlog(Logil, "il: hlenerr\n");
		il.hlenerr++;
		goto raise;
	}

	illen = nhgets(ih->illen);
	if(illen+IL_IPSIZE > plen){
		netlog(Logil, "il: lenerr\n");
		il.lenerr++;
		goto raise;
	}

	sp = nhgets(ih->ildst);
	dp = nhgets(ih->ilsrc);
	dst = nhgetl(ih->src);

	if(ilcksum && (csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) {
		if(ih->iltype < 0 || ih->iltype > Ilclose)
			st = "?";
		else
			st = iltype[ih->iltype];
		il.csumerr++;
		netlog(Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %i/%d->%d)\n",
			csum, st, nhgetl(ih->ilid), nhgetl(ih->ilack), dst, sp, dp);
		goto raise;
	}

	for(p = il.conv; *p; p++) {
		s = *p;
		if(s->lport == sp && s->rport == dp && s->raddr == dst) {
			ilprocess(s, ih, bp);
			return;
		}
	}

	if(ih->iltype != Ilsync){
		if(ih->iltype < 0 || ih->iltype > Ilclose)
			st = "?";
		else
			st = iltype[ih->iltype];
		netlog(Logil, "il: no channel, pkt(%s id %lud ack %lud %i/%ud->%ud)\n",
			st, nhgetl(ih->ilid), nhgetl(ih->ilack), dst, sp, dp); 
		goto raise;
	}

	gen = nil;
	spec = nil;
	for(p = il.conv; *p; p++) {
		s = *p;
		ic = (Ilcb*)s->ptcl;
		if(ic->state != Illistening)
			continue;

		if(s->rport == 0 && s->raddr == 0) {
			if(s->lport == sp) {
				spec = s;
				break;
			}
			if(s->lport == 0)
				gen = s;
		}
	}

	if(spec)
		s = spec;
	else
	if(gen)
		s = gen;
	else
		goto raise;

	new = Fsnewcall(&fs, s, nhgetl(ih->src), dp, nhgetl(ih->dst), sp);
	if(new == nil){
		netlog(Logil, "il: bad newcall %i/%ud->%ud\n", dst, sp, dp);
		ilsendctl(nil, ih, Ilclose, 0, nhgetl(ih->ilid));
		goto raise;
	}

	ic = (Ilcb*)new->ptcl;
	ic->conv = new;
	ic->state = Ilsyncee;
	initseq += msec;
	ic->start = initseq & 0xffffff;
	ic->next = ic->start+1;
	ic->recvd = 0;
	ic->rstart = nhgetl(ih->ilid);
	ic->slowtime = Slowtime;
	ic->rtt = Iltickms;
	ic->querytime = Keepalivetime;
	ic->deathtime = Deathtime;
	ic->window = Defaultwin;

	ilprocess(new, ih, bp);
	return;

raise:
	freeblist(bp);
	return;
}

int	sdataquery;	/* temporary counters for measuring */
int	squery;

void
_ilprocess(Conv *s, Ilhdr *h, Block *bp)
{
	Ilcb *ic;
	ulong id, ack;

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

	ic = (Ilcb*)s->ptcl;

	ic->querytime = Keepalivetime;
	ic->deathtime = Deathtime;

	switch(ic->state) {
	default:
		netlog(Logil, "il: unknown state %d\n", ic->state);
	case Ilclosed:
		freeblist(bp);
		break;
	case Ilsyncer:
		switch(h->iltype) {
		default:
			break;
		case Ilsync:
			if(ack != ic->start)
				ilhangup(s, "connection rejected");
			else {
				ic->recvd = id;
				ic->rstart = id;
				ilsendctl(s, nil, Ilack, ic->next, ic->recvd);
				ic->state = Ilestablished;
				Fsconnected(&fs, s, nil);
				ilpullup(s);
				iltimers(ic);
			}
			break;
		case Ilclose:
			if(ack == ic->start)
				ilhangup(s, "remote close");
			break;
		}
		freeblist(bp);
		break;
	case Ilsyncee:
		switch(h->iltype) {
		default:
			break;
		case Ilsync:
			if(id != ic->rstart || ack != 0)
				ic->state = Ilclosed;
			else {
				ic->recvd = id;
				ilsendctl(s, nil, Ilsync, ic->start, ic->recvd);
				iltimers(ic);
			}
			break;
		case Ilack:
			if(ack == ic->start) {
				ic->state = Ilestablished;
				ilpullup(s);
				iltimers(ic);
			}
			break;
		case Ilclose:
			if(ack == ic->start)
				ilhangup(s, "remote close");
			break;
		}
		freeblist(bp);
		break;
	case Ilestablished:
		switch(h->iltype) {
		case Ilsync:
			if(id != ic->rstart)
				ilhangup(s, "remote close");
			else {
				ilsendctl(s, nil, Ilack, ic->next, ic->rstart);
				iltimers(ic);
			}
			freeblist(bp);	
			break;
		case Ildata:
			iltimers(ic);
			ilackto(ic, ack);
			ic->acktime = Acktime;
			iloutoforder(s, h, bp);
			ilpullup(s);
			break;
		case Ildataquery:
sdataquery++;
			iltimers(ic);
			ilackto(ic, ack);
			ic->acktime = Acktime;
			iloutoforder(s, h, bp);
			ilpullup(s);
			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd);
			break;
		case Ilack:
			ilackto(ic, ack);
			iltimers(ic);
			freeblist(bp);
			break;
		case Ilquerey:
squery++;
			ilackto(ic, ack);
			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd);
			iltimers(ic);
			freeblist(bp);
			break;
		case Ilstate:
			ilackto(ic, ack);
			ilrexmit(ic);
			iltimers(ic);
			freeblist(bp);
			break;
		case Ilclose:
			freeblist(bp);
			if(ack < ic->start || ack > ic->next) 
				break;
			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd);
			ic->state = Ilclosing;
			ilfreeq(ic);
			iltimers(ic);
			break;
		}
		break;
	case Illistening:
		freeblist(bp);
		break;
	case Ilclosing:
		switch(h->iltype) {
		case Ilclose:
			ic->recvd = id;
			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd);
			if(ack == ic->next)
				ilhangup(s, nil);
			iltimers(ic);
			break;
		default:
			break;
		}
		freeblist(bp);
		break;
	}
}

void
ilrexmit(Ilcb *ic)
{
	Ilhdr *h;
	Block *nb;

	nb = nil;
	qlock(&ic->ackq);
	if(ic->unacked)
		nb = copyblock(ic->unacked, blocklen(ic->unacked));
	qunlock(&ic->ackq);

	if(nb == nil)
		return;

	h = (Ilhdr*)nb->rp;
/*	netlog(Logil, "il: rxmit %ux %d\n", nb, nhgetl(h->ilid)); */

	h->iltype = Ildataquery;
	hnputl(h->ilack, ic->recvd);
	h->ilsum[0] = 0;
	h->ilsum[1] = 0;
	if(ilcksum)
		hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen)));

	il.rexmit++;
	ipoput(nb, 0, ic->conv->ttl);
}

/* DEBUG */
void
ilprocess(Conv *s, Ilhdr *h, Block *bp)
{
	Ilcb *ic;

	ic = (Ilcb*)s->ptcl;

	USED(ic);
	DBG(s->raddr)(Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ",
		ilstates[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(s->raddr)(Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next);
}

void
ilhangup(Conv *s, char *msg)
{
	Ilcb *ic;
	int callout;

	netlog(Logil, "il: hangup! %i %d/%d\n", s->raddr, s->lport, s->rport);

	ic = (Ilcb*)s->ptcl;
	callout = ic->state == Ilsyncer;
	ic->state = Ilclosed;

	qhangup(s->rq, msg);
	qhangup(s->wq, msg);

	if(callout)
		Fsconnected(&fs, s, msg);
}

void
ilpullup(Conv *s)
{
	Ilcb *ic;
	Ilhdr *oh;
	Block *bp;
	ulong oid, dlen;

	ic = (Ilcb*)s->ptcl;
	if(ic->state != Ilestablished)
		return;

	qlock(&ic->outo);
	while(ic->outoforder) {
		bp = ic->outoforder;
		oh = (Ilhdr*)bp->rp;
		oid = nhgetl(oh->ilid);
		if(oid <= ic->recvd) {
			ic->outoforder = bp->list;
			freeblist(bp);
			continue;
		}
		if(oid != ic->recvd+1)
			break;

		ic->recvd = oid;
		ic->outoforder = bp->list;

		bp->list = nil;
		dlen = nhgets(oh->illen)-IL_HDRSIZE;
		bp = trimblock(bp, IL_IPSIZE+IL_HDRSIZE, dlen);
		/*
		 * Upper levels don't know about multiple-block
		 * messages so copy all into one (yick).
		 */
		bp = concatblock(bp);
		if(bp == 0)
			panic("ilpullup");
		qpass(s->rq, bp);
	}
	qunlock(&ic->outo);
}

void
iloutoforder(Conv *s, Ilhdr *h, Block *bp)
{
	Ilcb *ic;
	byte *lid;
	Block *f, **l;
	ulong id, newid;

	ic = (Ilcb*)s->ptcl;
	bp->list = nil;

	id = nhgetl(h->ilid);
	/* Window checks */
	if(id <= ic->recvd || id > ic->recvd+ic->window) {
		netlog(Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n",
			id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport);
		freeblist(bp);
		return;
	}

	/* Packet is acceptable so sort onto receive queue for pullup */
	qlock(&ic->outo);
	if(ic->outoforder == nil)
		ic->outoforder = bp;
	else {
		l = &ic->outoforder;
		for(f = *l; f; f = f->list) {
			lid = ((Ilhdr*)(f->rp))->ilid;
			newid = nhgetl(lid);
			if(id <= newid) {
				if(id == newid) {
					qunlock(&ic->outo);
					freeblist(bp);
					return;
				}
				bp->list = f;
				*l = bp;
				qunlock(&ic->outo);
				return;
			}
			l = &f->list;
		}
		*l = bp;
	}
	qunlock(&ic->outo);
}

void
ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack)
{
	Ilhdr *ih;
	Ilcb *ic;
	Block *bp;
	int ttl;

	bp = allocb(IL_IPSIZE+IL_HDRSIZE);
	bp->wp += IL_IPSIZE+IL_HDRSIZE;

	ih = (Ilhdr *)(bp->rp);

	/* Ip fields */
	ih->proto = IP_ILPROTO;
	hnputs(ih->illen, IL_HDRSIZE);
	ih->frag[0] = 0;
	ih->frag[1] = 0;
	if(inih) {
		hnputl(ih->dst, nhgetl(inih->src));
		hnputl(ih->src, nhgetl(inih->dst));
		hnputs(ih->ilsrc, nhgets(inih->ildst));
		hnputs(ih->ildst, nhgets(inih->ilsrc));
		hnputl(ih->ilid, nhgetl(inih->ilack));
		hnputl(ih->ilack, nhgetl(inih->ilid));
		ttl = MAXTTL;
	}
	else {
		hnputl(ih->dst, ipc->raddr);
		hnputl(ih->src, ipc->laddr);
		hnputs(ih->ilsrc, ipc->lport);
		hnputs(ih->ildst, ipc->rport);
		hnputl(ih->ilid, id);
		hnputl(ih->ilack, ack);
		ic = (Ilcb*)ipc->ptcl;
		ic->acktime = Ackkeepalive;
		ttl = ipc->ttl;
	}
	ih->iltype = type;
	ih->ilspec = 0;
	ih->ilsum[0] = 0;
	ih->ilsum[1] = 0;

	if(ilcksum)
		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));

	if(ipc){
		DBG(ipc->raddr)(Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",
		iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), 
		nhgets(ih->ilsrc), nhgets(ih->ildst));
	}

	ipoput(bp, 0, ttl);
}

void
ilackproc()
{
	Ilcb *ic;
	Conv **s, *p;
	static Rendez ilr;

loop:
	tsleep(&ilr, return0, 0, Iltickms);
	for(s = il.conv; s && *s; s++) {
		p = *s;
		ic = (Ilcb*)p->ptcl;

		ic->timeout += Iltickms;
		switch(ic->state) {
		case Ilclosed:
		case Illistening:
			break;
		case Ilclosing:
			if(ic->timeout >= ic->fasttime) {
				ilsendctl(p, nil, Ilclose, ic->next, ic->recvd);
				ilbackoff(ic);
			}
			if(ic->timeout >= ic->slowtime)
				ilhangup(p, nil);
			break;
		case Ilsyncee:
		case Ilsyncer:
			if(ic->timeout >= ic->fasttime) {
				ilsendctl(p, nil, Ilsync, ic->start, ic->recvd);
				ilbackoff(ic);
			}
			if(ic->timeout >= ic->slowtime)
				ilhangup(p, etime);
			break;
		case Ilestablished:
			ic->acktime -= Iltickms;
			if(ic->acktime <= 0)
				ilsendctl(p, nil, Ilack, ic->next, ic->recvd);

			ic->querytime -= Iltickms;
			if(ic->querytime <= 0){
				ic->deathtime -= Querytime;
				if(ic->deathtime < 0){
					netlog(Logil, "il: hangup due to deathtime (%d) < 0 \n", ic->deathtime);
					ilhangup(p, etime);
					break;
				}
				ilsendctl(p, nil, Ilquerey, ic->next, ic->recvd);
				ic->querytime = Querytime;
			}
			if(ic->unacked == nil) {
				ic->timeout = 0;
				break;
			}
			if(ic->timeout >= ic->fasttime) {
				ilrexmit(ic);
				ilbackoff(ic);
			}
			if(ic->timeout >= ic->slowtime) {
				netlog(Logil, "il: hangup due to timeout (%d) >= slowtime (%d)\n", ic->timeout, ic->slowtime);
				ilhangup(p, etime);
				break;
			}
			break;
		}
	}
	goto loop;
}

void
ilbackoff(Ilcb *ic)
{
	if(ic->fasttime < Slowtime/2)
		ic->fasttime += Fasttime;
	else
		ic->fasttime = (ic->fasttime)*3/2;
}

char*
ilstart(Conv *c, int type, int window)
{
	char *e;
	Ilcb *ic;

	ic = (Ilcb*)c->ptcl;
	ic->conv = c;

	e = nil;

	if(ic->state != Ilclosed)
		return e;

	ic->unacked = nil;
	ic->outoforder = nil;
	ic->slowtime = Slowtime;
	ic->rtt = Iltickms;
	iltimers(ic);

	initseq += msec;
	ic->start = initseq & 0xffffff;
	ic->next = ic->start+1;
	ic->recvd = 0;
	ic->window = window;

	switch(type) {
	default:
		netlog(Logil, "il: start: type %d\n", type);
		break;
	case IL_LISTEN:
		ic->state = Illistening;
		break;
	case IL_CONNECT:
		ic->state = Ilsyncer;
		ilsendctl(c, nil, Ilsync, ic->start, ic->recvd);
		break;
	}

	return e;
}

void
ilfreeq(Ilcb *ic)
{
	Block *bp, *next;

	qlock(&ic->ackq);
	for(bp = ic->unacked; bp; bp = next) {
		next = bp->list;
		freeblist(bp);
	}
	ic->unacked = nil;
	qunlock(&ic->ackq);

	qlock(&ic->outo);
	for(bp = ic->outoforder; bp; bp = next) {
		next = bp->list;
		freeblist(bp);
	}
	ic->outoforder = nil;
	qunlock(&ic->outo);
}

void
iltimers(Ilcb *ic)
{
	ic->timeout = 0;
	ic->fasttime = (Fasttime*ic->rtt)/Iltickms;
	ic->slowtime = (Slowtime*ic->rtt)/Iltickms;
}

void
iladvise(Block *bp, char *msg)
{
	Ilhdr *h;
	Ilcb *ic;		
	Ipaddr source, dest;
	ushort psource;
	Conv *s, **p;

	h = (Ilhdr*)(bp->rp);

	dest = nhgetl(h->dst);
	source = nhgetl(h->src);
	psource = nhgets(h->ilsrc);


	/* Look for a connection, unfortunately the destination port is missing */
	for(p = il.conv; *p; p++) {
		s = *p;
		if(s->laddr == source && s->lport == psource)
		if(s->raddr == dest){
			ic = (Ilcb*)s->ptcl;
			switch(ic->state){
			case Ilsyncer:
				ilhangup(s, msg);
				break;
			}
			break;
		}
	}
	freeblist(bp);
}
.
## diffname ip/il.c 1997/0403
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/ip/il.c /n/emeliedump/1997/0403/sys/src/brazil/ip/il.c
187c
	if(e != nil)
		return e;
	Fsconnected(&fs, c, nil);

	return nil;
.
185a
	e = Fsstdannounce(c, argv, argc);
	if(e != nil);
		return e;
.
181,182c
static char*
ilannounce(Conv *c, char **argv, int argc)
.
## diffname ip/il.c 1997/0404
## diff -e /n/emeliedump/1997/0403/sys/src/brazil/ip/il.c /n/emeliedump/1997/0404/sys/src/brazil/ip/il.c
187c
	if(e != nil)
.
## diffname ip/il.c 1997/0423
## diff -e /n/emeliedump/1997/0404/sys/src/brazil/ip/il.c /n/emeliedump/1997/0423/sys/src/brazil/ip/il.c
391a
	USED(m);
.
382c
iliput(Media *m, Block *bp)
.
143c
void	iliput(Media*, Block*);
.
## diffname ip/il.c 1997/0521
## diff -e /n/emeliedump/1997/0423/sys/src/brazil/ip/il.c /n/emeliedump/1997/0521/sys/src/brazil/ip/il.c
161c
	return ilstart(c, IL_CONNECT, 20);
.
158c
	e = Fsstdconnect(c, argv, argc);
.
## diffname ip/il.c 1997/0730
## diff -e /n/emeliedump/1997/0521/sys/src/brazil/ip/il.c /n/emeliedump/1997/0730/sys/src/brazil/ip/il.c
1005,1006c
	pt = ic->delay>>LogAGain;
	pt += ic->unackedbytes/(ic->rate>>LogAGain);
	ic->fasttime = (Fasttime*pt)/Iltickms;
	ic->slowtime = (Slowtime*pt)/Iltickms;
.
1003a
	int pt;

.
961a
	ic->rexmit = 0;
.
953,954c
	ic->unackedbytes = 0;
	ilinitrtt(ic);
.
931,934c
	ic->fasttime = (ic->fasttime)*3/2;
.
671a
	ic->rexmit++;
.
483c
	ilinitrtt(ic);
.
375a
		ic->unackedbytes -= blocklen(bp);
.
356,359c
		if(t > 120000){
			/* seed connection parameters with time of first ack */
			if(ic->lrttlen < 0){
				ic->rate = (ic->rttlen/t)<<LogAGain;
				ic->delay = t<<LogAGain;
				ic->mdev = t<<LogDGain;
				ic->lrttlen = ic->rttlen;
				ic->lrtt = t;
			}

			pt = ic->rttlen/(ic->rate>>LogAGain) + (ic->delay>>LogAGain);
	
			/* mdev */
			ic->mdev += abs(t-pt) - (ic->mdev>>LogDGain);
	
			/*  fixed delay */
			if(ic->rttlen != ic->lrttlen){
				x = (ic->lrtt*ic->rttlen - t*ic->lrttlen)/(ic->rttlen-ic->lrttlen);
				ic->delay += x - (ic->delay>>LogAGain);
			}
	
			/* rate */
			if(ic->lrtt != t){
				x = (ic->lrttlen - ic->rttlen)/(ic->lrtt - t);
				ic->rate += x - (ic->rate>>LogAGain);
			}

			ic->lrtt = t;
			ic->lrttlen = ic->rttlen;
		}

		if(ic->delay < (Iltickms<<LogAGain))
			ic->delay = Iltickms<<LogAGain;
.
354c
		t = msec - ic->rttms;
.
351c
	ulong id;
	int x, t, pt;
.
346a
ilinitrtt(Ilcb *ic)
{
	ic->delay = Iltickms<<LogAGain;
	ic->mdev = Iltickms<<LogDGain;
	ic->rate = 10000<<LogAGain;		/* 10 meg ether */
	ic->lrttlen = -1;
}

void
.
343a
	ic->unackedbytes += n;
.
334c
	np = copyblock(bp, n);
.
332a
	n = blocklen(bp);

.
331a
	int n;
.
292c
		ic->rttms = msec;
		ic->rttlen = dlen + IL_IPSIZE + IL_HDRSIZE;
.
176c
	sprint(ic->buf, "%s del %d Br %d md %d una %d rex %d", ilstates[ic->state],
		ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain,
		ic->unackedbytes, ic->rexmit);
	*msg = ic->buf;
.
127c
	LogAGain	= 3,
	LogDGain	= 2,
.
76a
	int	rexmit;
	char	buf[128];
.
75c
	int	rttlen;		/* Length of rttack packet */
	ulong	rttms;		/* Time we issued rttack packet */
	int	lrtt;		/* Last rtt seen */
	int	lrttlen;	/* Length of the packet lrtt is for */
.
73c
	int	delay;		/* Average of the fixed rtt delay */
	int	rate;		/* Average byte rate */
	int	mdev;		/* Mean deviation of rtt */
.
60a
	ulong	unackedbytes;
.
## diffname ip/il.c 1997/0801
## diff -e /n/emeliedump/1997/0730/sys/src/brazil/ip/il.c /n/emeliedump/1997/0801/sys/src/brazil/ip/il.c
1063,1064c
	pt = (ic->delay>>LogAGain) + ic->unackedbytes/(ic->rate>>LogAGain) + ic->mdev;
.
393,417d
380,391c
	if(ic->rttack == ackto)
		ilrttcalc(ic);
.
378d
371a
static void
ilrttcalc(Ilcb *ic)
{
	int dlen, dt, t, pt, x;

	t = msec - ic->rttms;

	/* Guard against the ulong zero wrap of MACHP(0)->ticks */
	if(t > 120000)
		return;


	/* seed connection parameters with time of first ack */
	if(ic->lrttlen == 0){
		ic->lrttlen = ic->rttlen;
		/* account pessimisticly for clock resolution */
		if(t == 0)
			t = TK2MS(1);
		ic->lrtt = t;
		x = (ic->rttlen/t)<<LogAGain;
		if(x < AGain)
			x = AGain;
		ic->rate = x;
		ic->delay = t<<LogAGain;
		ic->mdev = t<<LogDGain;
		goto out;
	}

	dlen = ic->rttlen - ic->lrttlen;
	dt = t - ic->lrtt;

	/*  fixed delay */
	if(dlen == 0)
		x = t - ic->rttlen/(ic->rate>>LogAGain);
	else
		x = (ic->lrtt*ic->rttlen - t*ic->lrttlen)/dlen;
	if(x > 0){
		x += ic->delay - (ic->delay>>LogAGain);
		if(x < AGain)
			x = AGain;
		ic->delay = x;
	}

	/* rate */
	if(dt == 0){
		if(dlen)
			x = DefByteRate;
		else
			x = -1;
	} else
		x = dlen/dt;
	if(x > 0){
		x += ic->rate - (ic->rate>>LogAGain);
		if(x < AGain)
			x = AGain;
		ic->rate = x;
	}

	/* mdev */
	pt = ic->rttlen/(ic->rate>>LogAGain) + (ic->delay>>LogAGain);
	ic->mdev += abs(t-pt) - (ic->mdev>>LogDGain);

out:
	ic->lrtt = t;
	ic->lrttlen = ic->rttlen;
}

.
368,369c
	ic->rate = DefByteRate<<LogAGain;		/* 10 meg ether */
	ic->lrtt = 0;
	ic->lrttlen = 0;
.
136a
	DGain		= 1<<LogDGain,
	DefByteRate	= 1000,
.
135a
	AGain		= 1<<LogAGain,
.
## diffname ip/il.c 1997/0802
## diff -e /n/emeliedump/1997/0801/sys/src/brazil/ip/il.c /n/emeliedump/1997/0802/sys/src/brazil/ip/il.c
1099,1100c
	ic->fasttime = (Fasttime/Seconds)*pt;
	if(ic->fasttime > Fasttime)
		ic->fasttime = Fasttime;
	ic->slowtime = (Slowtime/Seconds)*pt;
	if(ic->slowtime > Slowtime)
		ic->slowtime = Slowtime;
.
1024c
	ic->fasttime += ic->fasttime<<1;
.
764a
	ic->rttack = 0;		/* stop counting rtt */
.
453c
	/* Cancel if we've passed the packet we were interested in */
.
438,440c
	if(rtt > ic->maxrtt)
		ic->maxrtt = rtt;
.
435,436c
	pt = ic->rttlen/(rate>>LogAGain) + (delay>>LogAGain);
	ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain);
.
420,431c
	tt = rtt - (delay>>LogAGain);
	if(tt > 0){
		rate += ic->rttlen/tt - (rate>>LogAGain);
		if(rate < AGain)
			rate = AGain;
		ic->rate = rate;
.
404,418d
387,401c
	/* guess fixed delay as rtt of small packets */
	if(ic->rttlen < 128){
		delay += rtt - (delay>>LogAGain);
		if(delay < AGain)
			delay = AGain;
		ic->delay = delay;
.
384c
	if(rtt > 120000)
.
381c
	/* add in clock resolution hack */
	rtt = (msec + TK2MS(1) - 1) - ic->rttms;
	delay = ic->delay;
	rate = ic->rate;
.
379c
	int rtt, tt, pt, delay, rate;
.
372,373d
190c
		ic->unackedbytes, ic->rexmit, ic->maxrtt);
.
188c
	sprint(ic->buf, "%s del %d Br %d md %d una %d rex %d max %d", ilstates[ic->state],
.
139c
	DefByteRate	= 1000,		/* 10 meg ether */
.
128,129c
	Slowtime 	= 90*Seconds,	/* max time waiting for an ack before hangup */
	Fasttime 	= 4*Seconds,	/* max time between rexmit */
.
80,81d
76a
	int	maxrtt;		/* largest rtt seen */
.
## diffname ip/il.c 1997/0803
## diff -e /n/emeliedump/1997/0802/sys/src/brazil/ip/il.c /n/emeliedump/1997/0803/sys/src/brazil/ip/il.c
734c

	/*
	 *  Double delay estimate and half bandwidth estimate.  This is
	 *  in keeping with van jacobson's tcp alg.
	 */
	ic->rttack = 0;
	if((ic->delay>>LogAGain) < 2*Seconds)
		ic->delay *= 2;
	x = ic->rate>>1;
	if(x >= (1<<LogAGain))
		ic->rate = x;

.
731a
	c = ic->conv;
	id = nhgetl(h->ilid);
	netlog(Logil, "il: rexmit %ud %ud: %d %d: %i %d/%d\n", id, ic->recvd,
		ic->fasttime, ic->timeout,
		c->raddr, c->lport, c->rport);

.
723d
711a
	Conv *c;
	int x;
	ulong id;
.
664d
650d
557,559d
## diffname ip/il.c 1997/0804
## diff -e /n/emeliedump/1997/0803/sys/src/brazil/ip/il.c /n/emeliedump/1997/0804/sys/src/brazil/ip/il.c
1121a
}

int
ilnextqt(Ilcb *ic)
{
	int x;

	qlock(&ic->ackq);
	x = ic->qtx;
	ic->qt[x] = ic->next-1;	/* highest xmitted packet */
	ic->qt[0] = ic->qt[x];	/* compatibility with old implementations */
	if(++x > Nqt)
		x = 1;
	ic->qtx = x;
	qunlock(&ic->ackq);

	return x;
.
1083c
	ic->fasttime = Acktime + pt + Iltickms - 1;
.
1047c
		ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0);
.
1036a
	ic->qtx = 1;
.
983c
				ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
.
973c
				ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0);
.
964c
				ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0);
.
955c
				ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0);
.
919c
	ih->ilspec = ilspec;
.
881c
ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec)
.
723a
	h->ilspec = ilnextqt(ic);
.
709a
	int x;
.
708d
689c
			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
.
675c
			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
.
667c
			if(h->ilspec > Nqt)
				h->ilspec = 0;
			if(ic->qt[h->ilspec] > ack)
				ilrexmit(ic);
.
661c
			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
.
659c
		case Ilquery:
.
652c
			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
.
634c
				ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0);
.
610c
				ilsendctl(s, nil, Ilsync, ic->start, ic->recvd, 0);
.
587c
				ilsendctl(s, nil, Ilack, ic->next, ic->recvd, 0);
.
531c
		ilsendctl(nil, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
.
231c
		ilsendctl(c, nil, Ilclose, ic->next, ic->recvd, 0);
.
155a
int	ilnextqt(Ilcb*);
.
142c
void	ilsendctl(Conv*, Ilhdr*, int, ulong, ulong, int);
.
140a
/* state for query/dataquery messages */


.
82c
	int	rexmit;		/* number of retransmits */
	ulong	qt[Nqt+1];	/* state table for query messages */
	int	qtx;		/* ... index into qt */
.
52a
enum
{
	Nqt=	8,
};

.
38c
	Ilquery,
.
26c
	"query",
.
24c
	"dataquery",
.
## diffname ip/il.c 1997/0805
## diff -e /n/emeliedump/1997/0804/sys/src/brazil/ip/il.c /n/emeliedump/1997/0805/sys/src/brazil/ip/il.c
1043c
	ic->delay = Iltickms<<LogAGain;
	ic->mdev = Iltickms<<LogDGain;
	ic->rate = DefByteRate<<LogAGain;
.
555c
	ic->delay = Iltickms<<LogAGain;
	ic->mdev = Iltickms<<LogDGain;
	ic->rate = DefByteRate<<LogAGain;
.
377,384d
375a
static
.
140a

.
139d
## diffname ip/il.c 1997/0806
## diff -e /n/emeliedump/1997/0805/sys/src/brazil/ip/il.c /n/emeliedump/1997/0806/sys/src/brazil/ip/il.c
1018c
	ic->fasttime += ic->fasttime>>1;
.
131c
	Ackkeepalive	= 600*Seconds,
.
## diffname ip/il.c 1997/0902
## diff -e /n/emeliedump/1997/0806/sys/src/brazil/ip/il.c /n/emeliedump/1997/0902/sys/src/brazil/ip/il.c
787c
	netlog(Logil, "il: hangup! %i %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason");
.
249a
	ilfreeq(ic);
.
240d
## diffname ip/il.c 1997/0916
## diff -e /n/emeliedump/1997/0902/sys/src/brazil/ip/il.c /n/emeliedump/1997/0916/sys/src/brazil/ip/il.c
873a
					ilstats.dup++;
					ilstats.dupb += blocklen(bp);
.
823a
		}
.
822c
		if(oid != ic->recvd+1){
			il.order++;
.
344a
	il.stats = ilxstats;
.
331a
int
ilxstats(char *buf, int len)
{
	return snprint(buf, len, "\tdupp %d dupb %d\n", ilstats.dup, ilstats.dupb);
}

.
124a
static struct Ilstats
{
	ulong	dup;
	ulong	dupb;
} ilstats;

.
## diffname ip/il.c 1997/0917
## diff -e /n/emeliedump/1997/0916/sys/src/brazil/ip/il.c /n/emeliedump/1997/0917/sys/src/brazil/ip/il.c
1117c
	if(ic->slowtime < Slowtime)
.
## diffname ip/il.c 1997/1003
## diff -e /n/emeliedump/1997/0917/sys/src/brazil/ip/il.c /n/emeliedump/1997/1003/sys/src/brazil/ip/il.c
1112,1113c
	pt = (ic->delay>>LogAGain) + ic->unackedbytes/(ic->rate>>LogAGain) + (ic->mdev>>(LogDGain-1));
	ic->fasttime = pt + Iltickms - 1;
.
1018c
				ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
				ic->querytime = Querytime;
				ic->timeout = 0;
.
## diffname ip/il.c 1998/0306
## diff -e /n/emeliedump/1997/1003/sys/src/brazil/ip/il.c /n/emeliedump/1998/0306/sys/src/brazil/ip/il.c
1142,1143c
		if(s->lport == psource)
		if(ipcmp(s->laddr, source) == 0)
		if(ipcmp(s->raddr, dest) == 0){
.
1134,1135c
	v4tov6(dest, h->dst);
	v4tov6(source, h->src);
.
1128c
	uchar source[IPaddrlen], dest[IPaddrlen];
.
1114,1115c
	pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev;
	ic->fasttime = Acktime + pt + Iltickms - 1;
.
1056c
	ic->unackeduchars = 0;
.
1018,1020c
				ilrexmit(ic);
.
935,936c
		v6tov4(ih->dst, ipc->raddr);
		v6tov4(ih->src, ipc->laddr);
.
862c
	uchar *lid;
.
800c
	netlog(Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason");
.
547c
		netlog(Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
.
545c
	v4tov6(laddr, ih->dst);
	new = Fsnewcall(&fs, s, raddr, dp, laddr, sp);
.
527c
		if(s->rport == 0 && ipcmp(s->raddr, IPnoaddr) == 0) {
.
514,515c
		netlog(Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
			st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp); 
.
503c
		if(s->lport == sp)
		if(s->rport == dp)
		if(ipcmp(s->raddr, raddr) == 0) {
.
496,497c
		netlog(Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %I/%d->%d)\n",
			csum, st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
.
488c
	v4tov6(raddr, ih->src);
.
470d
465c
	uchar raddr[IPaddrlen];
	uchar laddr[IPaddrlen];
.
460c
iliput(uchar*, Block *bp)
.
453c
		ic->unackeduchars -= blocklen(bp);
.
386c
	ic->unackeduchars += n;
.
357a
	il.inuse = ilinuse;
.
341c
	int n;

	n = snprint(buf, len,
		"il: csum %d hlen %d len %d order %d rexmit %d",
		il.csumerr, il.hlenerr, il.lenerr, il.order, il.rexmit);
	n += snprint(buf+n, len-n, " dupp %d dupb %d\n",
		ilstats.dup, ilstats.dupb);
.
294,295c
	v6tov4(ih->dst, c->raddr);
	v6tov4(ih->src, c->laddr);
.
251c
		ipmove(c->laddr, IPnoaddr);
.
204,208c
	ic = (Ilcb*)(c->ptcl);
	return ic->state != Ilclosed;

.
200,202c
static int
ilinuse(Conv *c)
{
	Ilcb *ic;
.
198a
	return snprint(state, n, "%14.14s del %5.5d Br %5.5d md %5.5d una %5.5d rex %5.5d max %5.5d",
		ilstates[ic->state],
		ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain,
		ic->unackeduchars, ic->rexmit, ic->maxrtt);
}
.
196d
192,193c
static int
ilstate(Conv *c, char *state, int n)
.
170c
void	iliput(uchar*, Block*);
.
105,122c
	uchar	vihl;		/* Version and header length */
	uchar	tos;		/* Type of service */
	uchar	length[2];	/* packet length */
	uchar	id[2];		/* Identification */
	uchar	frag[2];	/* Fragment information */
	uchar	ttl;		/* Time to live */
	uchar	proto;		/* Protocol */
	uchar	cksum[2];	/* Header checksum */
	uchar	src[4];		/* Ip source */
	uchar	dst[4];		/* Ip destination */
	uchar	ilsum[2];	/* Checksum including header */
	uchar	illen[2];	/* Packet length */
	uchar	iltype;		/* Packet type */
	uchar	ilspec;		/* Special */
	uchar	ilsrc[2];	/* Src port */
	uchar	ildst[2];	/* Dst port */
	uchar	ilid[4];	/* Sequence id */
	uchar	ilack[4];	/* Acked sequence */
.
90d
80c
	int	rate;		/* Average uchar rate */
.
66c
	ulong	unackeduchars;
.
## diffname ip/il.c 1998/0307
## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/il.c /n/emeliedump/1998/0307/sys/src/brazil/ip/il.c
349a
	return n;
.
## diffname ip/il.c 1998/0313
## diff -e /n/emeliedump/1998/0307/sys/src/brazil/ip/il.c /n/emeliedump/1998/0313/sys/src/brazil/ip/il.c
1151c
	for(p = il->conv; *p; p++) {
.
1135c
iladvise(Proto *il, Block *bp, char *msg)
.
1083c
		netlog(c->p->f, Logil, "il: start: type %d\n", type);
.
1035c
				netlog(il->f, Logil, "il: hangup due to timeout (%d) >= slowtime (%d)\n", ic->timeout, ic->slowtime);
.
1019c
					netlog(il->f, Logil, "il: hangup due to deathtime (%d) < 0 \n", ic->deathtime);
.
983,984c
	tsleep(&ipriv->ilr, return0, 0, Iltickms);
	for(s = il->conv; s && *s; s++) {
.
981a
	il = x;
	ipriv = il->priv;

.
980c
	Proto *il;
	Ilpriv *ipriv;
.
976c
ilackproc(void *x)
.
972c
	ipoput(ipc->p->f, bp, 0, ttl);
.
967c
		netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",
.
902,903c
					ipriv->dup++;
					ipriv->dupb += blocklen(bp);
.
885c
		netlog(s->p->f, Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n",
.
878a
	ipriv = s->p->priv;
.
877a
	Ilpriv *ipriv;
.
849c
			ipriv = s->p->priv;
			ipriv->order++;
.
832a
	Ilpriv *ipriv;
.
823c
		Fsconnected(s, msg);
.
813c
	netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason");
.
804c
	netlog(s->p->f, Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next);
.
797c
	netlog(s->p->f, Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ",
.
785c
	ipoput(c->p->f, nb, 0, ic->conv->ttl);
.
771c
	ipriv->rexmit++;
.
767c
	netlog(c->p->f, Logil, "il: rexmit %ud %ud: %d %d: %i %d/%d\n", id, ic->recvd,
.
765a
	ipriv = c->p->priv;
.
762,763c
	hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen)));
.
744a
	Ilpriv *ipriv;
.
621c
				Fsconnected(s, nil);
.
605c
		netlog(s->p->f, Logil, "il: unknown state %d\n", ic->state);
.
560c
		netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
.
558c
	new = Fsnewcall(s, raddr, dp, laddr, sp);
.
533c
	for(p = il->conv; *p; p++) {
.
526c
		netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
.
511c
	for(p = il->conv; *p; p++) {
.
505,506c
		ipriv->csumerr++;
		netlog(il->f, Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %I/%d->%d)\n",
.
500c
	if((csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) {
.
491,492c
		netlog(il->f, Logil, "il: lenerr\n");
		ipriv->lenerr++;
.
484,485c
		netlog(il->f, Logil, "il: hlenerr\n");
		ipriv->hlenerr++;
.
480a
	ipriv = il->priv;

.
479a
	Ilpriv *ipriv;
.
470c
iliput(Proto *il, uchar*, Block *bp)
.
374c
	kproc("ilack", ilackproc, il);
.
372c
	il = smalloc(sizeof(Proto));
	il->priv = smalloc(sizeof(Ilpriv));
	il->name = "il";
	il->kick = ilkick;
	il->connect = ilconnect;
	il->announce = ilannounce;
	il->state = ilstate;
	il->create = ilcreate;
	il->close = ilclose;
	il->rcv = iliput;
	il->ctl = nil;
	il->advise = iladvise;
	il->stats = ilxstats;
	il->inuse = ilinuse;
	il->ipproto = IP_ILPROTO;
	il->nc = Nchans;
	il->ptclsize = sizeof(Ilcb);
	Fsproto(f, il);
.
356,370c
	Proto *il;
.
354c
ilinit(Fs *f)
.
349c
		ipriv->dup, ipriv->dupb);
.
347c
		ipriv->csumerr, ipriv->hlenerr, ipriv->lenerr, ipriv->order, ipriv->rexmit);
.
344a
	ipriv = il->priv;

.
343a
	Ilpriv *ipriv;
.
341c
ilxstats(Proto *il, char *buf, int len)
.
330c
	ipoput(f, bp, 0, c->ttl);
.
271a
	f = c->p->f;
.
268a
	Fs *f;
.
225c
	Fsconnected(c, nil);
.
178d
173,175d
169,170c
void	iliput(Proto*, uchar*, Block*);
void	iladvise(Proto*, Block*, char*);
.
167c
void	ilackproc(void*);
.
129a
	/* non-MIB stats */
	ulong		csumerr;		/* checksum errors */
	ulong		hlenerr;		/* header length error */
	ulong		lenerr;			/* short packet */
	ulong		order;			/* out of order */
	ulong		rexmit;			/* retransmissions */
	ulong		dup;
	ulong		dupb;

	Rendez		ilr;
};

.
126,128d
124c

typedef struct Ilpriv Ilpriv;
struct Ilpriv
.
## diffname ip/il.c 1998/0407
## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/il.c /n/emeliedump/1998/0407/sys/src/brazil/ip/il.c
204c
	return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5d rex %5.5d max %5.5d",
.
## diffname ip/il.c 1998/0630
## diff -e /n/emeliedump/1998/0407/sys/src/brazil/ip/il.c /n/emeliedump/1998/0630/sys/src/brazil/ip/il.c
204c
	return snprint(state, n, "%14.14s del %5.5d Br %5.5d md %5.5d una %5.5d rex %5.5d max %5.5d",
.
## diffname ip/il.c 1998/0724
## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/il.c /n/emeliedump/1998/0724/sys/src/brazil/ip/il.c
204c
	return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5d rex %5.5d max %5.5d",
.
## diffname ip/il.c 1998/0825
## diff -e /n/emeliedump/1998/0724/sys/src/brazil/ip/il.c /n/emeliedump/1998/0825/sys/src/brazil/ip/il.c
360c
	n += snprint(buf+n, len-n, " dupp %lud dupb %lud\n",
.
358c
		"il: csum %lud hlen %lud len %lud order %lud rexmit %lud",
.
204c
	return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5lud rex %5.5d max %5.5d",
.
## diffname ip/il.c 1998/0918
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/ip/il.c /n/emeliedump/1998/0918/sys/src/brazil/ip/il.c
887c
		qpassnolim(s->rq, packblock(bp));
.
## diffname ip/il.c 1998/0923
## diff -e /n/emeliedump/1998/0918/sys/src/brazil/ip/il.c /n/emeliedump/1998/0923/sys/src/brazil/ip/il.c
887c
		bp = packblock(bp);
		if(bp == 0)
			panic("ilpullup2");
		qpassnolim(s->rq, bp);
.
## diffname ip/il.c 1998/0924
## diff -e /n/emeliedump/1998/0923/sys/src/brazil/ip/il.c /n/emeliedump/1998/0924/sys/src/brazil/ip/il.c
1085a
	Ilpriv *ipriv;
	char kpname[NAMELEN];

	ipriv = c->p->priv;

	if(ipriv->ackprocstarted == 0){
		qlock(&ipriv->apl);
		if(ipriv->ackprocstarted == 0){
			sprint(kpname, "#I%dilack", c->p->f->dev);
			kproc(kpname, ilackproc, c->p);
			ipriv->ackprocstarted = 1;
		}
		qunlock(&ipriv->apl);
	}
.
388,389d
138a

	/* keeping track of the ack kproc */
	int	ackprocstarted;
	QLock	apl;
.
## diffname ip/il.c 1998/0925
## diff -e /n/emeliedump/1998/0924/sys/src/brazil/ip/il.c /n/emeliedump/1998/0925/sys/src/brazil/ip/il.c
1080a
	if(ic->fasttime > Fasttime)
		ic->fasttime = Fasttime;
.
599a
	ic->unackeduchars = 0;
.
## diffname ip/il.c 1998/0929
## diff -e /n/emeliedump/1998/0925/sys/src/brazil/ip/il.c /n/emeliedump/1998/0929/sys/src/brazil/ip/il.c
1231a
}

/* quick and dirty conversion from fastticks to microseconds */
static void
initfast(void)
{
	int i;
	uvlong x, hz;

	fastticks(&hz);
	x = 3;
	for(i = 1; i < 40; i++){
		if(x >= hz)
			break;
		x <<= 1;
	}
	microshift = i - 20;
}

void
ilinit(Fs *f)
{
	Proto *il;

	initfast();

	il = smalloc(sizeof(Proto));
	il->priv = smalloc(sizeof(Ilpriv));
	il->name = "il";
	il->kick = ilkick;
	il->connect = ilconnect;
	il->announce = ilannounce;
	il->state = ilstate;
	il->create = ilcreate;
	il->close = ilclose;
	il->rcv = iliput;
	il->ctl = nil;
	il->advise = iladvise;
	il->stats = ilxstats;
	il->inuse = ilinuse;
	il->ipproto = IP_ILPROTO;
	il->nc = Nchans;
	il->ptclsize = sizeof(Ilcb);
	Fsproto(f, il);
.
1169,1183d
1143c
	return nil;
.
1122,1129d
1114,1120c
	ilcbinit(ic);
.
1112c
		return nil;
.
1109,1110d
1089d
1087c
ilstart(Conv *c, int type)
.
1081,1083c
	ic->start = nrand(0x1000000);
	ic->next = ic->start+1;
	ic->recvd = 0;
	ic->window = Defaultwin;
	ic->unackeduchars = 0;
	ic->unacked = nil;
	ic->outoforder = nil;
	ic->rexmit = 0;
	ic->rxtot = 0;
	ic->qtx = 1;

	/* timers */
	ic->delay = DefRtt<<LogAGain;
	ic->mdev = DefRtt<<LogDGain;
	ic->rate = DefByteRate<<LogAGain;
	ic->querytime = msec + QueryTime;
	ic->lastrecv = msec;	/* or we'll timeout right away */
	ilsettimeout(ic);
.
1079c
ilcbinit(Ilcb *ic)
.
1067,1071d
1065d
1059,1063c

			if(ic->unacked != nil && ic->timeout <= msec) {
				if(ic->rexmit > MaxRexmit){
					netlog(il->f, Logil, "il: hangup: too many rexmits\n");
					ilhangup(p, etime);
					break;
				}
.
1057c
				ic->querytime = msec + QueryTime;
.
1048,1052c
			if(ic->querytime <= msec){
				if(msec - ic->lastrecv > DeathTime){
					netlog(il->f, Logil, "il: hangup: deathtime\n");
.
1044,1045c
			if(ic->recvd != ic->acksent && ic->acktime <= msec)
.
1040,1041d
1036c
			if(ic->timeout <= msec) {
				if(ic->rexmit > MaxRexmit){
					ilhangup(p, etime);
					break;
				}
.
1031,1032d
1027c
			if(ic->timeout <= msec) {
				if(ic->rexmit > MaxRexmit){
					ilhangup(p, nil);
					break;
				}
.
1021d
1004a
ilsettimeout(Ilcb *ic)
{
	ulong pt;

	pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev;
	pt += AckDelay;
	if(pt > MaxTimeout)
		pt = MaxTimeout;
	ic->timeout = msec + pt;
}

void
ilbackoff(Ilcb *ic)
{
	ulong pt;
	int i;
	Ilpriv *priv;

	pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev;
	pt += AckDelay;
	for(i = 0; i < ic->rexmit; i++)
		pt = pt + (pt>>1);
	if(pt > MaxTimeout)
		pt = MaxTimeout;
	ic->timeout = msec + pt;

	ic->rxtot++;
	ic->rexmit++;

	priv = ic->conv->p->priv;
	priv->rexmit++;
}

void
.
984c
		ic->acksent = ack;
		ic->acktime = msec;
.
835c
	netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr,
		s->lport, s->rport, msg?msg:"no reason");
.
806a
	ilbackoff(ic);

.
801,805d
793,799c
	/* rtt calcs are useless during retransmissions */
.
789,790c
	netlog(c->p->f, Logil, "il: rexmit %d %ud: %d %d: %i %d/%d\n", id, ic->recvd,
		ic->rexmit, ic->timeout,
.
787d
765,766d
748d
734d
724c
				ilsettimeout(ic);
			}
.
722c
			if(ic->qt[h->ilspec] > ack){
.
719c
			ilackto(ic, ack, bp);
.
715d
713c
			ilackto(ic, ack, bp);
.
708,709c
			ilackto(ic, ack, bp);
.
700,702c
			ilackto(ic, ack, bp);
.
693,695c
			ilackto(ic, ack, bp);
.
688,689d
686c
			else
.
671d
664d
644d
621,622c
	ic->lastrecv = msec;
.
593,600d
588,591c
	ilcbinit(ic);
.
481a
		ic->rexmit = 0;
		ilsettimeout(ic);
.
464c
		ilrttcalc(ic, bp);
.
460d
457c
ilackto(Ilcb *ic, ulong ackto, Block *bp)
.
452,453c
	if(mrtt > ic->maxrtt)
		ic->maxrtt = mrtt;
.
450c
	ic->mdev += abs(mrtt-pt) - (ic->mdev>>LogDGain);
.
439,440c
	/* this block had to be transmitted after the one acked so count its size */
	ic->rttlen += blocklen(bp)  + IL_IPSIZE + IL_HDRSIZE;

	/* if packet took longer than round trip delay, reset rate */
	tt = mrtt - (delay>>LogAGain);
.
433c
		delay += mrtt - (delay>>LogAGain);
.
427,428c
	/* Guard against zero wrap */
	if(rtt > 120000000)
.
422,423c
	fastrtt = fastticks(nil) - ic->rttstart;
	if(microshift >= 0)
		rtt = fastrtt >> microshift;
	else
		rtt = fastrtt << -microshift;
	mrtt = rtt >> 10;
.
420c
	uvlong fastrtt;
	int rtt, tt, pt, delay, rate, mrtt;
.
418c
ilrttcalc(Ilcb *ic, Block *bp)
.
410d
406,408c
	else
.
370,394d
342a
	if(ic->timeout <= msec)
		ilsettimeout(ic);
.
341d
338c
		ic->rttstart = fastticks(nil);
.
321,322c
	ack = ic->recvd;
	hnputl(ih->ilack, ack);
	ic->acksent = ack;
	ic->acktime = msec + AckDelay;
.
278c
	ulong id, ack;
.
233c
	e = ilstart(c, IL_LISTEN);
.
211c
		ic->unackeduchars, ic->rxtot, ic->maxrtt);
.
199c
	return ilstart(c, IL_CONNECT);
.
190a

.
189a
static	int	microshift;
.
186a
void	ilcbinit(Ilcb*);
.
180,181c
void	ilsettimeout(Ilcb*);
char*	ilstart(Conv*, int);
.
165a
	DefRtt		= 50,		/* cross country on a great day */
.
151,158c
	MaxRexmit 	= 10,		/* max retransmissions before hangup */
.
149c
	Iltickms 	= 50,		/* time base */
	AckDelay	= 2*Iltickms,	/* max time twixt message rcvd & ack sent */
	MaxTimeout 	= 4*Seconds,	/* max time between rexmit */
	QueryTime	= 5*Seconds,	/* time between subsequent queries */
	DeathTime	= 5*QueryTime,
.
145d
85,89c
	uvlong	rttstart;	/* Time we issued rttack packet */
.
73,78c
	int	window;		/* Maximum receive window */
	int	rxtot;		/* number of retransmits on this connection */
	int	rexmit;		/* number of retransmits of *unacked */
	ulong	qt[Nqt+1];	/* state table for query messages */
	int	qtx;		/* ... index into qt */

	/* timers */
	ulong	lastxmit;	/* time of last xmit */
	ulong	lastrecv;	/* time of last recv */
	ulong	timeout;	/* retransmission time for *unacked */
	ulong	acktime;	/* time to send next ack */
	ulong	querytime;	/* time to send next query */

	/* adaptive measurements */
.
70a
	ulong	acksent;	/* Last packet acked */
.
52a
static char *etime = "connection timed out";

.
43,50c
char	*iltype[] = 
{	
	"sync",
	"data",
	"dataquery",
	"ack",
	"query",
	"state",
	"close" 
.
20,31d
9a
enum				/* Connection state */
{
	Ilclosed,
	Ilsyncer,
	Ilsyncee,
	Ilestablished,
	Illistening,
	Ilclosing,
};

.
## diffname ip/il.c 1998/0930
## diff -e /n/emeliedump/1998/0929/sys/src/brazil/ip/il.c /n/emeliedump/1998/0930/sys/src/brazil/ip/il.c
1225c
	inittimeshift();
.
1217c
	timeshift = i - 10;
	if(i < 0)
		timeround = (1<<-i)-1;
	else
		timeround = 0;
.
1212c
	for(i = 1; i < 45; i++){
.
1205c
inittimeshift(void)
.
1203c
/* calculate shift that converts fast ticks to ms (more or less) */
.
1071c
	ic->unackedbytes = 0;
.
1056c
				ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
				ic->rxquery++;
				ilbackoff(ic);
.
989,991d
987d
979,980c
	pt = (ic->delay>>LogAGain)
		+ ic->unackedbytes/(ic->rate>>LogAGain)
		+ (ic->mdev>>(LogDGain-1))
		+ AckDelay;
.
977d
965,966c
	pt = (ic->delay>>LogAGain)
		+ ic->unackedbytes/(ic->rate>>LogAGain)
		+ (ic->mdev>>(LogDGain-1))
		+ AckDelay;
.
761a

	/* statistics */
	ic->rxtot++;
	priv = c->p->priv;
	priv->rexmit++;
.
756,758d
730a
	Ilpriv *priv;
.
685a
			if(ack >= ic->rttack)
				ic->rttack = 0;
.
468c
		ic->unackedbytes -= blocklen(bp);
.
441,442c
	if(rtt > ic->maxrtt)
		ic->maxrtt = rtt;
.
439c
	ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain);
.
425,436d
422a
	} else {
		/* if packet took longer than avg rtt delay, recalc rate */
		tt = rtt - (delay>>LogAGain);
		if(tt > 0){
			rate += ic->rttlen/tt - (rate>>LogAGain);
			if(rate < AGain)
				rate = AGain;
			ic->rate = rate;
		}
.
417,419c
	/* this block had to be transmitted after the one acked so count its size */
	ic->rttlen += blocklen(bp)  + IL_IPSIZE + IL_HDRSIZE;

	if(ic->rttlen < 256){
		/* guess fixed delay as rtt of small packets */
		delay += rtt - (delay>>LogAGain);
.
414c
	if(rtt > 120000)
.
405,409c
	if(timeshift >= 0)
		rtt = fastrtt >> timeshift;
	else {
		rtt = fastrtt;
		rtt = (rtt<<-timeshift)+timeround;
	}
.
402c
	int rtt, tt, pt, delay, rate;
.
394c
	ic->unackedbytes += n;
.
217c
		ic->unackedbytes, ic->rxtot, ic->rxquery, ic->maxrtt);
.
214c
	return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5lud rex %5.5d rxq %5.5d max %5.5d",
.
196d
194c
static	int	timeshift, timeround;
static	char	*etime = "connection timed out";
.
151,170d
75a
	int	rxquery;	/* number of queries on this connection */
.
67c
	ulong	unackedbytes;
.
53a
	MaxRexmit 	= 16,		/* max retransmissions before hangup */
	Defaultwin	= 20,

	LogAGain	= 3,
	AGain		= 1<<LogAGain,
	LogDGain	= 2,
	DGain		= 1<<LogDGain,

	DefByteRate	= 100,		/* assume a megabit link */
	DefRtt		= 50,		/* cross country on a great day */
};

.
52c
enum
{
	Seconds		= 1000,
	Iltickms 	= 50,		/* time base */
	AckDelay	= 2*Iltickms,	/* max time twixt message rcvd & ack sent */
	MaxTimeout 	= 4*Seconds,	/* max time between rexmit */
	QueryTime	= 5*Seconds,	/* time between subsequent queries */
	DeathTime	= 5*QueryTime,
.
27c
	"Closing",
	"Opening",		/* only for file server */
.
17a
	Ilopening,		/* only for file server */
.
## diffname ip/il.c 1998/1001
## diff -e /n/emeliedump/1998/0930/sys/src/brazil/ip/il.c /n/emeliedump/1998/1001/sys/src/brazil/ip/il.c
1084a
	ic->rxquery = 0;
.
990c
		+ (ic->mdev>>(LogDGain-2))
.
975c
		+ (ic->mdev>>(LogDGain-2))
.
## diffname ip/il.c 1998/1013
## diff -e /n/emeliedump/1998/1001/sys/src/brazil/ip/il.c /n/emeliedump/1998/1013/sys/src/brazil/ip/il.c
1207a
	ic->qt[x] = ic->next-1;	/* highest xmitted packet */
	ic->qt[0] = ic->qt[x];	/* compatibility with old implementations */
.
1203,1204d
745a
	}
.
744c
	if(nb == nil){
		print("ilrexmit: copyblock returns nil\n");
.
603a
	ic->querytime = msec + QueryTime;
.
60c
	QueryTime	= 10*Seconds,	/* time between subsequent queries */
.
## diffname ip/il.c 1999/0302
## diff -e /n/emeliedump/1998/1013/sys/src/brazil/ip/il.c /n/emeliedump/1999/0302/sys/src/brazil/ip/il.c
1195a
	qunlock(il);
.
1193c
			freeblist(bp);
			return;
.
1186a
			qunlock(il);
.
1181a
	qlock(il);
.
584a
	qunlock(new);
	poperror();
.
583a
	qlock(new);
	qunlock(il);
	if(waserror()){
		qunlock(new);
		nexterror();
	}
.
578a

.
572a
		qunlock(il);
.
568a
	}
.
567c
	else {
		qunlock(il);
.
534a
		qunlock(il);
.
529a
			qunlock(s);
			poperror();
.
528a
			qlock(s);
			qunlock(il);
			if(waserror()){
				qunlock(s);
				nexterror();
			}
.
523a
	qlock(il);

.
277c
	qunlock(c);
.
## diffname ip/il.c 1999/0331
## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/il.c /n/emeliedump/1999/0331/sys/src/brazil/ip/il.c
1068a

.
1057a

.
## diffname ip/il.c 1999/0424
## diff -e /n/emeliedump/1999/0331/sys/src/brazil/ip/il.c /n/emeliedump/1999/0424/sys/src/brazil/ip/il.c
1085c
			if(ic->unacked != nil)
			if(later(msec, ic->timeout, "timeout")) {
.
1075,1076c
			if(later(msec, ic->querytime, "querytime")){
				if(later(msec, ic->lastrecv+DeathTime, "deathtime")){
.
1072c
			if(ic->recvd != ic->acksent)
			if(later(msec, ic->acktime, "acktime"))
.
1061c
			if(later(msec, ic->timeout, "timeout")) {
.
1049c
			if(later(msec, ic->timeout, "timeout")) {
.
1026a
// complain if two numbers not within an hour of each other
#define Tfuture (1000*60*60)
int
later(ulong t1, ulong t2, char *x)
{
	int dt;

	dt = t1 - t2;
	if(dt > 0) {
		if(dt > Tfuture)
			print("%s: way future %d\n", x, dt);
		return 1;
	}
	if(dt < -Tfuture) {
		print("%s: way past %d\n", x, -dt);
		return 1;
	}
	return 0;
}

.
## diffname ip/il.c 1999/0429
## diff -e /n/emeliedump/1999/0424/sys/src/brazil/ip/il.c /n/emeliedump/1999/0429/sys/src/brazil/ip/il.c
1107c
			if(later(msec, ic->timeout, "timeout2")) {
.
1081c
			if(later(msec, ic->timeout, "timeout1")) {
.
1069c
			if(later(msec, ic->timeout, "timeout0")) {
.
729a
			ilsettimeout(ic);
.
352c
	if(later(msec, ic->timeout, "ilkick"))
.
267a
		ilsettimeout(ic);
.
## diffname ip/il.c 1999/0430
## diff -e /n/emeliedump/1999/0429/sys/src/brazil/ip/il.c /n/emeliedump/1999/0430/sys/src/brazil/ip/il.c
1043c
		if(x != nil)
			print("%s: way past %d\n", x, -dt);
.
1038c
		if(x != nil && dt > Tfuture)
.
353c
	if(later(msec, ic->timeout, nil))
.
## diffname ip/il.c 1999/0501
## diff -e /n/emeliedump/1999/0430/sys/src/brazil/ip/il.c /n/emeliedump/1999/0501/sys/src/brazil/ip/il.c
192a
int	later(ulong, ulong, char*);
.
## diffname ip/il.c 1999/0529
## diff -e /n/emeliedump/1999/0501/sys/src/brazil/ip/il.c /n/emeliedump/1999/0529/sys/src/brazil/ip/il.c
59c
	MaxTimeout 	= 30*Seconds,	/* max time between rexmit */
.
## diffname ip/il.c 1999/0630
## diff -e /n/emeliedump/1999/0529/sys/src/brazil/ip/il.c /n/emeliedump/1999/0630/sys/src/brazil/ip/il.c
992d
988,989c
	netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",
.
590c
		ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
.
## diffname ip/il.c 1999/0703
## diff -e /n/emeliedump/1999/0630/sys/src/brazil/ip/il.c /n/emeliedump/1999/0703/sys/src/brazil/ip/il.c
1295c
	inittimescale();
.
1283,1287d
1277,1281c
	if(hz > 1000){
		scalediv = hz/1000;
		scalemul = 1;
	} else {
		scalediv = 1;
		scalemul = 1000/hz;
.
1273,1274c
	uvlong hz;
.
1271c
inittimescale(void)
.
1269c
/* calculate scale constants that converts fast ticks to ms (more or less) */
.
1017c
		+ (ic->mdev>>(LogDGain-1))
.
1002c
		+ (ic->mdev>>(LogDGain-1))
.
419c
	if(rtt > 120000 || rtt < 0)
.
408,414c
	rtt = fastticks(nil) - ic->rttstart;
	rtt = (rtt*scalemul)/scalediv;
.
405d
197c
static	ulong	scalediv, scalemul;
.
## diffname ip/il.c 1999/0817
## diff -e /n/emeliedump/1999/0703/sys/src/brazil/ip/il.c /n/emeliedump/1999/0817/sys/src/brazil/ip/il.c
986c
	ipoput(ipc->p->f, bp, 0, ttl, tos);
.
972a
		tos = ipc->tos;
.
960a
		tos = DFLTTOS;
.
941c
	int ttl, tos;
.
787c
	ipoput(c->p->f, nb, 0, ic->conv->ttl, ic->conv->tos);
.
356c
	ipoput(f, bp, 0, c->ttl, c->tos);
.
## diffname ip/il.c 1999/0821
## diff -e /n/emeliedump/1999/0817/sys/src/brazil/ip/il.c /n/emeliedump/1999/0821/sys/src/brazil/ip/il.c
768d
765,766c
	if(nb == nil)
.
## diffname ip/il.c 1999/0916
## diff -e /n/emeliedump/1999/0821/sys/src/brazil/ip/il.c /n/emeliedump/1999/0916/sys/src/brazil/ip/il.c
679a
	established:
.
671a
		case Ildata:
			if(ack == ic->start) {
				ic->state = Ilestablished;
				goto established;
			}
			break;
.
## diffname ip/il.c 1999/0917
## diff -e /n/emeliedump/1999/0916/sys/src/brazil/ip/il.c /n/emeliedump/1999/0917/sys/src/brazil/ip/il.c
993a
}

void
ilreject(Fs *f, Ilhdr *inih)
{
	Ilhdr *ih;
	Block *bp;

	bp = allocb(IL_IPSIZE+IL_HDRSIZE);
	bp->wp += IL_IPSIZE+IL_HDRSIZE;

	ih = (Ilhdr *)(bp->rp);

	/* Ip fields */
	ih->proto = IP_ILPROTO;
	hnputs(ih->illen, IL_HDRSIZE);
	ih->frag[0] = 0;
	ih->frag[1] = 0;
	hnputl(ih->dst, nhgetl(inih->src));
	hnputl(ih->src, nhgetl(inih->dst));
	hnputs(ih->ilsrc, nhgets(inih->ildst));
	hnputs(ih->ildst, nhgets(inih->ilsrc));
	hnputl(ih->ilid, nhgetl(inih->ilack));
	hnputl(ih->ilack, nhgetl(inih->ilid));
	ih->iltype = Ilclose;
	ih->ilspec = 0;
	ih->ilsum[0] = 0;
	ih->ilsum[1] = 0;

	if(ilcksum)
		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));

	ipoput(f, bp, 0, MAXTTL, DFLTTOS);
.
730a
			ic->recvd = id;
.
649c
				ilhangup(s, "connection rejected");
.
575a
		ilreject(il->f, ih);		/* no listener */
.
545a
		ilreject(il->f, ih);		/* no channel and not sync */
.
193a
void	ilreject(Fs*, Ilhdr*);
.
## diffname ip/il.c 2000/0424
## diff -e /n/emeliedump/1999/0917/sys/src/brazil/ip/il.c /n/emeliedump/2000/0424/sys/src/9/ip/il.c
1343a
	il->gc = nil;
.
## diffname ip/il.c 2000/0706
## diff -e /n/emeliedump/2000/0424/sys/src/9/ip/il.c /n/emeliedump/2000/0706/sys/src/9/ip/il.c
926,927c
					ipriv->stats[DupMsg]++;
					ipriv->stats[DupBytes] += blocklen(bp);
.
868c
			ipriv->stats[OutOfOrder]++;
.
626a
	priv = s->p->priv;
	priv->stats[InMsgs]++;
.
618a
	Ilpriv *priv;
.
515c
		ipriv->stats[CsumErrs]++;
.
502c
		ipriv->stats[LenErrs]++;
.
495c
		ipriv->stats[HlenErrs]++;
.
373,380c
	priv = il->priv;
	p = buf;
	e = p+len;
	for(i = 0; i < Nstats; i++)
		p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]);
	return p - buf;
.
370,371c
	Ilpriv *priv;
	char *p, *e;
	int i;
.
357a
	priv->stats[OutMsgs]++;
.
295a
	priv = c->p->priv;
.
292a

.
291a
	Ilpriv *priv;
.
157d
155a
	ulong	stats[Nstats];
.
152a
	Nstats,
};

static char *statnames[] =
{
[InMsgs]	"InMsgs",
[OutMsgs]	"OutMsgs",
[CsumErrs]	"CsumErrs",
[HlenErrs]	"HlenErr",
[LenErrs]	"LenErrs",
[OutOfOrder]	"OutOfOrder",
[Retrans]	"Retrans",
[DupMsg]	"DupMsg",
[DupBytes]	"DupBytes",
};

.
151a
enum
{
	InMsgs,
	OutMsgs,
	CsumErrs,		/* checksum errors */
	HlenErrs,		/* header length error */
	LenErrs,		/* short packet */
	OutOfOrder,		/* out of order */
	Retrans,		/* retransmissions */
	DupMsg,
	DupBytes,
.
## diffname ip/il.c 2000/1121
## diff -e /n/emeliedump/2000/0706/sys/src/9/ip/il.c /n/emeliedump/2000/1121/sys/src/9/ip/il.c
61c
	DeathTime	= 30*QueryTime,
.
## diffname ip/il.c 2000/1220
## diff -e /n/emeliedump/2000/1121/sys/src/9/ip/il.c /n/emeliedump/2000/1220/sys/src/9/ip/il.c
307d
## diffname ip/il.c 2001/0227
## diff -e /n/emeliedump/2000/1220/sys/src/9/ip/il.c /n/emeliedump/2001/0227/sys/src/9/ip/il.c
1244a

	if(fasttimeout){
		/* timeout if we can't connect quickly */
		ic->fasttimeout = 1;
		ic->timeout = msec+Iltickms;
		ic->rexmit = MaxRexmit - 4;
	};
.
1220c
ilstart(Conv *c, int type, int fasttimeout)
.
1208a
	ic->fasttimeout = 0;
.
1094a
	if(ic->fasttimeout)
		ic->timeout = msec+Iltickms;

.
499d
270c
	e = ilstart(c, IL_LISTEN, 0);
.
236c
	return ilstart(c, IL_CONNECT, fast);
.
232a
	fast = argc > 1 && strstr(argv[1], "!fasttimeout") != nil;
.
231a
	int fast;
.
213c
char*	ilstart(Conv*, int, int);
.
102a
	/* if set, fasttimeout causes a connection request to terminate after 4*Iltickms */
	int	fasttimeout;

.
## diffname ip/il.c 2001/0301
## diff -e /n/emeliedump/2001/0227/sys/src/9/ip/il.c /n/emeliedump/2001/0301/sys/src/9/ip/il.c
1269a
		iphtadd(&ipriv->ht, c);
.
1266a
		iphtadd(&ipriv->ht, c);
.
870c
	illocalclose(s);
.
698,700c
			if(id != ic->rstart || ack != 0){
				illocalclose(s);
			} else {
.
644d
641d
637,638c
	ilprocess(s, ih, bp);
	qunlock(s);
.
634c
		qunlock(s);
.
604,631c
	qlock(s);
.
601a
	
		ic = (Ilcb*)s->ptcl;
	
		ic->conv = s;
		ic->state = Ilsyncee;
		ilcbinit(ic);
		ic->rstart = nhgetl(ih->ilid);
		iphtadd(&ipriv->ht, s);
.
594,600c
		s = Fsnewcall(s, raddr, dp, laddr, sp);
		if(s == nil){
			qunlock(il);
			netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
			ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
			goto raise;
.
586,592c
	ic = (Ilcb*)s->ptcl;
	if(ic->state == Illistening){
		if(ih->iltype != Ilsync){
			qunlock(il);
			if(ih->iltype < 0 || ih->iltype > Ilclose)
				st = "?";
			else
				st = iltype[ih->iltype];
			ilreject(il->f, ih);		/* no channel and not sync */
			netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
				st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp); 
			goto raise;
		}
.
576,582d
555,574c
	s = iphtlook(&ipriv->ht, raddr, dp, laddr, sp);
	if(s == nil){
.
541a
	v4tov6(laddr, ih->dst);
.
519c
	Conv *s;
.
306,308c
		illocalclose(c);
.
282a
void
illocalclose(Conv *c)
{
	Ilcb *ic;
	Ilpriv *ipriv;

	ipriv = c->p->priv;
	ic = (Ilcb*)c->ptcl;
	ic->state = Ilclosed;
	iphtrem(&ipriv->ht, c);
	ipmove(c->laddr, IPnoaddr);
	c->lport = 0;
}

.
225c
void	illocalclose(Conv *c);
.
196c
	Rendez	ilr;
.
188,194c
	ulong	csumerr;		/* checksum errors */
	ulong	hlenerr;		/* header length error */
	ulong	lenerr;			/* short packet */
	ulong	order;			/* out of order */
	ulong	rexmit;			/* retransmissions */
	ulong	dup;
	ulong	dupb;
.
185a
	Ipht	ht;

.
## diffname ip/il.c 2001/0302
## diff -e /n/emeliedump/2001/0301/sys/src/9/ip/il.c /n/emeliedump/2001/0302/sys/src/9/ip/il.c
687a
				ic->fasttimeout = 0;
				ic->rexmit = 0;
.
681a
				ic->fasttimeout = 0;
				ic->rexmit = 0;
.
655a
				ic->fasttimeout = 0;
				ic->rexmit = 0;
.
571a
		if(ih->iltype == Ilsync)
			ilreject(il->f, ih);		/* no listener */
.
517a
		ic->rexmit = 0;
.
## diffname ip/il.c 2001/0303
## diff -e /n/emeliedump/2001/0302/sys/src/9/ip/il.c /n/emeliedump/2001/0303/sys/src/9/ip/il.c
239c
	/* huge hack to quickly try an il connection */
	fast = 0;
	if(argc > 1){
		p = strstr(argv[1], "!fasttimeout");
		if(p != nil){
			*p = 0;
			fast = 1;
		}
	}

.
236c
	char *e, *p;
.
## diffname ip/il.c 2001/0306
## diff -e /n/emeliedump/2001/0303/sys/src/9/ip/il.c /n/emeliedump/2001/0306/sys/src/9/ip/il.c
347,349d
338c
ilkick(Conv *c)
.
## diffname ip/il.c 2001/0527
## diff -e /n/emeliedump/2001/0306/sys/src/9/ip/il.c /n/emeliedump/2001/0527/sys/src/9/ip/il.c
1221c
	char kpname[KNAMELEN];
.
## diffname ip/il.c 2001/0623
## diff -e /n/emeliedump/2001/0527/sys/src/9/ip/il.c /n/emeliedump/2001/0623/sys/src/9/ip/il.c
531c
iliput(Proto *il, Ipifc*, Block *bp)
.
221c
void	iliput(Proto*, Ipifc*, Block*);
.
## diffname ip/il.c 2001/0823
## diff -e /n/emeliedump/2001/0623/sys/src/9/ip/il.c /n/emeliedump/2001/0823/sys/src/9/ip/il.c
1016a
if(ipc==nil)
	panic("ipc is nil caller is %.8lux", getcallerpc(&ipc));
if(ipc->p==nil)
	panic("ipc->p is nil");
.
606c
		s = new;

.
599,600c
		new = Fsnewcall(s, raddr, dp, laddr, sp);
		if(new == nil){
.
540c
	Conv *new, *s;
.
## diffname ip/il.c 2001/0922
## diff -e /n/emeliedump/2001/0823/sys/src/9/ip/il.c /n/emeliedump/2001/0922/sys/src/9/ip/il.c
1389c
	il->nc = scalednconv();
.
## diffname ip/il.c 2002/0507
## diff -e /n/emeliedump/2001/0922/sys/src/9/ip/il.c /n/emeliedump/2002/0507/sys/src/9/ip/il.c
1060c
	ipoput4(f, bp, 0, MAXTTL, DFLTTOS);
.
1039a
	ih->vihl = IP_VER4;
.
1027c
	ipoput4(ipc->p->f, bp, 0, ttl, tos);
.
1017a

.
981a
	ih->vihl = IP_VER4;
.
822c
	ipoput4(c->p->f, nb, 0, ic->conv->ttl, ic->conv->tos);
.
805a
	h->vihl = IP_VER4;
.
411c
	ipoput4(f, bp, 0, c->ttl, c->tos);
.
369a
	ih->vihl = IP_VER4;
.
## diffname ip/il.c 2002/0601
## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/il.c /n/emeliedump/2002/0601/sys/src/9/ip/il.c
600c
		new = Fsnewcall(s, raddr, dp, laddr, sp, V4);
.
## diffname ip/il.c 2002/0710
## diff -e /n/emeliedump/2002/0601/sys/src/9/ip/il.c /n/emeliedump/2002/0710/sys/src/9/ip/il.c
1256c
		ic->timeout = NOW+Iltickms;
.
1221,1222c
	ic->querytime = NOW + QueryTime;
	ic->lastrecv = NOW;	/* or we'll timeout right away */
.
1185c
			if(later(NOW, ic->timeout, "timeout2")) {
.
1181c
				ic->querytime = NOW + QueryTime;
.
1174,1175c
			if(later(NOW, ic->querytime, "querytime")){
				if(later(NOW, ic->lastrecv+DeathTime, "deathtime")){
.
1171c
			if(later(NOW, ic->acktime, "acktime"))
.
1159c
			if(later(NOW, ic->timeout, "timeout1")) {
.
1147c
			if(later(NOW, ic->timeout, "timeout0")) {
.
1099c
		ic->timeout = NOW+Iltickms;
.
1096c
	ic->timeout = NOW + pt;
.
1079c
	ic->timeout = NOW + pt;
.
1010c
		ic->acktime = NOW;
.
644,645c
	ic->lastrecv = NOW;
	ic->querytime = NOW + QueryTime;
.
410c
	if(later(NOW, ic->timeout, nil))
.
390c
	ic->acktime = NOW + AckDelay;
.
## diffname ip/il.c 2002/0711
## diff -e /n/emeliedump/2002/0710/sys/src/9/ip/il.c /n/emeliedump/2002/0711/sys/src/9/ip/il.c
419c
	c->rq = qopen(64*1024, Qmsg, 0, c);
.
## diffname ip/il.c 2002/0712
## diff -e /n/emeliedump/2002/0711/sys/src/9/ip/il.c /n/emeliedump/2002/0712/sys/src/9/ip/il.c
1381d
420c
	c->wq = qopen(64*1024, Qkick, ilkick, c);
.
339a
	Conv *c = x;
.
338c
ilkick(void *x)
.
## diffname ip/il.c 2002/0719
## diff -e /n/emeliedump/2002/0712/sys/src/9/ip/il.c /n/emeliedump/2002/0719/sys/src/9/ip/il.c
420c
	c->rq = qopen(64*1024, 0, 0, c);
.
## diffname ip/il.c 2003/0220
## diff -e /n/emeliedump/2002/0719/sys/src/9/ip/il.c /n/emeliedump/2003/0220/sys/src/9/ip/il.c
421c
	c->wq = qbypass(ilkick, c);
.
353d
345d
338c
ilkick(void *x, Block *bp)
.
## diffname ip/il.c 2003/0308
## diff -e /n/emeliedump/2003/0220/sys/src/9/ip/il.c /n/emeliedump/2003/0308/sys/src/9/ip/il.c
1064c
	ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);
.
1030c
	ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);
.
823c
	ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c);
.
411c
	ipoput4(f, bp, 0, c->ttl, c->tos, c);
.
## diffname ip/il.c 2003/0407
## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/il.c /n/emeliedump/2003/0407/sys/src/9/ip/il.c
1136c
	tsleep(&up->sleep, return0, 0, Iltickms);
.
1133d
1130d
198,199d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].