Date: Sat, 19 May 2012 18:32:31 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r235657 - stable/9/sys/netinet Message-ID: <201205191832.q4JIWVXv038390@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bz Date: Sat May 19 18:32:31 2012 New Revision: 235657 URL: http://svn.freebsd.org/changeset/base/235657 Log: MFC r231767: 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 Modified: stable/9/sys/netinet/tcp_input.c stable/9/sys/netinet/tcp_output.c stable/9/sys/netinet/tcp_seq.h stable/9/sys/netinet/tcp_syncache.c stable/9/sys/netinet/tcp_timewait.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/netinet/tcp_input.c ============================================================================== --- stable/9/sys/netinet/tcp_input.c Sat May 19 18:16:49 2012 (r235656) +++ stable/9/sys/netinet/tcp_input.c Sat May 19 18:32:31 2012 (r235657) @@ -1524,7 +1524,7 @@ tcp_do_segment(struct mbuf *m, struct tc */ 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; } @@ -1549,7 +1549,7 @@ tcp_do_segment(struct mbuf *m, struct tc 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); @@ -1593,7 +1593,7 @@ tcp_do_segment(struct mbuf *m, struct tc */ 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; } @@ -1631,11 +1631,13 @@ tcp_do_segment(struct mbuf *m, struct tc */ 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 || @@ -2101,7 +2103,7 @@ tcp_do_segment(struct mbuf *m, struct tc 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 @@ -2260,7 +2262,7 @@ tcp_do_segment(struct mbuf *m, struct tc 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; } @@ -2574,11 +2576,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; Modified: stable/9/sys/netinet/tcp_output.c ============================================================================== --- stable/9/sys/netinet/tcp_output.c Sat May 19 18:16:49 2012 (r235656) +++ stable/9/sys/netinet/tcp_output.c Sat May 19 18:32:31 2012 (r235657) @@ -685,13 +685,13 @@ send: /* Timestamps. */ if ((tp->t_flags & TF_RCVD_TSTMP) || ((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) { - to.to_tsval = ticks + tp->ts_offset; + to.to_tsval = tcp_ts_getticks() + tp->ts_offset; to.to_tsecr = tp->ts_recent; to.to_flags |= TOF_TS; /* Set receive buffer autosizing timestamp. */ if (tp->rfbuf_ts == 0 && (so->so_rcv.sb_flags & SB_AUTOSIZE)) - tp->rfbuf_ts = ticks; + tp->rfbuf_ts = tcp_ts_getticks(); } /* Selective ACK's. */ if (tp->t_flags & TF_SACK_PERMIT) { Modified: stable/9/sys/netinet/tcp_seq.h ============================================================================== --- stable/9/sys/netinet/tcp_seq.h Sat May 19 18:16:49 2012 (r235656) +++ stable/9/sys/netinet/tcp_seq.h Sat May 19 18:32:31 2012 (r235657) @@ -62,7 +62,34 @@ (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ (tp)->snd_recover = (tp)->iss -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * hz) - /* timestamp wrap-around time */ +#ifdef _KERNEL +/* + * Clock macros for RFC 1323 timestamps. + */ +#define TCP_TS_TO_TICKS(_t) ((_t) * hz / 1000) + +/* Timestamp wrap-around time, 24 days. */ +#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * 1000) + +/* + * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323. + * We always use 1ms granularity independent of hz. + */ +static __inline u_int +tcp_ts_getticks(void) +{ + struct timeval tv; + u_long ms; + + /* + * getmicrouptime() should be good enough for any 1-1000ms granularity. + * Do not use getmicrotime() here as it might break nfsroot/tcp. + */ + getmicrouptime(&tv); + ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + return (ms); +} +#endif /* _KERNEL */ #endif /* _NETINET_TCP_SEQ_H_ */ Modified: stable/9/sys/netinet/tcp_syncache.c ============================================================================== --- stable/9/sys/netinet/tcp_syncache.c Sat May 19 18:16:49 2012 (r235656) +++ stable/9/sys/netinet/tcp_syncache.c Sat May 19 18:32:31 2012 (r235657) @@ -818,7 +818,7 @@ syncache_socket(struct syncache *sc, str if (sc->sc_flags & SCF_TIMESTAMP) { tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP; tp->ts_recent = sc->sc_tsreflect; - tp->ts_recent_age = ticks; + tp->ts_recent_age = tcp_ts_getticks(); tp->ts_offset = sc->sc_tsoff; } #ifdef TCP_SIGNATURE @@ -1225,7 +1225,7 @@ _syncache_add(struct in_conninfo *inc, s */ if (to->to_flags & TOF_TS) { sc->sc_tsreflect = to->to_tsval; - sc->sc_ts = ticks; + sc->sc_ts = tcp_ts_getticks(); sc->sc_flags |= SCF_TIMESTAMP; } if (to->to_flags & TOF_SCALE) { @@ -1666,7 +1666,7 @@ syncookie_generate(struct syncache_head data |= md5_buffer[2] << 10; /* more digest bits */ data ^= md5_buffer[3]; sc->sc_ts = data; - sc->sc_tsoff = data - ticks; /* after XOR */ + sc->sc_tsoff = data - tcp_ts_getticks(); /* after XOR */ } TCPSTAT_INC(tcps_sc_sendcookie); @@ -1751,7 +1751,7 @@ syncookie_lookup(struct in_conninfo *inc sc->sc_flags |= SCF_TIMESTAMP; sc->sc_tsreflect = to->to_tsval; sc->sc_ts = to->to_tsecr; - sc->sc_tsoff = to->to_tsecr - ticks; + sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks(); sc->sc_flags |= (data & 0x1) ? SCF_SIGNATURE : 0; sc->sc_flags |= ((data >> 1) & 0x1) ? SCF_SACK : 0; sc->sc_requested_s_scale = min((data >> 2) & 0xf, Modified: stable/9/sys/netinet/tcp_timewait.c ============================================================================== --- stable/9/sys/netinet/tcp_timewait.c Sat May 19 18:16:49 2012 (r235656) +++ stable/9/sys/netinet/tcp_timewait.c Sat May 19 18:32:31 2012 (r235657) @@ -558,7 +558,7 @@ tcp_twrespond(struct tcptw *tw, int flag */ if (tw->t_recent && flags == TH_ACK) { to.to_flags |= TOF_TS; - to.to_tsval = ticks + tw->ts_offset; + to.to_tsval = tcp_ts_getticks() + tw->ts_offset; to.to_tsecr = tw->t_recent; } optlen = tcp_addoptions(&to, (u_char *)(th + 1));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205191832.q4JIWVXv038390>