mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
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
This commit is contained in:
1 parent
da04cf02c9
commit
04cd9bca4d
6 files changed
+35
-67
No files matched your search
@@ -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 *",
|
||||
|
||||
+23
-27
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user