Change the way receive idle time and round trip time are measured.

Instead of incrementing t_idle and t_rtt in tcp_slowtimo(), we now
take a timstamp (via tcp_now) and use subtraction to compute the
delta when we actually need it (using unsigned arithmetic so that
tcp_now wrapping is handled correctly).

Based on similar changes in FreeBSD.
This commit is contained in:
thorpej 2001-09-10 15:23:09 +00:00
parent 7c233db184
commit 7446fd2bc8
4 changed files with 36 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_input.c,v 1.127 2001/07/08 16:18:57 abs Exp $ */
/* $NetBSD: tcp_input.c,v 1.128 2001/09/10 15:23:09 thorpej Exp $ */
/*
%%% portions-copyright-nrl-95
@ -1252,7 +1252,7 @@ after_listen:
* Segment received on connection.
* Reset idle time and keep-alive timer.
*/
tp->t_idle = 0;
tp->t_rcvtime = tcp_now;
if (TCPS_HAVEESTABLISHED(tp->t_state))
TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle);
@ -1306,9 +1306,10 @@ after_listen:
if (opti.ts_present && opti.ts_ecr)
tcp_xmit_timer(tp,
TCP_TIMESTAMP(tp) - opti.ts_ecr + 1);
else if (tp->t_rtt &&
else if (tp->t_rtttime &&
SEQ_GT(th->th_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
tcp_xmit_timer(tp,
tcp_now - tp->t_rtttime);
acked = th->th_ack - tp->snd_una;
tcpstat.tcps_rcvackpack++;
tcpstat.tcps_rcvackbyte += acked;
@ -1459,8 +1460,8 @@ after_listen:
* if we didn't have to retransmit the SYN,
* use its rtt as our initial srtt & rtt var.
*/
if (tp->t_rtt)
tcp_xmit_timer(tp, tp->t_rtt);
if (tp->t_rtttime)
tcp_xmit_timer(tp, tcp_now - tp->t_rtttime);
} else
tp->t_state = TCPS_SYN_RECEIVED;
@ -1789,7 +1790,7 @@ after_listen:
tp->snd_ssthresh = win * tp->t_segsz;
tp->snd_recover = tp->snd_max;
TCP_TIMER_DISARM(tp, TCPT_REXMT);
tp->t_rtt = 0;
tp->t_rtttime = 0;
tp->snd_nxt = th->th_ack;
tp->snd_cwnd = tp->t_segsz;
(void) tcp_output(tp);
@ -1849,8 +1850,8 @@ after_listen:
*/
if (opti.ts_present && opti.ts_ecr)
tcp_xmit_timer(tp, TCP_TIMESTAMP(tp) - opti.ts_ecr + 1);
else if (tp->t_rtt && SEQ_GT(th->th_ack, tp->t_rtseq))
tcp_xmit_timer(tp,tp->t_rtt);
else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tcp_now - tp->t_rtttime);
/*
* If all outstanding data is acked, stop retransmit
@ -2425,13 +2426,11 @@ tcp_pulloutofband(so, th, m, off)
void
tcp_xmit_timer(tp, rtt)
struct tcpcb *tp;
short rtt;
uint32_t rtt;
{
short delta;
short rttmin;
int32_t delta;
tcpstat.tcps_rttupdated++;
--rtt;
if (tp->t_srtt != 0) {
/*
* srtt is stored as fixed point with 3 bits after the
@ -2467,7 +2466,7 @@ tcp_xmit_timer(tp, rtt)
tp->t_srtt = rtt << (TCP_RTT_SHIFT + 2);
tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT + 2 - 1);
}
tp->t_rtt = 0;
tp->t_rtttime = 0;
tp->t_rxtshift = 0;
/*
@ -2481,11 +2480,8 @@ tcp_xmit_timer(tp, rtt)
* statistical, we have to test that we don't drop below
* the minimum feasible timer (which is 2 ticks).
*/
if (tp->t_rttmin > rtt + 2)
rttmin = tp->t_rttmin;
else
rttmin = rtt + 2;
TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), rttmin, TCPTV_REXMTMAX);
TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX);
/*
* We received an ack for a packet that wasn't retransmitted;
@ -2519,7 +2515,7 @@ tcp_newreno(tp, th)
* offset in tcp_output().
*/
TCP_TIMER_DISARM(tp, TCPT_REXMT);
tp->t_rtt = 0;
tp->t_rtttime = 0;
tp->snd_nxt = th->th_ack;
/*
* Set snd_cwnd to one segment beyond ACK'd offset. snd_una

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.72 2001/09/10 04:43:35 thorpej Exp $ */
/* $NetBSD: tcp_output.c,v 1.73 2001/09/10 15:23:10 thorpej Exp $ */
/*
%%% portions-copyright-nrl-95
@ -467,7 +467,7 @@ tcp_output(tp)
(tcp_cwm_burstsize * txsegsize) +
(tp->snd_nxt - tp->snd_una));
} else {
if (idle && tp->t_idle >= tp->t_rxtcur) {
if (idle && (tcp_now - tp->t_rcvtime) >= tp->t_rxtcur) {
/*
* We have been idle for "a while" and no acks are
* expected to clock out any data we send --
@ -938,8 +938,8 @@ send:
* Time this transmission if not a retransmission and
* not currently timing anything.
*/
if (tp->t_rtt == 0) {
tp->t_rtt = 1;
if (tp->t_rtttime == 0) {
tp->t_rtttime = tcp_now;
tp->t_rtseq = startseq;
tcpstat.tcps_segstimed++;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_timer.c,v 1.49 2001/09/10 04:24:25 thorpej Exp $ */
/* $NetBSD: tcp_timer.c,v 1.50 2001/09/10 15:23:10 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -220,9 +220,6 @@ tcp_slowtimo()
goto tpgone;
}
}
tp->t_idle++;
if (tp->t_rtt)
tp->t_rtt++;
tpgone:
;
}
@ -253,9 +250,6 @@ dotcb6:
goto tp6gone;
}
}
tp->t_idle++;
if (tp->t_rtt)
tp->t_rtt++;
tp6gone:
;
}
@ -317,7 +311,8 @@ tcp_timers(tp, timer)
*/
case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT &&
((tcp_maxidle == 0) || (tp->t_idle <= tcp_maxidle)))
((tcp_maxidle == 0) ||
((tcp_now - tp->t_rcvtime) <= tcp_maxidle)))
TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_keepintvl);
else
tp = tcp_close(tp);
@ -391,7 +386,7 @@ tcp_timers(tp, timer)
/*
* If timing a segment in this window, stop the timer.
*/
tp->t_rtt = 0;
tp->t_rtttime = 0;
/*
* Remember if we are retransmitting a SYN, because if
* we do, set the initial congestion window must be set
@ -451,8 +446,8 @@ tcp_timers(tp, timer)
if (rto < tp->t_rttmin)
rto = tp->t_rttmin;
if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
(tp->t_idle >= tcp_maxpersistidle ||
tp->t_idle >= rto * tcp_totbackoff)) {
((tcp_now - tp->t_rcvtime) >= tcp_maxpersistidle ||
(tcp_now - tp->t_rcvtime) >= rto * tcp_totbackoff)) {
tcpstat.tcps_persistdrops++;
tp = tcp_drop(tp, ETIMEDOUT);
break;
@ -486,7 +481,8 @@ tcp_timers(tp, timer)
if (so->so_options & SO_KEEPALIVE &&
tp->t_state <= TCPS_CLOSE_WAIT) {
if ((tcp_maxidle > 0) &&
(tp->t_idle >= tcp_keepidle + tcp_maxidle))
((tcp_now - tp->t_rcvtime) >=
tcp_keepidle + tcp_maxidle))
goto dropit;
/*
* Send a packet designed to force a response

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_var.h,v 1.83 2001/09/10 04:24:25 thorpej Exp $ */
/* $NetBSD: tcp_var.h,v 1.84 2001/09/10 15:23:11 thorpej Exp $ */
/*
%%% portions-copyright-nrl-98
@ -136,7 +136,7 @@ struct tcpcb {
u_int t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_state; /* state of this connection */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
short t_rxtcur; /* current retransmit value */
uint32_t t_rxtcur; /* current retransmit value */
short t_dupacks; /* consecutive dup acks recd */
u_short t_peermss; /* peer's maximum segment size */
u_short t_ourmss; /* our's maximum segment size */
@ -200,12 +200,12 @@ struct tcpcb {
* transmit timing stuff. See below for scale of srtt and rttvar.
* "Variance" is actually smoothed difference.
*/
short t_idle; /* inactivity time */
short t_rtt; /* round trip time */
uint32_t t_rcvtime; /* time last segment received */
uint32_t t_rtttime; /* time we started measuring rtt */
tcp_seq t_rtseq; /* sequence number being timed */
short t_srtt; /* smoothed round-trip time */
short t_rttvar; /* variance in round-trip time */
short t_rttmin; /* minimum rtt allowed */
int32_t t_srtt; /* smoothed round-trip time */
int32_t t_rttvar; /* variance in round-trip time */
uint32_t t_rttmin; /* minimum rtt allowed */
u_long max_sndwnd; /* largest window peer has offered */
/* out-of-band data */
@ -702,7 +702,7 @@ struct tcpcb *
int tcp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
int tcp_usrreq __P((struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *));
void tcp_xmit_timer __P((struct tcpcb *, int));
void tcp_xmit_timer __P((struct tcpcb *, uint32_t));
tcp_seq tcp_new_iss __P((struct tcpcb *, tcp_seq));
tcp_seq tcp_new_iss1 __P((void *, void *, u_int16_t, u_int16_t, size_t,
tcp_seq));