summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2012-02-15 16:09:56 +0000
committerbz <bz@FreeBSD.org>2012-02-15 16:09:56 +0000
commite7eef5c8119b66a2a14b9e339e440f80c327182a (patch)
treeb0aa46ec2c710c27495fdbd3425f1e1e7f502603 /sys/netinet/tcp_input.c
parentd93961fe9edf9c6624e6d6c918343387bf79d54e (diff)
downloadFreeBSD-src-e7eef5c8119b66a2a14b9e339e440f80c327182a.zip
FreeBSD-src-e7eef5c8119b66a2a14b9e339e440f80c327182a.tar.gz
Fix PAWS (Protect Against Wrapped Sequence numbers) in cases when
hz >> 1000 and thus getting outside the timestamp clock frequenceny of 1ms < x < 1s per tick as mandated by RFC1323, leading to connection resets on idle connections. Always use a granularity of 1ms using getmicrouptime() making all but relevant callouts independent of hz. Use getmicrouptime(), not getmicrotime() as the latter may make a jump possibly breaking TCP nfsroot mounts having our timestamps move forward for more than 24.8 days in a second without having been idle for that long. PR: kern/61404 Reviewed by: jhb, mav, rrs Discussed with: silby, lstewart Sponsored by: Sandvine Incorporated (originally in 2011) MFC after: 6 weeks
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 0fadf87..1a31c5e 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1493,7 +1493,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
to.to_tsecr -= tp->ts_offset;
- if (TSTMP_GT(to.to_tsecr, ticks))
+ if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
to.to_tsecr = 0;
}
@@ -1518,7 +1518,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
if (to.to_flags & TOF_TS) {
tp->t_flags |= TF_RCVD_TSTMP;
tp->ts_recent = to.to_tsval;
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
}
if (to.to_flags & TOF_MSS)
tcp_mss(tp, to.to_mss);
@@ -1562,7 +1562,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) != 0 &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
tp->ts_recent = to.to_tsval;
}
@@ -1600,11 +1600,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) != 0 &&
to.to_tsecr) {
- if (!tp->t_rttlow ||
- tp->t_rttlow > ticks - to.to_tsecr)
- tp->t_rttlow = ticks - to.to_tsecr;
+ u_int t;
+
+ t = tcp_ts_getticks() - to.to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
tcp_xmit_timer(tp,
- ticks - to.to_tsecr + 1);
+ TCP_TS_TO_TICKS(t) + 1);
} else if (tp->t_rtttime &&
SEQ_GT(th->th_ack, tp->t_rtseq)) {
if (!tp->t_rttlow ||
@@ -2070,7 +2072,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TSTMP_LT(to.to_tsval, tp->ts_recent)) {
/* Check to see if ts_recent is over 24 days old. */
- if (ticks - tp->ts_recent_age > TCP_PAWS_IDLE) {
+ if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) {
/*
* Invalidate ts_recent. If this segment updates
* ts_recent, the age will be reset later and ts_recent
@@ -2229,7 +2231,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
((thflags & (TH_SYN|TH_FIN)) != 0))) {
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
tp->ts_recent = to.to_tsval;
}
@@ -2543,11 +2545,13 @@ process_ACK:
* timestamps of 0 or we could calculate a
* huge RTT and blow up the retransmit timer.
*/
- if ((to.to_flags & TOF_TS) != 0 &&
- to.to_tsecr) {
- if (!tp->t_rttlow || tp->t_rttlow > ticks - to.to_tsecr)
- tp->t_rttlow = ticks - to.to_tsecr;
- tcp_xmit_timer(tp, ticks - to.to_tsecr + 1);
+ if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) {
+ u_int t;
+
+ t = tcp_ts_getticks() - to.to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
+ tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1);
} else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) {
if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime)
tp->t_rttlow = ticks - tp->t_rtttime;
OpenPOWER on IntegriCloud