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. Reviewed by: jhb Approved by: so Security: FreeBSD-SA-18:08.tcp Security: CVE-2018-6922
This commit is contained in:
parent
7b7dbfa9b3
commit
95a914f631
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=337384
@ -445,6 +445,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 .
|
||||
|
@ -91,6 +91,11 @@ SYSCTL_UMA_CUR(_net_inet_tcp_reass, OID_AUTO, cursegments, 0,
|
||||
&tcp_reass_zone,
|
||||
"Global number of TCP Segments currently in Reassembly Queue");
|
||||
|
||||
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)
|
||||
@ -170,6 +175,10 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
|
||||
* 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.
|
||||
@ -180,7 +189,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
|
||||
* 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)) {
|
||||
TCPSTAT_INC(tcps_rcvreassfull);
|
||||
*tlenp = 0;
|
||||
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
|
||||
|
Loading…
Reference in New Issue
Block a user