diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -3600,7 +3600,8 @@ INP_WLOCK_ASSERT(tptoinpcb(tp)); TCPSTAT_INC(tcps_rttupdated); - tp->t_rttupdated++; + if (tp->t_rttupdated < UTYPE_MAX(tp->t_rttupdated)) + tp->t_rttupdated++; #ifdef STATS stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_RTT, imax(0, rtt * 1000 / hz)); diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c --- a/sys/netinet/tcp_stacks/bbr.c +++ b/sys/netinet/tcp_stacks/bbr.c @@ -6397,7 +6397,8 @@ tp->t_rttbest = tp->t_srtt + tp->t_rttvar; } KMOD_TCPSTAT_INC(tcps_rttupdated); - tp->t_rttupdated++; + if (tp->t_rttupdated < UTYPE_MAX(tp->t_rttupdated)) + tp->t_rttupdated++; #ifdef STATS stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_RTT, imax(0, rtt_ticks)); #endif diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c --- a/sys/netinet/tcp_stacks/rack.c +++ b/sys/netinet/tcp_stacks/rack.c @@ -7725,7 +7725,8 @@ } rack->rc_srtt_measure_made = 1; KMOD_TCPSTAT_INC(tcps_rttupdated); - tp->t_rttupdated++; + if (tp->t_rttupdated < UTYPE_MAX(tp->t_rttupdated)) + tp->t_rttupdated++; #ifdef STATS if (rack_stats_gets_ms_rtt == 0) { /* Send in the microsecond rtt used for rxt timeout purposes */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -3136,7 +3136,7 @@ tp->t_rttbest); db_print_indent(indent); - db_printf("t_rttupdated: %lu max_sndwnd: %u t_softerror: %d\n", + db_printf("t_rttupdated: %u max_sndwnd: %u t_softerror: %d\n", tp->t_rttupdated, tp->max_sndwnd, tp->t_softerror); db_print_indent(indent); diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -222,7 +222,6 @@ uint32_t snd_ssthresh_prev; /* ssthresh prior to retransmit */ tcp_seq snd_recover_prev; /* snd_recover prior to retransmit */ int t_sndzerowin; /* zero-window updates sent */ - u_long t_rttupdated; /* number of times rtt sampled */ int snd_numholes; /* number of holes seen by sender */ u_int t_badrxtwin; /* window for retransmit recovery */ TAILQ_HEAD(sackhole_head, sackhole) snd_holes; @@ -269,6 +268,7 @@ uint32_t t_dsack_bytes; /* dsack bytes received */ uint32_t t_dsack_tlp_bytes; /* dsack bytes received for TLPs sent */ uint32_t t_dsack_pack; /* dsack packets we have eceived */ + uint8_t t_rttupdated; /* number of times rtt sampled */ /* TCP Fast Open */ uint8_t t_tfo_client_cookie_len; /* TFO client cookie length */ uint32_t t_end_info_status; /* Status flag of end info */ @@ -682,6 +682,22 @@ max((tp)->t_rttmin, (((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)) \ + (tp)->t_rttvar) >> TCP_DELTA_SHIFT) +/* + * Programmatically determine the maximum value of + * an unsigned type, without integer overflow. + * + * After determining the byte-size of the type, + * e.g. 2 for uint16, set the left-most bit. (0x8000) + * Set all bits but the highest by subtracting one. (0x7FFF) + * Shift all set bits left by one by way of muliply by 2. (0xFFFE) + * Finally, set the lowest bit by adding one. (0xFFFF) + * + * This is a portable way to programmatically determine + * the maximum value of an unsigned variable of arbitrary size. + */ +#define UTYPE_MAX(x) \ + ((((1ULL << (sizeof((x)) * 8 - 1)) - 1) * 2) + 1) + /* * TCP statistics. * Many of these should be kept per connection,