git: 04cd9bca4dab - main - tcp: refactor tcp_autorcvbuf() and associated sysctls
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 22 Oct 2026 03:31:24 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=04cd9bca4dab67c45292c59bbf6d78ce66fc5628
commit 04cd9bca4dab67c45292c59bbf6d78ce66fc5628
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-10-22 03:27:36 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-10-22 03:27:36 +0000
tcp: refactor tcp_autorcvbuf() and associated sysctls
Run the entire function under the socket buffer lock. Make it responsible
to set the new limit or clear SB_AUTOSIZE in case of a failure. Use
unsigned type for newsize, that matches both the sb_hiwat type and min()
argument types. Make byte counter in the tcpcb unsigned, too. Make the
sizing tunables unsigned, and make the switching tunable a boolean. Don't
execute Dtrace probe in case of a failure. Simplify the Dtrace probe to
report only relevant information, the previous probe looked more like a
leftover from a debugging session.
Reviewed by: tuexen
Differential Revision: https://reviews.freebsd.org/D60731
---
sys/netinet/in_kdtrace.c | 8 ++-----
sys/netinet/tcp_input.c | 50 ++++++++++++++++++++-----------------------
sys/netinet/tcp_stacks/bbr.c | 11 +---------
sys/netinet/tcp_stacks/rack.c | 20 +++--------------
sys/netinet/tcp_usrreq.c | 2 +-
sys/netinet/tcp_var.h | 11 +++++-----
6 files changed, 35 insertions(+), 67 deletions(-)
diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c
index 917e6b8be137..a44b4c8ed476 100644
--- a/sys/netinet/in_kdtrace.c
+++ b/sys/netinet/in_kdtrace.c
@@ -539,13 +539,9 @@ SDT_PROBE_DEFINE6_XLATE(tcp, , , state__change,
"void *", "void *",
"int", "tcplsinfo_t *");
-SDT_PROBE_DEFINE6_XLATE(tcp, , , receive__autoresize,
- "void *", "void *",
- "struct tcpcb *", "csinfo_t *",
- "struct mbuf *", "ipinfo_t *",
+SDT_PROBE_DEFINE2_XLATE(tcp, , , receive__autoresize,
"struct tcpcb *", "tcpsinfo_t *" ,
- "struct tcphdr *", "tcpinfoh_t *",
- "int", "int");
+ "u_int", "u_int");
SDT_PROBE_DEFINE5_XLATE(udp, , , receive,
"void *", "pktinfo_t *",
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 202438632238..5ebcad5eae43 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -208,18 +208,19 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_ack, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_insecure_ack), 0,
"Follow RFC793 criteria for validating SEG.ACK");
-VNET_DEFINE(int, tcp_recvspace) = 1024*64;
+VNET_DEFINE(u_int, tcp_recvspace) = 1024*64;
#define V_tcp_recvspace VNET(tcp_recvspace)
-SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(tcp_recvspace), 0, "Initial receive socket buffer size");
+SYSCTL_UINT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_recvspace), 0,
+ "Initial receive socket buffer size");
-VNET_DEFINE(int, tcp_do_autorcvbuf) = 1;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW,
+VNET_DEFINE(bool, tcp_do_autorcvbuf) = true;
+SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_do_autorcvbuf), 0,
"Enable automatic receive buffer sizing");
-VNET_DEFINE(int, tcp_autorcvbuf_max) = 8*1024*1024;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
+VNET_DEFINE(u_int, tcp_autorcvbuf_max) = 8*1024*1024;
+SYSCTL_UINT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_max), 0,
"Max size of automatic receive buffer");
@@ -1415,11 +1416,12 @@ drop:
* TODO: Only step up if the application is actually serving
* the buffer to better manage the socket buffer resources.
*/
-int
-tcp_autorcvbuf(struct mbuf *m, struct tcphdr *th, struct socket *so,
- struct tcpcb *tp, int tlen)
+void
+tcp_autorcvbuf(struct tcpcb *tp, u_int tlen)
{
- int newsize = 0;
+ struct socket *so = tptosocket(tp);
+
+ SOCK_RECVBUF_LOCK_ASSERT(so);
if (V_tcp_do_autorcvbuf && (so->so_rcv.sb_flags & SB_AUTOSIZE) &&
tp->t_srtt != 0 && tp->rfbuf_ts != 0 &&
@@ -1427,17 +1429,22 @@ tcp_autorcvbuf(struct mbuf *m, struct tcphdr *th, struct socket *so,
((tp->t_srtt >> TCP_RTT_SHIFT)/2)) {
if (tp->rfbuf_cnt > ((so->so_rcv.sb_hiwat / 2)/ 4 * 3) &&
so->so_rcv.sb_hiwat < V_tcp_autorcvbuf_max) {
- newsize = min((so->so_rcv.sb_hiwat + (so->so_rcv.sb_hiwat/2)), V_tcp_autorcvbuf_max);
- }
- TCP_PROBE6(receive__autoresize, NULL, tp, m, tp, th, newsize);
+ u_int newsize;
+ newsize = min((so->so_rcv.sb_hiwat +
+ (so->so_rcv.sb_hiwat / 2)), V_tcp_autorcvbuf_max);
+ if (sbreserve_locked(so, SO_RCV, newsize, NULL)) {
+ TCP_PROBE2(receive__autoresize, tp, newsize);
+ } else {
+ so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
+ }
+ }
/* Start over with next RTT. */
tp->rfbuf_ts = 0;
tp->rfbuf_cnt = 0;
} else {
tp->rfbuf_cnt += tlen; /* add up */
}
- return (newsize);
}
int
@@ -1838,8 +1845,6 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
}
} else if (th->th_ack == tp->snd_una &&
tlen <= sbspace(&so->so_rcv)) {
- int newsize = 0; /* automatic sockbuf scaling */
-
/*
* This is a pure, in-sequence data packet with
* nothing on the reassembly queue and we have enough
@@ -1873,21 +1878,12 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
TCPSTAT_ADD(tcps_rcvbyte, tlen);
TCP_PROBE3(debug__input, tp, th, m);
- newsize = tcp_autorcvbuf(m, th, so, tp, tlen);
-
/* Add data to socket buffer. */
SOCK_RECVBUF_LOCK(so);
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
m_freem(m);
} else {
- /*
- * Set new socket buffer size.
- * Give up when limit is reached.
- */
- if (newsize)
- if (!sbreserve_locked(so, SO_RCV,
- newsize, NULL))
- so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
+ tcp_autorcvbuf(tp, tlen);
m_adj(m, drop_hdrlen); /* delayed header drop */
sbappendstream_locked(&so->so_rcv, m, 0);
}
diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c
index 13cbc885c80a..a055f6d756ac 100644
--- a/sys/netinet/tcp_stacks/bbr.c
+++ b/sys/netinet/tcp_stacks/bbr.c
@@ -8419,7 +8419,6 @@ bbr_do_fastnewdata(struct mbuf *m, struct tcphdr *th, struct socket *so,
uint32_t tiwin, int32_t nxt_pkt)
{
uint16_t nsegs;
- int32_t newsize = 0; /* automatic sockbuf scaling */
struct tcp_bbr *bbr;
#ifdef NETFLIX_SB_LIMITS
u_int mcnt, appended;
@@ -8499,22 +8498,14 @@ bbr_do_fastnewdata(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->rcv_up = tp->rcv_nxt;
KMOD_TCPSTAT_ADD(tcps_rcvpack, (int)nsegs);
KMOD_TCPSTAT_ADD(tcps_rcvbyte, tlen);
- newsize = tcp_autorcvbuf(m, th, so, tp, tlen);
/* Add data to socket buffer. */
SOCK_RECVBUF_LOCK(so);
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
m_freem(m);
} else {
- /*
- * Set new socket buffer size. Give up when limit is
- * reached.
- */
- if (newsize)
- if (!sbreserve_locked(so, SO_RCV, newsize, NULL))
- so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
+ tcp_autorcvbuf(tp, tlen);
m_adj(m, drop_hdrlen); /* delayed header drop */
-
#ifdef NETFLIX_SB_LIMITS
appended =
#endif
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index c1f89a6286b4..227c765b1cee 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -12250,14 +12250,8 @@ rack_process_data(struct mbuf *m, struct tcphdr *th, struct socket *so,
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
m_freem(m);
} else {
- int32_t newsize;
-
- if (tlen > 0) {
- newsize = tcp_autorcvbuf(m, th, so, tp, tlen);
- if (newsize)
- if (!sbreserve_locked(so, SO_RCV, newsize, NULL))
- so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
- }
+ if (tlen > 0)
+ tcp_autorcvbuf(tp, tlen);
#ifdef NETFLIX_SB_LIMITS
appended =
#endif
@@ -12407,7 +12401,6 @@ rack_do_fastnewdata(struct mbuf *m, struct tcphdr *th, struct socket *so,
uint32_t tiwin, int32_t nxt_pkt, uint8_t iptos)
{
int32_t nsegs;
- int32_t newsize = 0; /* automatic sockbuf scaling */
struct tcp_rack *rack;
#ifdef NETFLIX_SB_LIMITS
u_int mcnt, appended;
@@ -12485,20 +12478,13 @@ rack_do_fastnewdata(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->rcv_up = tp->rcv_nxt;
KMOD_TCPSTAT_ADD(tcps_rcvpack, nsegs);
KMOD_TCPSTAT_ADD(tcps_rcvbyte, tlen);
- newsize = tcp_autorcvbuf(m, th, so, tp, tlen);
/* Add data to socket buffer. */
SOCK_RECVBUF_LOCK(so);
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
m_freem(m);
} else {
- /*
- * Set new socket buffer size. Give up when limit is
- * reached.
- */
- if (newsize)
- if (!sbreserve_locked(so, SO_RCV, newsize, NULL))
- so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
+ tcp_autorcvbuf(tp, tlen);
m_adj(m, drop_hdrlen); /* delayed header drop */
#ifdef NETFLIX_SB_LIMITS
appended =
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index ac0c11a2233e..60b16fafdbb0 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -2884,7 +2884,7 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent, bool show_bblog,
/* Skip sackblks, sackhint. */
db_print_indent(indent);
- db_printf("t_rttlow: %d rfbuf_ts: %u rfbuf_cnt: %d\n",
+ db_printf("t_rttlow: %d rfbuf_ts: %u rfbuf_cnt: %u\n",
tp->t_rttlow, tp->rfbuf_ts, tp->rfbuf_cnt);
db_print_indent(indent);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 8400824761ed..75efd8eb92e0 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -422,7 +422,7 @@ struct tcpcb {
struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */
struct sackhint sackhint; /* SACK scoreboard hint */
int t_rttlow; /* smallest observerved RTT */
- int rfbuf_cnt; /* recv buffer autoscaling byte count */
+ u_int rfbuf_cnt; /* recv buffer autoscaling byte count */
struct toedev *tod; /* toedev handling this connection */
int t_sndrexmitpack; /* retransmit packets sent */
int t_rcvoopack; /* out-of-order packets received */
@@ -1303,13 +1303,13 @@ VNET_DECLARE(int, path_mtu_discovery);
VNET_DECLARE(int, tcp_abc_l_var);
VNET_DECLARE(uint32_t, tcp_ack_war_cnt);
VNET_DECLARE(uint32_t, tcp_ack_war_time_window);
-VNET_DECLARE(int, tcp_autorcvbuf_max);
+VNET_DECLARE(u_int, tcp_autorcvbuf_max);
VNET_DECLARE(int, tcp_autosndbuf_inc);
VNET_DECLARE(int, tcp_autosndbuf_max);
VNET_DECLARE(int, tcp_bind_all_fibs);
VNET_DECLARE(int, tcp_delack_enabled);
-VNET_DECLARE(int, tcp_do_autorcvbuf);
VNET_DECLARE(int, tcp_do_autosndbuf);
+VNET_DECLARE(bool, tcp_do_autorcvbuf);
VNET_DECLARE(int, tcp_do_ecn);
VNET_DECLARE(int, tcp_do_lrd);
VNET_DECLARE(int, tcp_do_prr);
@@ -1336,7 +1336,7 @@ VNET_DECLARE(int, tcp_mssdflt);
VNET_DECLARE(int, tcp_perconn_stats_dflt_tpl);
VNET_DECLARE(int, tcp_perconn_stats_enable);
#endif /* STATS */
-VNET_DECLARE(int, tcp_recvspace);
+VNET_DECLARE(u_int, tcp_recvspace);
VNET_DECLARE(int, tcp_retries);
VNET_DECLARE(int, tcp_sack_globalholes);
VNET_DECLARE(int, tcp_sack_globalmaxholes);
@@ -1403,6 +1403,7 @@ VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]);
#define V_tcp_hhh VNET(tcp_hhh)
#endif
+void tcp_autorcvbuf(struct tcpcb *, u_int);
void tcp_account_for_send(struct tcpcb *, uint32_t, uint8_t, uint8_t, bool);
int tcp_addoptions(struct tcpopt *, u_char *);
struct tcpcb *
@@ -1437,8 +1438,6 @@ void hhook_run_tcp_est_in(struct tcpcb *tp,
#endif
int tcp_input(struct mbuf **, int *, int);
-int tcp_autorcvbuf(struct mbuf *, struct tcphdr *, struct socket *,
- struct tcpcb *, int);
int tcp_input_with_port(struct mbuf **, int *, int, uint16_t);
void tcp_do_segment(struct tcpcb *, struct mbuf *, struct tcphdr *, int,
int, uint8_t);