~kris/9p

9hist

6297ba31013f1b1c8fdde78eb70d53af96432390 — David du Colombier 23 years ago 81ed157
Plan 9 from Bell Labs 2003-02-09
M alphapc/etherif.h => alphapc/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {

	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	int	minmtu;
	int 	maxmtu;
	uchar	ea[Eaddrlen];

M bitsy/etherif.h => bitsy/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {

	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	int	minmtu;
	int 	maxmtu;
	uchar	ea[Eaddrlen];

M ip/ethermedium.c => ip/ethermedium.c +23 -17
@@ 35,8 35,8 @@ Medium ethermedium =
{
.name=		"ether",
.hsize=		14,
.minmtu=	60,
.maxmtu=	1514,
.mintu=		60,
.maxtu=		1514,
.maclen=	6,
.bind=		etherbind,
.unbind=	etherunbind,


@@ 52,8 52,8 @@ Medium gbemedium =
{
.name=		"gbe",
.hsize=		14,
.minmtu=	60,
.maxmtu=	9014,
.mintu=		60,
.maxtu=		9014,
.maclen=	6,
.bind=		etherbind,
.unbind=	etherunbind,


@@ 161,7 161,7 @@ etherbind(Ipifc *ifc, int argc, char **argv)
	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);

	/*
	 *  get mac address
	 *  get mac address and speed
	 */
	snprint(addr, sizeof(addr), "%s/stats", dir);
	buf = smalloc(512);


@@ 179,9 179,15 @@ etherbind(Ipifc *ifc, int argc, char **argv)
	if(!ptr)
		error(Eio);
	ptr += 6;

	parsemac(ifc->mac, ptr, 6);

	ptr = strstr(buf, "mbps: ");
	if(ptr){
		ptr += 6;
		ifc->mbps = atoi(ptr);
	} else
		ifc->mbps = 100;

	/*
 	 *  open arp conversation
	 */


@@ 287,8 293,8 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
	bp = padblock(bp, ifc->m->hsize);
	if(bp->next)
		bp = concatblock(bp);
	if(BLEN(bp) < ifc->minmtu)
		bp = adjustblock(bp, ifc->minmtu);
	if(BLEN(bp) < ifc->mintu)
		bp = adjustblock(bp, ifc->mintu);
	eh = (Etherhdr*)bp->rp;

	/* copy in mac addresses and ether type */


@@ 331,7 337,7 @@ etherread4(void *a)
		pexit("hangup", 1);
	}
	for(;;){
		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxmtu, 0);
		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
		if(!canrlock(ifc)){
			freeb(bp);
			continue;


@@ 370,7 376,7 @@ etherread6(void *a)
		pexit("hangup", 1);
	}
	for(;;){
		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxmtu, 0);
		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
		if(!canrlock(ifc)){
			freeb(bp);
			continue;


@@ 465,8 471,8 @@ sendarp(Ipifc *ifc, Arpent *a)
	arprelease(er->f->arp, a);

	n = sizeof(Etherarp);
	if(n < a->type->minmtu)
		n = a->type->minmtu;
	if(n < a->type->mintu)
		n = a->type->mintu;
	bp = allocb(n);
	memset(bp->rp, 0, n);
	e = (Etherarp*)bp->rp;


@@ 542,8 548,8 @@ sendgarp(Ipifc *ifc, uchar *ip)
		return;

	n = sizeof(Etherarp);
	if(n < ifc->m->minmtu)
		n = ifc->m->minmtu;
	if(n < ifc->m->mintu)
		n = ifc->m->mintu;
	bp = allocb(n);
	memset(bp->rp, 0, n);
	e = (Etherarp*)bp->rp;


@@ 576,7 582,7 @@ recvarp(Ipifc *ifc)
	static uchar eprinted[4];
	Etherrock *er = ifc->arg;

	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxmtu, 0);
	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
	if(ebp == nil) {
		print("arp: rcv: %r\n");
		return;


@@ 633,8 639,8 @@ recvarp(Ipifc *ifc)
			break;

		n = sizeof(Etherarp);
		if(n < ifc->minmtu)
			n = ifc->minmtu;
		if(n < ifc->mintu)
			n = ifc->mintu;
		rbp = allocb(n);
		r = (Etherarp*)rbp->rp;
		memset(r, 0, sizeof(Etherarp));

M ip/icmp6.c => ip/icmp6.c +1 -1
@@ 543,7 543,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
	memmove(np->dst, p->src, IPaddrlen);
	np->type = PacketTooBigV6;
	np->code = 0;
	hnputl(np->icmpid, ifc->maxmtu - ifc->m->hsize);
	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));
	set_cksum(nbp);
	np->ttl = HOP_LIMIT;

M ip/ip.c => ip/ip.c +1 -1
@@ 294,7 294,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
		goto raise;

	/* If we dont need to fragment just send it */
	medialen = ifc->maxmtu - ifc->m->hsize;
	medialen = ifc->maxtu - ifc->m->hsize;
	if(len <= medialen) {
		if(!gating)
			hnputs(eh->id, incref(&ip->id4));

M ip/ip.h => ip/ip.h +5 -4
@@ 124,8 124,8 @@ struct Medium
{
	char	*name;
	int	hsize;		/* medium header size */
	int	minmtu;		/* default min mtu */
	int	maxmtu;		/* default max mtu */
	int	mintu;		/* default min mtu */
	int	maxtu;		/* default max mtu */
	int	maclen;		/* mac address length  */
	void	(*bind)(Ipifc*, int, char**);
	void	(*unbind)(Ipifc*);


@@ 212,8 212,9 @@ struct Ipifc
	Conv	*conv;		/* link to its conversation structure */
	char	dev[64];	/* device we're attached to */
	Medium	*m;		/* Media pointer */
	int	maxmtu;		/* Maximum transfer unit */
	int	minmtu;		/* Minumum tranfer unit */
	int	maxtu;		/* Maximum transfer unit */
	int	mintu;		/* Minumum tranfer unit */
	int	mbps;		/* megabits per second */
	void	*arg;		/* medium specific */
	int	reassemble;	/* reassemble IP packets before forwarding */


M ip/ipifc.c => ip/ipifc.c +8 -8
@@ 140,8 140,8 @@ ipifcbind(Conv *c, char **argv, int argc)

	/* set up parameters */
	ifc->m = m;
	ifc->minmtu = ifc->m->minmtu;
	ifc->maxmtu = ifc->m->maxmtu;
	ifc->mintu = ifc->m->mintu;
	ifc->maxtu = ifc->m->maxtu;
	if(ifc->m->unbindonclose == 0)
		ifc->conv->inuse++;
	ifc->rp.mflag	= 0;		// default not managed


@@ 226,7 226,7 @@ ipifcunbind(Ipifc *ifc)



char sfixedformat[] = "device %s maxmtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";

char slineformat[] = "	%-40.40I %-10.10M %-40.40I %-12lud %-12lud\n";



@@ 241,7 241,7 @@ ipifcstate(Conv *c, char *state, int n)
	ifc = (Ipifc*)c->ptcl;

	m = snprint(state, n, sfixedformat, 
		ifc->dev, ifc->maxmtu, ifc->sendra6, ifc->recvra6,
		ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
		ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
		ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
		ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,


@@ 358,9 358,9 @@ ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
	if(ifc->m == nil)
		return Ebadarg;
	mtu = strtoul(argv[1], 0, 0);
	if(mtu < ifc->m->minmtu || mtu > ifc->m->maxmtu)
	if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
		return Ebadarg;
	ifc->maxmtu = mtu;
	ifc->maxtu = mtu;
	return nil;
}



@@ 393,8 393,8 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
		/* fall through */
	case 5:
		mtu = strtoul(argv[4], 0, 0);
		if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu)
			ifc->maxmtu = mtu;
		if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
			ifc->maxtu = mtu;
		/* fall through */
	case 4:
		parseip(ip, argv[1]);

M ip/ipv6.c => ip/ipv6.c +1 -1
@@ 222,7 222,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
	}

	/* If we dont need to fragment just send it */
	medialen = ifc->maxmtu - ifc->m->hsize;
	medialen = ifc->maxtu - ifc->m->hsize;
	if(len <= medialen) {
		hnputs(eh->ploadlen, len-IPV6HDR_LEN);
		ifc->m->bwrite(ifc, bp, V6, gate);

M ip/loopbackmedium.c => ip/loopbackmedium.c +2 -2
@@ 103,8 103,8 @@ loopbackread(void *a)
Medium loopbackmedium =
{
.hsize=		0,
.minmtu=	0,
.maxmtu=	Maxtu,
.mintu=		0,
.maxtu=		Maxtu,
.maclen=	0,
.name=		"loopback",
.bind=		loopbackbind,

M ip/netdevmedium.c => ip/netdevmedium.c +5 -5
@@ 24,8 24,8 @@ Medium netdevmedium =
{
.name=		"netdev",
.hsize=		0,
.minmtu=	0,
.maxmtu=	64000,
.mintu=	0,
.maxtu=	64000,
.maclen=	0,
.bind=		netdevbind,
.unbind=	netdevunbind,


@@ 88,8 88,8 @@ netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)

	if(bp->next)
		bp = concatblock(bp);
	if(BLEN(bp) < ifc->minmtu)
		bp = adjustblock(bp, ifc->minmtu);
	if(BLEN(bp) < ifc->mintu)
		bp = adjustblock(bp, ifc->mintu);

	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
	ifc->out++;


@@ 114,7 114,7 @@ netdevread(void *a)
		pexit("hangup", 1);
	}
	for(;;){
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
		if(bp == nil){
			/*
			 * get here if mchan is a pipe and other side hangs up

M ip/pktmedium.c => ip/pktmedium.c +2 -2
@@ 17,8 17,8 @@ Medium pktmedium =
{
.name=		"pkt",
.hsize=		14,
.minmtu=	40,
.maxmtu=	4*1024,
.mintu=	40,
.maxtu=	4*1024,
.maclen=	6,
.bind=		pktbind,
.unbind=	pktunbind,

M ip/tcp.c => ip/tcp.c +150 -46
@@ 29,6 29,7 @@ enum
	TcptimerDONE	= 2,
	MAX_TIME 	= (1<<20),	/* Forever */
	TCP_ACK		= 50,		/* Timed ack sequence in ms */
	MAXBACKMS	= 30000,	/* longest backoff time (ms) before hangup */

	URG		= 0x20,		/* Data marked urgent */
	ACK		= 0x10,		/* Acknowledge is valid */


@@ 39,9 40,10 @@ enum

	EOLOPT		= 0,
	NOOPOPT		= 1,
	MAXBACKMS	= 30000,	/* longest backoff time (ms) before hangup */
	MSSOPT		= 2,
	MSS_LENGTH	= 4,		/* Mean segment size */
	WSOPT		= 3,
	WS_LENGTH	= 3,		/* Bits to scale window size by */
	MSL2		= 10,
	MSPTICK		= 50,		/* Milliseconds per timer tick */
	DEF_MSS		= 1460,		/* Default mean segment */


@@ 77,7 79,9 @@ enum

	Maxlimbo	= 1000,		/* maximum procs waiting for response to SYN ACK */
	NLHT		= 256,		/* hash table size, must be a power of 2 */
	LHTMASK		= NLHT-1
	LHTMASK		= NLHT-1,

	HaveWS		= 1<<8,
};

/* Must correspond to the enumeration above */


@@ 127,8 131,7 @@ struct Tcp4hdr
	uchar	tcpcksum[2];
	uchar	tcpurg[2];
	/* Options segment */
	uchar	tcpopt[2];
	uchar	tcpmss[2];
	uchar	tcpopt[1];
};

typedef struct Tcp6hdr Tcp6hdr;


@@ 149,8 152,7 @@ struct Tcp6hdr
	uchar	tcpcksum[2];
	uchar	tcpurg[2];
	/* Options segment */
	uchar	tcpopt[2];
	uchar	tcpmss[2];
	uchar	tcpopt[1];
};

/*


@@ 167,9 169,10 @@ struct	Tcp
	ulong	seq;
	ulong	ack;
	uchar	flags;
	ushort	wnd;
	ushort	ws;	/* window scale option (if not zero) */
	ulong	wnd;
	ushort	urg;
	ushort	mss;
	ushort	mss;	/* max segment size option (if not zero) */
	ushort	len;	/* size of data */
};



@@ 199,9 202,10 @@ struct Tcpctl
		ulong	una;		/* Unacked data pointer */
		ulong	nxt;		/* Next sequence expected */
		ulong	ptr;		/* Data pointer */
		ushort	wnd;		/* Tcp send window */
		ulong	wnd;		/* Tcp send window */
		ulong	urg;		/* Urgent data pointer */
		ulong	wl2;
		int	scale;		/* how much to right shift window in xmitted packets */
		/* to implement tahoe and reno TCP */
		ulong	dupacks;	/* number of duplicate acks rcvd */
		int	recovery;	/* loss recovery flag */


@@ 209,20 213,23 @@ struct Tcpctl
	} snd;
	struct {
		ulong	nxt;		/* Receive pointer to next uchar slot */
		ushort	wnd;		/* Receive window incoming */
		ulong	wnd;		/* Receive window incoming */
		ulong	urg;		/* Urgent pointer */
		ulong	lastacked;	/* Last ack sent */
		int	blocked;
		int	una;		/* unacked data segs */
		int	scale;		/* how much to left shift window in rcved packets */
	} rcv;
	ulong	iss;			/* Initial sequence number */
	ushort	cwind;			/* Congestion window */
	int	sawwsopt;		/* true if we saw a wsopt on the incoming SYN */
	ulong	cwind;			/* Congestion window */
	int	scale;			/* desired snd.scale */
	ushort	ssthresh;		/* Slow start threshold */
	int	resent;			/* Bytes just resent */
	int	irs;			/* Initial received squence */
	ushort	mss;			/* Mean segment size */
	int	rerecv;			/* Overlap of data rerecevived */
	ushort	window;			/* Recevive window */
	ulong	window;			/* Recevive window */
	uchar	backoff;		/* Exponential backoff counter */
	int	backedoff;		/* ms we've backed off for rexmits */
	uchar	flags;			/* State flags */


@@ 271,6 278,8 @@ struct Limbo
	ulong	irs;		/* initial received sequence */
	ulong	iss;		/* initial sent sequence */
	ushort	mss;		/* mss from the other end */
	ushort	rcvscale;	/* how much to scale rcvd windows */
	ushort	sndscale;	/* how much to scale sent windows */
	ulong	lastsend;	/* last time we sent a synack */
	uchar	version;	/* v4 or v6 */
	uchar	rexmits;	/* number of retransmissions */


@@ 362,9 371,9 @@ void	procsyn(Conv*, Tcp*);
void	tcpiput(Proto*, Ipifc*, Block*);
void	tcpoutput(Conv*);
int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*);
void	tcpstart(Conv*, int, ushort);
void	tcpstart(Conv*, int);
void	tcptimeout(void*);
void	tcpsndsyn(Tcpctl*);
void	tcpsndsyn(Conv*, Tcpctl*);
void	tcprcvwin(Conv*);
void	tcpacktimer(void*);
void	tcpkeepalive(void*);


@@ 372,6 381,7 @@ void	tcpsetkacounter(Tcpctl*);
void    tcprxmit(Conv*);
void	tcpsettimer(Tcpctl*);
void	tcpsynackrtt(Conv*);
void	tcpsetscale(Conv*, Tcpctl*, ushort, ushort);

static void limborexmit(Proto*);
static void limbo(Conv*, uchar*, uchar*, Tcp*, int);


@@ 427,7 437,7 @@ tcpconnect(Conv *c, char **argv, int argc)
	e = Fsstdconnect(c, argv, argc);
	if(e != nil)
		return e;
	tcpstart(c, TCP_CONNECT, QMAX);
	tcpstart(c, TCP_CONNECT);

	return nil;
}


@@ 440,9 450,9 @@ tcpstate(Conv *c, char *state, int n)
	s = (Tcpctl*)(c->ptcl);

	return snprint(state, n,
		"%s srtt %d mdev %d cwin %d swin %d rwin %d timer.start %d timer.count %d rerecv %d\n",
		"%s srtt %d mdev %d cwin %lud swin %lud>>%d rwin %lud>>%d timer.start %d timer.count %d rerecv %d\n",
		tcpstates[s->state], s->srtt, s->mdev,
		s->cwind, s->snd.wnd, s->rcv.wnd,
		s->cwind, s->snd.wnd, s->snd.scale, s->rcv.wnd, s->rcv.scale,
		s->timer.start, s->timer.count, s->rerecv);
}



@@ 463,7 473,7 @@ tcpannounce(Conv *c, char **argv, int argc)
	e = Fsstdannounce(c, argv, argc);
	if(e != nil)
		return e;
	tcpstart(c, TCP_LISTEN, QMAX);
	tcpstart(c, TCP_LISTEN);
	Fsconnected(c, nil);

	return nil;


@@ 554,7 564,7 @@ tcprcvwin(Conv *s)				/* Call with tcb locked */
	Tcpctl *tcb;

	tcb = (Tcpctl*)s->ptcl;
	w = QMAX - qlen(s->rq);
	w = tcb->window - qlen(s->rq);
	if(w < 0)
		w = 0;
	tcb->rcv.wnd = w;


@@ 740,7 750,7 @@ localclose(Conv *s, char *reason)	 /*  called with tcb locked */

/* mtu (- TCP + IP hdr len) of 1st hop */
int
tcpmtu(Proto *tcp, uchar *addr, int version)
tcpmtu(Proto *tcp, uchar *addr, int version, int *scale)
{
	Ipifc *ifc;
	int mtu;


@@ 751,14 761,23 @@ tcpmtu(Proto *tcp, uchar *addr, int version)
	case V4:
		mtu = DEF_MSS;
		if(ifc != nil)
			mtu = ifc->maxmtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
			mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
		break;
	case V6:
		mtu = DEF_MSS6;
		if(ifc != nil)
			mtu = ifc->maxmtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
			mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
		break;
	}
	if(ifc != nil){
		if(ifc->mbps > 100)
			*scale = HaveWS | 3;
		else if(ifc->mbps > 10)
			*scale = HaveWS | 1;
		else
			*scale = HaveWS | 0;
	} else
		*scale = HaveWS | 0;

	return mtu;
}


@@ 769,6 788,7 @@ inittcpctl(Conv *s, int mode)
	Tcpctl *tcb;
	Tcp4hdr* h4;
	Tcp6hdr* h6;
	int mss;

	tcb = (Tcpctl*)s->ptcl;



@@ 790,6 810,8 @@ inittcpctl(Conv *s, int mode)
	tcb->katimer.func = tcpkeepalive;
	tcb->katimer.arg = s;

	mss = DEF_MSS;

	/* create a prototype(pseudo) header */
	if(mode != TCP_LISTEN){
		if(ipcmp(s->laddr, IPnoaddr) == 0)


@@ 813,20 835,28 @@ inittcpctl(Conv *s, int mode)
			hnputs(h6->tcpdport, s->rport);
			ipmove(h6->tcpsrc, s->laddr);
			ipmove(h6->tcpdst, s->raddr);
			mss = DEF_MSS6;
			break;
		default:
			panic("inittcpctl: version %d", s->ipversion);
		}
	}

	tcb->mss = tcb->cwind = tcpmtu(s->p, s->laddr, s->ipversion);
	tcb->mss = tcb->cwind = mss;

	/* default is no window scaling */
	tcb->window = QMAX;
	tcb->rcv.wnd = QMAX;
	tcb->rcv.scale = 0;
	tcb->snd.scale = 0;
	qsetlimit(s->rq, QMAX);
}

/*
 *  called with s qlocked
 */
void
tcpstart(Conv *s, int mode, ushort window)
tcpstart(Conv *s, int mode)
{
	Tcpctl *tcb;
	Tcppriv *tpriv;


@@ 846,10 876,7 @@ tcpstart(Conv *s, int mode, ushort window)

	tcb = (Tcpctl*)s->ptcl;

	/* Send SYN, go into SYN_SENT state */
	inittcpctl(s, mode);
	tcb->window = window;
	tcb->rcv.wnd = window;

	iphtadd(&tpriv->ht, s);
	switch(mode) {


@@ 862,7 889,7 @@ tcpstart(Conv *s, int mode, ushort window)
	case TCP_CONNECT:
		tpriv->stats[ActiveOpens]++;
		tcb->flags |= ACTIVE;
		tcpsndsyn(tcb);
		tcpsndsyn(s, tcb);
		tcpsetstate(s, Syn_sent);
		tcpoutput(s);
		break;


@@ 898,10 925,13 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
	Tcp6hdr *h;
	ushort csum;
	ushort hdrlen;
	uchar *opt;

	hdrlen = TCP6_HDRSIZE;
	if(tcph->mss)
		hdrlen += MSS_LENGTH;
	if(tcph->ws)
		hdrlen += WS_LENGTH;

	if(data) {
		dlen = blocklen(data);


@@ 930,14 960,22 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
	hnputl(h->tcpseq, tcph->seq);
	hnputl(h->tcpack, tcph->ack);
	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
	hnputs(h->tcpwin, tcph->wnd);
	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
	hnputs(h->tcpurg, tcph->urg);

	opt = h->tcpopt;
	if(tcph->mss != 0){
		h->tcpopt[0] = MSSOPT;
		h->tcpopt[1] = MSS_LENGTH;
		hnputs(h->tcpmss, tcph->mss);
		*opt++ = MSSOPT;
		*opt++ = MSS_LENGTH;
		hnputs(opt, tcph->mss);
		opt += 2;
	}
	if(tcph->ws != 0){
		*opt++ = WSOPT;
		*opt++ = WS_LENGTH;
		*opt = tcph->ws;
	}

	if(tcb != nil && tcb->nochecksum){
		h->tcpcksum[0] = h->tcpcksum[1] = 0;
	} else {


@@ 961,10 999,13 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
	Tcp4hdr *h;
	ushort csum;
	ushort hdrlen;
	uchar *opt;

	hdrlen = TCP4_HDRSIZE;
	if(tcph->mss)
		hdrlen += MSS_LENGTH;
	if(tcph->ws)
		hdrlen += WS_LENGTH;

	if(data) {
		dlen = blocklen(data);


@@ 989,14 1030,22 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
	hnputl(h->tcpseq, tcph->seq);
	hnputl(h->tcpack, tcph->ack);
	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
	hnputs(h->tcpwin, tcph->wnd);
	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
	hnputs(h->tcpurg, tcph->urg);

	opt = h->tcpopt;
	if(tcph->mss != 0){
		h->tcpopt[0] = MSSOPT;
		h->tcpopt[1] = MSS_LENGTH;
		hnputs(h->tcpmss, tcph->mss);
		*opt++ = MSSOPT;
		*opt++ = MSS_LENGTH;
		hnputs(opt, tcph->mss);
		opt += 2;
	}
	if(tcph->ws != 0){
		*opt++ = WSOPT;
		*opt++ = WS_LENGTH;
		*opt = tcph->ws;
	}

	if(tcb != nil && tcb->nochecksum){
		h->tcpcksum[0] = h->tcpcksum[1] = 0;
	} else {


@@ 1025,7 1074,7 @@ ntohtcp6(Tcp *tcph, Block **bpp)
	tcph->dest = nhgets(h->tcpdport);
	tcph->seq = nhgetl(h->tcpseq);
	tcph->ack = nhgetl(h->tcpack);
	hdrlen = (h->tcpflag[0] & 0xf0)>>2;
	hdrlen = h->tcpflag[0]>>2;
	if(hdrlen < TCP6_HDRSIZE) {
		freeblist(*bpp);
		return -1;


@@ 1035,6 1084,7 @@ ntohtcp6(Tcp *tcph, Block **bpp)
	tcph->wnd = nhgets(h->tcpwin);
	tcph->urg = nhgets(h->tcpurg);
	tcph->mss = 0;
	tcph->ws = 0;
	tcph->len = nhgets(h->ploadlen) - hdrlen;

	*bpp = pullupblock(*bpp, hdrlen+TCP6_PKT);


@@ 1057,6 1107,10 @@ ntohtcp6(Tcp *tcph, Block **bpp)
			if(optlen == MSS_LENGTH)
				tcph->mss = nhgets(optr+2);
			break;
		case WSOPT:
			if(optlen == WS_LENGTH)
				tcph->ws = HaveWS | *(optr+2);
			break;
		}
		n -= optlen;
		optr += optlen;


@@ 1083,7 1137,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
	tcph->seq = nhgetl(h->tcpseq);
	tcph->ack = nhgetl(h->tcpack);

	hdrlen = (h->tcpflag[0] & 0xf0)>>2;
	hdrlen = h->tcpflag[0]>>2;
	if(hdrlen < TCP4_HDRSIZE) {
		freeblist(*bpp);
		return -1;


@@ 1093,6 1147,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
	tcph->wnd = nhgets(h->tcpwin);
	tcph->urg = nhgets(h->tcpurg);
	tcph->mss = 0;
	tcph->ws = 0;
	tcph->len = nhgets(h->length) - (hdrlen + TCP4_PKT);

	*bpp = pullupblock(*bpp, hdrlen+TCP4_PKT);


@@ 1115,6 1170,10 @@ ntohtcp4(Tcp *tcph, Block **bpp)
			if(optlen == MSS_LENGTH)
				tcph->mss = nhgets(optr+2);
			break;
		case WSOPT:
			if(optlen == WS_LENGTH)
				tcph->ws = HaveWS | *(optr+2);
			break;
		}
		n -= optlen;
		optr += optlen;


@@ 1127,7 1186,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
 *  number and put a SYN on the send queue
 */
void
tcpsndsyn(Tcpctl *tcb)
tcpsndsyn(Conv *s, Tcpctl *tcb)
{
	tcb->iss = (nrand(1<<16)<<16)|nrand(1<<16);
	tcb->rttseq = tcb->iss;


@@ 1138,6 1197,9 @@ tcpsndsyn(Tcpctl *tcb)
	tcb->flgcnt++;
	tcb->flags |= FORCE;
	tcb->sndsyntime = NOW;

	/* set desired mss and scale */
	tcb->mss = tcpmtu(s->p, s->laddr, s->ipversion, &tcb->scale);
}

void


@@ 1204,6 1266,7 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar ve
	seg->wnd = 0;
	seg->urg = 0;
	seg->mss = 0;
	seg->ws = 0;
	switch(version) {
	case V4:
		hbp = htontcp4(seg, nil, &ph4, nil);


@@ 1244,6 1307,7 @@ tcphangup(Conv *s)
		seg.wnd = 0;
		seg.urg = 0;
		seg.mss = 0;
		seg.ws = 0;
		switch(s->ipversion) {
		case V4:
			tcb->protohdr.tcp4hdr.vihl = IP_VER4;


@@ 1274,6 1338,7 @@ sndsynack(Proto *tcp, Limbo *lp)
	Tcp4hdr ph4;
	Tcp6hdr ph6;
	Tcp seg;
	int scale;

	/* make pseudo header */
	switch(lp->version) {


@@ 1305,9 1370,18 @@ sndsynack(Proto *tcp, Limbo *lp)
	seg.ack = lp->irs+1;
	seg.flags = SYN|ACK;
	seg.urg = 0;
	seg.mss = tcpmtu(tcp, lp->laddr, lp->version);
	seg.mss = tcpmtu(tcp, lp->laddr, lp->version, &scale);
	seg.wnd = QMAX;

	/* if the other side set scale, we should too */
	if(lp->rcvscale){
		seg.ws = scale;
		lp->sndscale = scale;
	} else {
		seg.ws = 0;
		lp->sndscale = 0;
	}

	switch(lp->version) {
	case V4:
		hbp = htontcp4(&seg, nil, &ph4, nil);


@@ 1377,6 1451,7 @@ limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version)
		lp->lport = seg->dest;
		lp->rport = seg->source;
		lp->mss = seg->mss;
		lp->rcvscale = seg->ws;
		lp->irs = seg->seq;
		lp->iss = (nrand(1<<16)<<16)|nrand(1<<16);
	}


@@ 1474,6 1549,7 @@ limborst(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
}

/*
 *  come here when we finally get an ACK to our SYN-ACK.
 *  lookup call in limbo.  if found, create a new conversation
 *
 *  called with proto locked


@@ 1558,6 1634,9 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
	if(lp->mss != 0 && lp->mss < tcb->mss)
		tcb->mss = lp->mss;

	/* window scaling */
	tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale);

	/* the congestion window always starts out as a single segment */
	tcb->snd.wnd = segp->wnd;
	tcb->cwind = tcb->mss;


@@ 1664,7 1743,8 @@ update(Conv *s, Tcp *seg)
{
	int rtt, delta;
	Tcpctl *tcb;
	ushort acked, expand;
	ulong acked;
	ulong expand;
	Tcppriv *tpriv;

	tpriv = s->p->priv;


@@ 1752,7 1832,7 @@ update(Conv *s, Tcp *seg)
			expand = ((int)tcb->mss * tcb->mss) / tcb->cwind;

		if(tcb->cwind + expand < tcb->cwind)
			expand = 65535 - tcb->cwind;
			expand = tcb->snd.wnd - tcb->cwind;
		if(tcb->cwind + expand > tcb->snd.wnd)
			expand = tcb->snd.wnd - tcb->cwind;
		if(expand != 0)


@@ 1962,6 2042,9 @@ reset:
	qlock(s);
	qunlock(tcp);

	/* fix up window */
	seg.wnd <<= tcb->rcv.scale;

	if(tcb->kacounter > 0)
		tcb->kacounter = MAXBACKMS / (tcb->katimer.start*MSPTICK);
	if(tcb->kacounter < 3)


@@ 1991,10 2074,11 @@ reset:
				update(s, &seg);
				tcpsynackrtt(s);
				tcpsetstate(s, Established);
				tcpsetscale(s, tcb, seg.ws, tcb->scale);
			}
			else {
				tcb->time = NOW;
				tcpsetstate(s, Syn_received);
				tcpsetstate(s, Syn_received);	/* DLP - shouldn't this be a reset? */
			}

			if(length != 0 || (seg.flags & FIN))


@@ 2340,7 2424,7 @@ tcpoutput(Conv *s)
		}
		ssize = sndcnt-sent;
		if(ssize && usable < 2)
			netlog(s->p->f, Logtcp, "throttled snd.wnd 0x%ux cwind 0x%ux\n",
			netlog(s->p->f, Logtcp, "throttled snd.wnd %lud cwind %lud\n",
				tcb->snd.wnd, tcb->cwind);
		if(usable < ssize)
			ssize = usable;


@@ 2364,6 2448,7 @@ tcpoutput(Conv *s)
		seg.dest = s->rport;
		seg.flags = ACK;
		seg.mss = 0;
		seg.ws = 0;

		switch(tcb->state){
		case Syn_sent:


@@ 2371,7 2456,8 @@ tcpoutput(Conv *s)
			if(tcb->snd.ptr == tcb->iss){
				seg.flags |= SYN;
				dsize--;
				seg.mss = tcpmtu(s->p, s->laddr, s->ipversion);
				seg.mss = tcb->mss;
				seg.ws = tcb->scale;
			}
			break;
		case Syn_received:


@@ 2384,7 2470,8 @@ tcpoutput(Conv *s)
				seg.flags |= SYN;
				dsize = 0;
				ssize = 1;
				seg.mss = tcpmtu(s->p, s->laddr, s->ipversion);
				seg.mss = tcb->mss;
				seg.ws = tcb->scale;
			}
			break;
		}


@@ 2506,6 2593,7 @@ tcpsendka(Conv *s)
	seg.dest = s->rport;
	seg.flags = ACK|PSH;
	seg.mss = 0;
	seg.ws = 0;
	if(tcpporthogdefense)
		seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
	else


@@ 3019,3 3107,19 @@ tcpinit(Fs *fs)

	Fsproto(fs, tcp);
}

void
tcpsetscale(Conv *s, Tcpctl *tcb, ushort rcvscale, ushort sndscale)
{
	if(rcvscale){
		tcb->rcv.scale = rcvscale & 0xff;
		tcb->snd.scale = sndscale & 0xff;
		tcb->window = QMAX<<tcb->snd.scale;
		qsetlimit(s->rq, tcb->window);
	} else {
		tcb->rcv.scale = 0;
		tcb->snd.scale = 0;
		tcb->window = QMAX;
		qsetlimit(s->rq, tcb->window);
	}
}

M ip/tripmedium.c => ip/tripmedium.c +5 -5
@@ 21,8 21,8 @@ static void	tripares(Fs*, int, uchar*, uchar*, int, int);
Medium tripmedium =
{
.name=		"trip",
.minmtu=	20,
.maxmtu=	64*1024,
.mintu=	20,
.maxtu=	64*1024,
.maclen=	LCIMACSIZE,
.bind=		tripbind,
.unbind=	tripunbind,


@@ 140,7 140,7 @@ tripread(void *a)
	er->readp = up;	/* hide identity under a rock for unbind */

	for(;;) {
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
		ifc->in++;
		ipiput4(er->fs, ifc, bp);
	}


@@ 255,8 255,8 @@ sendifcinfo(Ipifc *dest)
			continue;

		mtc.type = T_CTLIFADMIN;
		mtc.maxtu = ifc->maxmtu;
		mtc.mintu = ifc->minmtu;
		mtc.maxtu = ifc->maxtu;
		mtc.mintu = ifc->mintu;

		mtc.port = 0;
		if(ifc->m == &tripmedium) {

M mtx/etherif.h => mtx/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {

	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	int	minmtu;
	int 	maxmtu;
	uchar	ea[Eaddrlen];

M pc/etherif.h => pc/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {

	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	int	minmtu;
	int 	maxmtu;
	uchar	ea[Eaddrlen];

M port/netif.c => port/netif.c +1 -0
@@ 212,6 212,7 @@ netifread(Netif *nif, Chan *c, void *a, long n, ulong offset)
		j += snprint(p+j, READSTR-j, "buffer errs: %d\n", nif->buffs);
		j += snprint(p+j, READSTR-j, "output errs: %d\n", nif->oerrs);
		j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom);
		j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps);
		j += snprint(p+j, READSTR-j, "addr: ");
		for(i = 0; i < nif->alen; i++)
			j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);

M port/netif.h => port/netif.h +1 -0
@@ 74,6 74,7 @@ struct Netif
	/* about net */
	int	limit;			/* flow control */
	int	alen;			/* address length */
	int	mbps;			/* megabits per sec */
	uchar	addr[Nmaxaddr];
	uchar	bcast[Nmaxaddr];
	Netaddr	*maddr;			/* known multicast addresses */