diff options
author | bz <bz@FreeBSD.org> | 2012-02-15 16:09:56 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2012-02-15 16:09:56 +0000 |
commit | e7eef5c8119b66a2a14b9e339e440f80c327182a (patch) | |
tree | b0aa46ec2c710c27495fdbd3425f1e1e7f502603 /sys/netinet/tcp_seq.h | |
parent | d93961fe9edf9c6624e6d6c918343387bf79d54e (diff) | |
download | FreeBSD-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_seq.h')
-rw-r--r-- | sys/netinet/tcp_seq.h | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h index f58b537..51d971f 100644 --- a/sys/netinet/tcp_seq.h +++ b/sys/netinet/tcp_seq.h @@ -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_ */ |