svn commit: r337386 - in stable/10: share/man/man4 sys/netinet
Jonathan T. Looney
jtl at FreeBSD.org
Mon Aug 6 17:46:30 UTC 2018
Author: jtl
Date: Mon Aug 6 17:46:28 2018
New Revision: 337386
URL: https://svnweb.freebsd.org/changeset/base/337386
Log:
MFC r337384:
Address concerns about CPU usage while doing TCP reassembly.
Currently, the per-queue limit is a function of the receive buffer
size and the MSS. In certain cases (such as connections with large
receive buffers), the per-queue segment limit can be quite large.
Because we process segments as a linked list, large queues may not
perform acceptably.
The better long-term solution is to make the queue more efficient.
But, in the short-term, we can provide a way for a system
administrator to set the maximum queue size.
We set the default queue limit to 100. This is an effort to balance
performance with a sane resource limit. Depending on their
environment, goals, etc., an administrator may choose to modify this
limit in either direction.
Approved by: so
Security: FreeBSD-SA-18:08.tcp
Sponsored by: CVE-2018-6922
Modified:
stable/10/share/man/man4/tcp.4
stable/10/sys/netinet/tcp_reass.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/share/man/man4/tcp.4
==============================================================================
--- stable/10/share/man/man4/tcp.4 Mon Aug 6 17:41:53 2018 (r337385)
+++ stable/10/share/man/man4/tcp.4 Mon Aug 6 17:46:28 2018 (r337386)
@@ -436,6 +436,20 @@ no reseeding will occur.
Reseeding should not be necessary, and will break
.Dv TIME_WAIT
recycling for a few minutes.
+.It Va reass.cursegments
+The current total number of segments present in all reassembly queues.
+.It Va reass.maxsegments
+The maximum limit on the total number of segments across all reassembly
+queues.
+The limit can be adjusted as a tunable.
+.It Va reass.maxqueuelen
+The maximum number of segments allowed in each reassembly queue.
+By default, the system chooses a limit based on each TCP connection's
+receive buffer size and maximum segment size (MSS).
+The actual limit applied to a session's reassembly queue will be the lower of
+the system-calculated automatic limit and the user-specified
+.Va reass.maxqueuelen
+limit.
.It Va rexmit_min , rexmit_slop
Adjust the retransmit timer calculation for
.Tn TCP .
Modified: stable/10/sys/netinet/tcp_reass.c
==============================================================================
--- stable/10/sys/netinet/tcp_reass.c Mon Aug 6 17:41:53 2018 (r337385)
+++ stable/10/sys/netinet/tcp_reass.c Mon Aug 6 17:46:28 2018 (r337386)
@@ -96,6 +96,11 @@ SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows,
static uma_zone_t tcp_reass_zone;
+static u_int tcp_reass_maxqueuelen = 100;
+SYSCTL_UINT(_net_inet_tcp_reass, OID_AUTO, maxqueuelen, CTLFLAG_RWTUN,
+ &tcp_reass_maxqueuelen, 0,
+ "Maximum number of TCP Segments per Reassembly Queue");
+
/* Initialize TCP reassembly queue */
static void
tcp_reass_zone_change(void *tag)
@@ -184,6 +189,10 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tl
* socket receive buffer determines our advertised window and grows
* automatically when socket buffer autotuning is enabled. Use it as the
* basis for our queue limit.
+ *
+ * However, allow the user to specify a ceiling for the number of
+ * segments in each queue.
+ *
* Always let the missing segment through which caused this queue.
* NB: Access to the socket buffer is left intentionally unlocked as we
* can tolerate stale information here.
@@ -194,7 +203,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tl
* is understood.
*/
if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
- tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
+ tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1,
+ tcp_reass_maxqueuelen)) {
tcp_reass_overflows++;
TCPSTAT_INC(tcps_rcvmemdrop);
m_freem(m);
More information about the svn-src-all
mailing list