~kris/9p

9hist

60a9b49c675c8ab381d1bec8bef4b761df863a0a — David du Colombier 27 years ago 94eb2a8
Plan 9 from Bell Labs 1998-11-18
3 files changed, 119 insertions(+), 44 deletions(-)

M ip/ip.h
M ip/rudp.c
M ip/tcp.c
M ip/ip.h => ip/ip.h +7 -0
@@ 12,6 12,7 @@ typedef struct	Ipmux	Ipmux;
typedef struct	IProuter IProuter;
typedef struct	Ipifc	Ipifc;
typedef struct	Log	Log;
typedef struct	Ifclog	Ifclog;
typedef struct	Medium	Medium;
typedef struct	Proto	Proto;
typedef struct	Pstate	Pstate;


@@ 258,6 259,7 @@ struct Fs
	Route	*queue;			/* used as temp when reinjecting routes */

	Log	*alog;
	Ifclog	*ilog;
};

int	Fsconnected(Conv*, char*);


@@ 302,6 304,11 @@ void	netlogclose(Fs*);
char*	netlogctl(Fs*, char*, int);
long	netlogread(Fs*, void*, ulong, long);
void	netlog(Fs*, int, char*, ...);
void	ifcloginit(Fs*);
long	ifclogread(Fs*, Chan *,void*, ulong, long);
void	ifclog(Fs*, uchar *, int);
void	ifclogopen(Fs*, Chan*);
void	ifclogclose(Fs*, Chan*);

/*
 *  iproute.c

M ip/rudp.c => ip/rudp.c +53 -28
@@ 161,10 161,6 @@ struct Rudppriv
static ulong generation = 0;
static Rendez rend;

/* Used only for debugging */
static ushort drop = 0;
static ushort drop_rate = 10;

/*
 *  protocol specific part of Conv
 */


@@ 173,6 169,7 @@ struct Rudpcb
{
	QLock;
	uchar	headers;
	uchar	randdrop;
	Reliable *r;
};



@@ 261,6 258,15 @@ rudpclose(Conv *c)
	Rudpcb *ucb;
	Reliable *r, *nr;

	/* force out any delayed acks */
	ucb = (Rudpcb*)c->ptcl;
	qlock(ucb);
	for(r = ucb->r; r; r = r->next){
		if(r->acksent != r->rcvseq)
			relsendack(c, r);
	}
	qunlock(ucb);

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


@@ 269,10 275,12 @@ rudpclose(Conv *c)
	c->lport = 0;
	c->rport = 0;

	ucb = (Rudpcb*)c->ptcl;
	ucb->headers = 0;
	ucb->randdrop = 0;
	qlock(ucb);
	for(r = ucb->r; r; r = nr){
		if(r->acksent != r->rcvseq)
			relsendack(c, r);
		nr = r->next;
		relhangup(c, r);
		free(r);


@@ 284,6 292,21 @@ rudpclose(Conv *c)
	unlock(c);
}

/*
 *  randomly don't send packets
 */
static void
doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl)
{
	Rudpcb *ucb;

	ucb = (Rudpcb*)c->ptcl;
	if(ucb->randdrop && nrand(10) == 1)
		freeblist(bp);
	else
		ipoput(f, bp, x, ttl);
}

int
flow(Reliable *r)
{


@@ 411,7 434,7 @@ rudpkick(Conv *c, int)
	DPRINT("sent: %lud/%lud, %lud/%lud\n", 
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);

	ipoput(f, bp, 0, c->ttl);
	doipoput(c, f, bp, 0, c->ttl);

	/* flow control of sorts */
	qlock(&r->lock);


@@ 593,6 616,9 @@ rudpctl(Conv *c, char **f, int n)
		} else if(strcmp(f[0], "headers") == 0){
			ucb->headers = 6;
			return nil;
		} else if(strcmp(f[0], "randdrop") == 0){
			ucb->randdrop = 1;
			return nil;
		}
	}
	return "unknown control request";


@@ 802,6 828,19 @@ reliput(Conv *c, Block *bp, uchar *addr, ushort port)
	DPRINT("rcvd %lud/%lud, %lud/%lud, r->sndgen = %lud\n", 
		seq, sgen, ack, agen, r->sndgen);

	/* make sure we're not talking to a new remote side */
	if(r->rcvgen != sgen){
		if(seq != 1)
			return -1;

		/* new connection */
		if(r->rcvgen != 0){
			DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
			relhangup(c, r);
		}
		r->rcvgen = sgen;
	}

	/* dequeue acked packets */
	if(ack && agen == r->sndgen){
		ackreal = 0;


@@ 833,29 872,10 @@ reliput(Conv *c, Block *bp, uchar *addr, ushort port)
		
	}

	/* make sure we're not talking to a new remote side */
	if(r->rcvgen != sgen){
		if(seq != 1)
			return -1;

		/* new connection */
		if(r->rcvgen != 0){
			DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
			relhangup(c, r);
		}
		r->rcvgen = sgen;
	}

	/* no message or input queue full */
	if(seq == 0 || qfull(c->rq))
		return -1;

	if(DEBUG && ++drop == drop_rate){
		DPRINT("drop pkt on purpose\n");
		drop = 0;
		return -1;
	}

	/* refuse out of order delivery */
	if(seq != NEXTSEQ(r->rcvseq)){
		relsendack(c, r);	/* tell him we got it already */


@@ 913,16 933,21 @@ relsendack(Conv *c, Reliable *r)
	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));

	DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
	ipoput(f, bp, 0, c->ttl);
	doipoput(c, f, bp, 0, c->ttl);
}

/*
 *  called with ucb locked (and c locked if user initiated close)
 */
void
relhangup(Conv *, Reliable *r)
relhangup(Conv *c, Reliable *r)
{
	int n;
	Block *bp;
	char hup[ERRLEN];

	n = snprint(hup, sizeof(hup), "hangup %I!%d", r->addr, r->port);
	qproduce(c->eq, hup, n);

	/*
	 *  dump any unacked outgoing messages


@@ 965,5 990,5 @@ relrexmit(Conv *c, Reliable *r)
	upriv->rxmits++;
	np = copyblock(r->unacked, blocklen(r->unacked));
	DPRINT("rxmit r->ackrvcd+1 = %lud\n", r->ackrcvd+1);
	ipoput(f, np, 0, c->ttl);
	doipoput(c, f, np, 0, c->ttl);
}

M ip/tcp.c => ip/tcp.c +59 -16
@@ 38,6 38,7 @@ enum
	MSPTICK		= 50,		/* Milliseconds per timer tick */
	DEF_MSS		= 1024,		/* Default mean segment */
	DEF_RTT		= 150,		/* Default round trip */
	DEF_KAT		= 10000,	/* Default keep alive trip in ms */
	TCP_LISTEN	= 0,		/* Listen connection */
	TCP_CONNECT	= 1,		/* Outgoing connection */



@@ 171,11 172,11 @@ struct Tcpctl
	Timer	timer;			/* Activity timer */
	Timer	acktimer;		/* Acknowledge timer */
	Timer	rtt_timer;		/* Round trip timer */
	Timer	katimer;		/* keep alive timer */
	ulong	rttseq;			/* Round trip sequence */
	int	srtt;			/* Shortened round trip */
	int	mdev;			/* Mean deviation of round trip */
	int	kacounter;		/* count down for keep alive */
	int	f2counter;		/* count down for finwait2 state */
	uint	sndsyntime;		/* time syn sent */

	Tcphdr	protohdr;		/* prototype header */


@@ 237,6 238,7 @@ void	tcptimeout(void*);
void	tcpsndsyn(Tcpctl*);
void	tcprcvwin(Conv*);
void	tcpacktimer(Conv*);
void	tcpkeepalive(Conv*);

void
tcpsetstate(Conv *s, uchar newstate)


@@ 554,6 556,7 @@ localclose(Conv *s, char *reason)	 /*  called with tcb locked */
	tcphalt(tpriv, &tcb->timer);
	tcphalt(tpriv, &tcb->rtt_timer);
	tcphalt(tpriv, &tcb->acktimer);
	tcphalt(tpriv, &tcb->katimer);

	/* Flush reassembly queue; nothing more can arrive */
	for(rp = tcb->reseq; rp != nil; rp = rp1) {


@@ 594,6 597,10 @@ inittcpctl(Conv *s)
	tcb->acktimer.start = TCP_ACK / MSPTICK;
	tcb->acktimer.func = tcpacktimer;
	tcb->acktimer.arg = s;
	tcb->kacounter = 0;
	tcb->katimer.start = DEF_KAT / MSPTICK;
	tcb->katimer.func = tcpkeepalive;
	tcb->katimer.arg = s;

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


@@ 1007,8 1014,6 @@ update(Conv *s, Tcp *seg)
	tpriv = s->p->priv;
	tcb = (Tcpctl*)s->ptcl;

	tcb->kacounter = MAXBACKOFF;	/* keep alive count down */

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


@@ 1224,6 1229,9 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
	tcb = (Tcpctl*)s->ptcl;
	qlock(tcb);

	if(tcb->kacounter > 0)
		tcb->kacounter = MAXBACKOFF;

	switch(tcb->state) {
	case Closed:
		sndrst(tcp, source, dest, length, &seg);


@@ 1343,9 1351,9 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
		case Finwait1:
			update(s, &seg);
			if(tcb->sndcnt == 0){
				tcb->f2counter = MAXBACKOFF;
				tcb->kacounter = MAXBACKOFF;
				tcpsetstate(s, Finwait2);
				tcb->timer.start = MSL2 * (1000 / MSPTICK);
				tcb->katimer.start = MSL2 * (1000 / MSPTICK);
				tcpgo(tpriv, &tcb->timer);
			}
			break;


@@ 1686,6 1694,8 @@ tcpoutput(Conv *s)
		}

		tpriv->tstats.tcpOutSegs++;
		if(tcb->kacounter > 0)
			tcpgo(tpriv, &tcb->katimer);
		ipoput(f, hbp, 0, s->ttl);
	}
}


@@ 1694,7 1704,7 @@ tcpoutput(Conv *s)
 *  the BSD convention (hack?) for keep alives.  resend last uchar acked.
 */
void
tcpkeepalive(Conv *s)
tcpsendka(Conv *s)
{
	Tcp seg;
	Tcpctl *tcb;


@@ 1730,6 1740,47 @@ tcpkeepalive(Conv *s)
	ipoput(s->p->f, hbp, 0, s->ttl);
}

/*
 *  if we've timed out, close the connection
 *  otherwise, send a keepalive and restart the timer
 */
void
tcpkeepalive(Conv *s)
{
	Tcpctl *tcb;

	tcb = (Tcpctl*)s->ptcl;
	if(--(tcb->kacounter) <= 0)
		localclose(s, Etimedout);
	else {
		qlock(tcb);
		tcpsendka(s);
		qunlock(tcb);
		tcpgo(s->p->priv, &tcb->katimer);
	}
}

/*
 *  start keepalive timer
 */
char*
tcpstartka(Conv *s, char **f, int n)
{
	Tcpctl *tcb;
	int x;

	tcb = (Tcpctl*)s->ptcl;
	if(n > 1){
		x = atoi(f[1]);
		if(x >= MSPTICK)
			tcb->katimer.start = x/MSPTICK;
	}
	tcb->kacounter = MAXBACKOFF;
	tcpgo(s->p->priv, &tcb->katimer);

	return nil;
}

void
tcprxmit(Conv *s)
{


@@ 1782,16 1833,6 @@ tcptimeout(void *arg)
		}
		tcprxmit(s);
		break;
	case Finwait2:
		if(--(tcb->f2counter) <= 0)
			localclose(s, Etimedout);
		else {
			qlock(tcb);
			tcpkeepalive(s);
			qunlock(tcb);
			tcpgo(s->p->priv, &tcb->timer);
		}
		break;
	case Time_wait:
		localclose(s, nil);
		break;


@@ 2001,6 2042,8 @@ tcpctl(Conv* c, char** f, int n)
{
	if(n == 1 && strcmp(f[0], "hangup") == 0)
		return tcphangup(c);
	if(n >= 1 && strcmp(f[0], "keepalive") == 0)
		return tcpstartka(c, f, n);
	return "unknown control request";
}