18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1990, 1993
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met:
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    documentation and/or other materials provided with the distribution.
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    may be used to endorse or promote products derived from this software
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    without specific prior written permission.
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE.
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	@(#)tcp_timer.c	8.1 (Berkeley) 6/10/93
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h>
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef LOG_ENABLED
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct   tcpstat tcpstat;        /* tcp statistics */
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectu_int32_t        tcp_now;                /* for RFC 1323 timestamps */
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Fast timeout routine for processing delayed acks
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_fasttimo(void)
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct socket *so;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpcb *tp;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_fasttimo");
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so = tcb.so_next;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so)
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (; so != &tcb; so = so->so_next)
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if ((tp = (struct tcpcb *)so->so_tcpcb) &&
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    (tp->t_flags & TF_DELACK)) {
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_flags &= ~TF_DELACK;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_flags |= TF_ACKNOW;
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			STAT(tcpstat.tcps_delack++);
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			(void) tcp_output(tp);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Tcp protocol timeout routine called every 500 ms.
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Updates the timers in all active tcb's and
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * causes finite state machine actions if timers expire.
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_slowtimo(void)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct socket *ip, *ipnxt;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpcb *tp;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register int i;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_slowtimo");
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Search through tcb's and update active timers.
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ip = tcb.so_next;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (ip == 0)
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   return;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (; ip != &tcb; ip = ipnxt) {
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		ipnxt = ip->so_next;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp = sototcpcb(ip);
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tp == 0)
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			continue;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		for (i = 0; i < TCPT_NTIMERS; i++) {
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				tcp_timers(tp,i);
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (ipnxt->so_prev != ip)
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					goto tpgone;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			}
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_idle++;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tp->t_rtt)
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   tp->t_rtt++;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttpgone:
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;		/* increment iss */
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCP_COMPAT_42
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((int)tcp_iss < 0)
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_iss = 0;				/* XXX */
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_now++;					/* for timestamps */
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Cancel all timers for TCP tp.
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_canceltimers(struct tcpcb *tp)
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register int i;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (i = 0; i < TCPT_NTIMERS; i++)
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_timer[i] = 0;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP timer processing.
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct tcpcb *
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_timers(register struct tcpcb *tp, int timer)
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register int rexmt;
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_timers");
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	switch (timer) {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * 2 MSL timeout in shutdown went off.  If we're closed but
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * still waiting for peer to close and connection has been idle
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * too long, or if 2MSL time is up from TIME_WAIT, delete connection
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * control block.  Otherwise, check again in a bit.
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPT_2MSL:
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tp->t_state != TCPS_TIME_WAIT &&
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    tp->t_idle <= TCP_MAXIDLE)
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		else
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp = tcp_close(tp);
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Retransmission timer went off.  Message has not
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * been acked within retransmit interval.  Back off
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * to a longer retransmit interval and retransmit one segment.
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPT_REXMT:
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * XXXXX If a packet has timed out, then remove all the queued
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * packets for that session.
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * This is a hack to suit our terminal server here at the uni of canberra
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * since they have trouble with zeroes... It usually lets them through
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * unharmed, but under some conditions, it'll eat the zeros.  If we
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * keep retransmitting it, it'll keep eating the zeroes, so we keep
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * retransmitting, and eventually the connection dies...
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * (this only happens on incoming data)
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 *
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * So, if we were gonna drop the connection from too many retransmits,
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * don't... instead halve the t_maxseg, which might break up the NULLs and
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * let them through
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 *
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * *sigh*
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_maxseg >>= 1;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (tp->t_maxseg < 32) {
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/*
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * We tried our best, now the connection must die!
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				tp->t_rxtshift = TCP_MAXRXTSHIFT;
1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				STAT(tcpstat.tcps_timeoutdrop++);
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				tp = tcp_drop(tp, tp->t_softerror);
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return (tp); /* XXX */
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			}
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * Set rxtshift to 6, which is still at the maximum
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * backoff time
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_rxtshift = 6;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_rexmttimeo++);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		TCPT_RANGESET(tp->t_rxtcur, rexmt,
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * If losing, let the lower level know and try for
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * a better route.  Also, if we backed off this far,
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * our srtt estimate is probably bogus.  Clobber it
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * so we'll take the next rtt measurement as our srtt;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * move the current srtt into rttvar to keep the current
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * retransmit times until then.
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*			in_losing(tp->t_inpcb); */
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tp->t_srtt = 0;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->snd_nxt = tp->snd_una;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * If timing a segment in this window, stop the timer.
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_rtt = 0;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Close the congestion window down to one segment
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * (we'll open it by one segment for each ack we get).
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Since we probably have a window's worth of unacked
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * data accumulated, this "slow start" keeps us from
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * dumping all that data as back-to-back packets (which
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * might overwhelm an intermediate gateway).
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * There are two phases to the opening: Initially we
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * open by one mss on each ack.  This makes the window
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * size increase exponentially with time.  If the
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * window is larger than the path can handle, this
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * exponential growth results in dropped packet(s)
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * almost immediately.  To get more time between
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * drops but still "push" the network to take advantage
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * of improving conditions, we switch from exponential
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * to linear window opening at some threshold size.
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * For a threshold, we use half the current window
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * size, truncated to a multiple of the mss.
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * (the minimum cwnd that will give us exponential
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * growth is 2 mss.  We don't allow the threshold
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * to go below this.)
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		{
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (win < 2)
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			win = 2;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->snd_cwnd = tp->t_maxseg;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->snd_ssthresh = win * tp->t_maxseg;
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_dupacks = 0;
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		(void) tcp_output(tp);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Persistence timer into zero window.
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Force a byte to be output, if possible.
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPT_PERSIST:
2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_persisttimeo++);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_setpersist(tp);
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_force = 1;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		(void) tcp_output(tp);
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_force = 0;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Keep-alive timer went off; send something
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * or drop connection if idle for too long.
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPT_KEEP:
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_keeptimeo++);
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tp->t_state < TCPS_ESTABLISHED)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			goto dropit;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*		if (tp->t_socket->so_options & SO_KEEPALIVE && */
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    	if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				goto dropit;
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * Send a packet designed to force a response
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * if the peer is up and reachable:
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * either an ACK if the connection is still alive,
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * or an RST if the peer has closed the connection
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * due to timeout or reboot.
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * Using sequence number tp->snd_una-1
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * causes the transmitted zero-length segment
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * to lie outside the receive window;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * by the protocol spec, this requires the
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * correspondent TCP to respond.
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			STAT(tcpstat.tcps_keepprobe++);
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCP_COMPAT_42
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * The keepalive packet must have nonzero length
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * to get a 4.2 host to respond.
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			    tp->rcv_nxt - 1, tp->snd_una - 1, 0);
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			    tp->rcv_nxt, tp->snd_una - 1, 0);
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	dropit:
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_keepdrops++);
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return (tp);
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
319