Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -3408,7 +3408,7 @@ INP_WLOCK_ASSERT(tp->t_inpcb); TCPSTAT_INC(tcps_rttupdated); - tp->t_rttupdated++; + INCMAX(tp->t_rttupdated); #ifdef STATS stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_RTT, imax(0, rtt * 1000 / hz)); Index: sys/netinet/tcp_stacks/bbr.c =================================================================== --- sys/netinet/tcp_stacks/bbr.c +++ sys/netinet/tcp_stacks/bbr.c @@ -6515,7 +6515,7 @@ tp->t_rttbest = tp->t_srtt + tp->t_rttvar; } KMOD_TCPSTAT_INC(tcps_rttupdated); - tp->t_rttupdated++; + INCMAX(tp->t_rttupdated); #ifdef STATS stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_RTT, imax(0, rtt_ticks)); #endif Index: sys/netinet/tcp_stacks/rack.c =================================================================== --- sys/netinet/tcp_stacks/rack.c +++ sys/netinet/tcp_stacks/rack.c @@ -3905,7 +3905,7 @@ } KMOD_TCPSTAT_INC(tcps_rttupdated); rack_log_rtt_upd(tp, rack, rtt, o_srtt, o_var); - tp->t_rttupdated++; + INCMAX(tp->t_rttupdated); #ifdef STATS stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_RTT, imax(0, rtt)); #endif Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -2776,7 +2776,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); Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -182,7 +182,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; @@ -218,6 +217,7 @@ tcp_seq gput_seq; /* Outbound measurement seq */ tcp_seq gput_ack; /* Inbound measurement ack */ int32_t t_stats_gput_prev; /* XXXLAS: Prev gput measurement */ + uint8_t t_rttupdated; /* number of times rtt sampled */ uint8_t t_tfo_client_cookie_len; /* TCP Fast Open client cookie length */ unsigned int *t_tfo_pending; /* TCP Fast Open server pending counter */ union { @@ -511,6 +511,33 @@ 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 + * a signed or unsigned type, without integer overflow. + * Determining if the type of a variable is signed + * or not in a portable way without typeof() is quite + * involved but the resuting code is still optimal. + */ +#define UTYPE_MAX(x) \ + ((((1 << (sizeof((x)) * 8 - 1)) - 1) * 2) + 1) +#define TYPE_MAX(x) \ + ((((1 << (sizeof((x)) * 8 - 2)) - 1) * 2) + 1) +#define HIGH_BIT(n) \ + ((n) & (1 << (sizeof(n) * 8 - 1))) +#define IS_SIGNED(n) \ + (HIGH_BIT(n) ? \ + HIGH_BIT(n >> 1) != 0 : \ + HIGH_BIT(~n >> 1) != 0) + +/* + * Macro to Post-increment counters that should NOT + * overflow, as a drop-in replacement for 'x++'. + */ +#define INCMAX(x) \ + IS_SIGNED(x) ? \ + ((x) < TYPE_MAX(x)) ? (x)++ : (x) : \ + ((x) < UTYPE_MAX(x)) ? (x)++ : (x) + /* * TCP statistics. * Many of these should be kept per connection,