2005-01-06 20:45:51 -05:00
|
|
|
/*-
|
2017-11-20 14:43:44 -05:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
*
|
1995-10-03 12:54:17 -04:00
|
|
|
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
|
1994-05-24 06:09:53 -04:00
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2017-02-28 18:42:47 -05:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1994-05-24 06:09:53 -04:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
|
* without specific prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*
|
1995-10-03 12:54:17 -04:00
|
|
|
* @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
|
1994-05-24 06:09:53 -04:00
|
|
|
*/
|
|
|
|
|
|
2007-10-07 16:44:24 -04:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
2012-11-27 01:42:44 -05:00
|
|
|
#include "opt_inet.h"
|
2000-01-09 14:17:30 -05:00
|
|
|
#include "opt_inet6.h"
|
2014-05-18 18:39:01 -04:00
|
|
|
#include "opt_rss.h"
|
1997-09-16 14:36:06 -04:00
|
|
|
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <sys/param.h>
|
1995-11-09 15:23:09 -05:00
|
|
|
#include <sys/kernel.h>
|
2002-09-05 11:33:30 -04:00
|
|
|
#include <sys/lock.h>
|
2001-06-22 23:21:46 -04:00
|
|
|
#include <sys/mbuf.h>
|
2002-09-05 11:33:30 -04:00
|
|
|
#include <sys/mutex.h>
|
|
|
|
|
#include <sys/protosw.h>
|
2010-03-20 15:47:30 -04:00
|
|
|
#include <sys/smp.h>
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <sys/socketvar.h>
|
2002-09-05 11:33:30 -04:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
#include <sys/systm.h>
|
1995-10-03 12:54:17 -04:00
|
|
|
|
2008-12-02 16:37:28 -05:00
|
|
|
#include <net/if.h>
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <net/route.h>
|
2015-01-18 13:06:40 -05:00
|
|
|
#include <net/rss_config.h>
|
2009-08-01 15:26:27 -04:00
|
|
|
#include <net/vnet.h>
|
2014-05-18 18:39:01 -04:00
|
|
|
#include <net/netisr.h>
|
1994-05-24 06:09:53 -04:00
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
2015-09-13 11:50:55 -04:00
|
|
|
#include <netinet/in_kdtrace.h>
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <netinet/in_pcb.h>
|
2014-05-18 18:39:01 -04:00
|
|
|
#include <netinet/in_rss.h>
|
2002-09-05 11:33:30 -04:00
|
|
|
#include <netinet/in_systm.h>
|
2000-01-09 14:17:30 -05:00
|
|
|
#ifdef INET6
|
|
|
|
|
#include <netinet6/in6_pcb.h>
|
|
|
|
|
#endif
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <netinet/ip_var.h>
|
2016-01-21 17:34:51 -05:00
|
|
|
#include <netinet/tcp.h>
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <netinet/tcp_fsm.h>
|
|
|
|
|
#include <netinet/tcp_timer.h>
|
|
|
|
|
#include <netinet/tcp_var.h>
|
2023-03-16 11:43:16 -04:00
|
|
|
#include <netinet/tcp_log_buf.h>
|
2018-06-07 14:18:13 -04:00
|
|
|
#include <netinet/tcp_seq.h>
|
2016-01-27 12:59:39 -05:00
|
|
|
#include <netinet/cc/cc.h>
|
2014-10-07 17:50:28 -04:00
|
|
|
#ifdef INET6
|
|
|
|
|
#include <netinet6/tcp6_var.h>
|
|
|
|
|
#endif
|
1994-05-24 06:09:53 -04:00
|
|
|
#include <netinet/tcpip.h>
|
|
|
|
|
|
2016-01-26 11:33:38 -05:00
|
|
|
int tcp_persmin;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, persmin,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_persmin, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"minimum persistence interval");
|
2016-01-26 11:33:38 -05:00
|
|
|
|
|
|
|
|
int tcp_persmax;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, persmax,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_persmax, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"maximum persistence interval");
|
2016-01-26 11:33:38 -05:00
|
|
|
|
1999-08-30 17:17:07 -04:00
|
|
|
int tcp_keepinit;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_keepinit, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"time to establish connection");
|
1996-09-13 19:51:44 -04:00
|
|
|
|
1999-08-30 17:17:07 -04:00
|
|
|
int tcp_keepidle;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_keepidle, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"time before keepalive probes begin");
|
1995-11-09 15:23:09 -05:00
|
|
|
|
1999-08-30 17:17:07 -04:00
|
|
|
int tcp_keepintvl;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_keepintvl, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"time between keepalive probes");
|
1995-11-09 15:23:09 -05:00
|
|
|
|
1999-08-30 17:17:07 -04:00
|
|
|
int tcp_delacktime;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
2007-03-19 15:00:51 -04:00
|
|
|
&tcp_delacktime, 0, sysctl_msec_to_ticks, "I",
|
1999-08-30 23:40:24 -04:00
|
|
|
"Time before a delayed ACK is sent");
|
2004-08-16 14:32:07 -04:00
|
|
|
|
2021-12-04 17:02:44 -05:00
|
|
|
VNET_DEFINE(int, tcp_msl);
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl,
|
2021-12-04 17:02:44 -05:00
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_VNET,
|
|
|
|
|
&VNET_NAME(tcp_msl), 0, sysctl_msec_to_ticks, "I",
|
2020-02-26 09:26:36 -05:00
|
|
|
"Maximum segment lifetime");
|
1999-08-30 17:17:07 -04:00
|
|
|
|
2019-03-23 17:36:59 -04:00
|
|
|
int tcp_rexmit_initial;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_initial,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
2019-03-23 17:36:59 -04:00
|
|
|
&tcp_rexmit_initial, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"Initial Retransmission Timeout");
|
|
|
|
|
|
2002-07-18 15:06:12 -04:00
|
|
|
int tcp_rexmit_min;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
2007-03-19 15:00:51 -04:00
|
|
|
&tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"Minimum Retransmission Timeout");
|
2002-07-18 15:06:12 -04:00
|
|
|
|
|
|
|
|
int tcp_rexmit_slop;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
2007-03-19 15:00:51 -04:00
|
|
|
&tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"Retransmission Timer Slop");
|
2002-07-18 15:06:12 -04:00
|
|
|
|
2020-01-08 18:30:26 -05:00
|
|
|
VNET_DEFINE(int, tcp_always_keepalive) = 1;
|
|
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_VNET|CTLFLAG_RW,
|
|
|
|
|
&VNET_NAME(tcp_always_keepalive) , 0,
|
|
|
|
|
"Assume SO_KEEPALIVE on all TCP connections");
|
1996-04-04 06:17:04 -05:00
|
|
|
|
2007-02-26 17:25:21 -05:00
|
|
|
int tcp_fast_finwait2_recycle = 0;
|
2020-02-12 08:31:36 -05:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, fast_finwait2_recycle, CTLFLAG_RW,
|
2007-03-19 15:00:51 -04:00
|
|
|
&tcp_fast_finwait2_recycle, 0,
|
|
|
|
|
"Recycle closed FIN_WAIT_2 connections faster");
|
2007-02-26 17:25:21 -05:00
|
|
|
|
|
|
|
|
int tcp_finwait2_timeout;
|
2020-02-26 09:26:36 -05:00
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"FIN-WAIT2 timeout");
|
2007-02-26 17:25:21 -05:00
|
|
|
|
2012-02-05 11:53:02 -05:00
|
|
|
int tcp_keepcnt = TCPTV_KEEPCNT;
|
|
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
|
|
|
|
|
"Number of keepalive probes to send");
|
2007-02-26 17:25:21 -05:00
|
|
|
|
1995-11-14 15:34:56 -05:00
|
|
|
/* max idle probes */
|
1999-08-30 17:17:07 -04:00
|
|
|
int tcp_maxpersistidle;
|
1995-10-03 12:54:17 -04:00
|
|
|
|
2018-06-07 14:18:13 -04:00
|
|
|
int tcp_rexmit_drop_options = 0;
|
2013-01-09 15:27:06 -05:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
|
|
|
|
|
&tcp_rexmit_drop_options, 0,
|
|
|
|
|
"Drop TCP options from 3rd and later retransmitted SYN");
|
|
|
|
|
|
2022-09-27 13:38:20 -04:00
|
|
|
int tcp_maxunacktime = TCPTV_MAXUNACKTIME;
|
|
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxunacktime,
|
|
|
|
|
CTLTYPE_INT|CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
|
&tcp_maxunacktime, 0, sysctl_msec_to_ticks, "I",
|
|
|
|
|
"Maximum time (in ms) that a session can linger without making progress");
|
|
|
|
|
|
2017-10-06 16:33:40 -04:00
|
|
|
VNET_DEFINE(int, tcp_pmtud_blackhole_detect);
|
2014-10-07 17:50:28 -04:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
|
2014-10-21 03:31:21 -04:00
|
|
|
CTLFLAG_RW|CTLFLAG_VNET,
|
2014-10-07 17:50:28 -04:00
|
|
|
&VNET_NAME(tcp_pmtud_blackhole_detect), 0,
|
|
|
|
|
"Path MTU Discovery Black Hole Detection Enabled");
|
|
|
|
|
|
|
|
|
|
#ifdef INET
|
2017-10-06 16:33:40 -04:00
|
|
|
VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200;
|
2014-10-07 17:50:28 -04:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_mss,
|
2014-10-21 03:31:21 -04:00
|
|
|
CTLFLAG_RW|CTLFLAG_VNET,
|
2014-10-07 17:50:28 -04:00
|
|
|
&VNET_NAME(tcp_pmtud_blackhole_mss), 0,
|
|
|
|
|
"Path MTU Discovery Black Hole Detection lowered MSS");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef INET6
|
2017-10-06 16:33:40 -04:00
|
|
|
VNET_DEFINE(int, tcp_v6pmtud_blackhole_mss) = 1220;
|
2014-10-07 17:50:28 -04:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, v6pmtud_blackhole_mss,
|
2014-10-21 03:31:21 -04:00
|
|
|
CTLFLAG_RW|CTLFLAG_VNET,
|
2014-10-07 17:50:28 -04:00
|
|
|
&VNET_NAME(tcp_v6pmtud_blackhole_mss), 0,
|
|
|
|
|
"Path MTU Discovery IPv6 Black Hole Detection lowered MSS");
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-06-30 00:26:29 -04:00
|
|
|
#ifdef RSS
|
|
|
|
|
static int per_cpu_timers = 1;
|
|
|
|
|
#else
|
2010-03-20 15:47:30 -04:00
|
|
|
static int per_cpu_timers = 0;
|
2014-06-30 00:26:29 -04:00
|
|
|
#endif
|
2010-03-20 15:47:30 -04:00
|
|
|
SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
|
|
|
|
|
&per_cpu_timers , 0, "run tcp timers on all cpus");
|
|
|
|
|
|
2023-06-06 16:56:44 -04:00
|
|
|
static int
|
|
|
|
|
sysctl_net_inet_tcp_retries(SYSCTL_HANDLER_ARGS)
|
|
|
|
|
{
|
|
|
|
|
int error, new;
|
|
|
|
|
|
|
|
|
|
new = V_tcp_retries;
|
|
|
|
|
error = sysctl_handle_int(oidp, &new, 0, req);
|
|
|
|
|
if (error == 0 && req->newptr) {
|
|
|
|
|
if ((new < 1) || (new > TCP_MAXRXTSHIFT))
|
|
|
|
|
error = EINVAL;
|
|
|
|
|
else
|
|
|
|
|
V_tcp_retries = new;
|
|
|
|
|
}
|
|
|
|
|
return (error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VNET_DEFINE(int, tcp_retries) = TCP_MAXRXTSHIFT;
|
|
|
|
|
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, retries,
|
|
|
|
|
CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW,
|
|
|
|
|
&VNET_NAME(tcp_retries), 0, sysctl_net_inet_tcp_retries, "I",
|
|
|
|
|
"maximum number of consecutive timer based retransmissions");
|
|
|
|
|
|
2014-05-18 18:39:01 -04:00
|
|
|
/*
|
|
|
|
|
* Map the given inp to a CPU id.
|
|
|
|
|
*
|
|
|
|
|
* This queries RSS if it's compiled in, else it defaults to the current
|
|
|
|
|
* CPU ID.
|
|
|
|
|
*/
|
2018-06-07 14:18:13 -04:00
|
|
|
inline int
|
2014-05-18 18:39:01 -04:00
|
|
|
inp_to_cpuid(struct inpcb *inp)
|
|
|
|
|
{
|
|
|
|
|
u_int cpuid;
|
|
|
|
|
|
|
|
|
|
if (per_cpu_timers) {
|
2022-02-07 21:22:03 -05:00
|
|
|
#ifdef RSS
|
2014-05-18 18:39:01 -04:00
|
|
|
cpuid = rss_hash2cpuid(inp->inp_flowid, inp->inp_flowtype);
|
|
|
|
|
if (cpuid == NETISR_CPUID_NONE)
|
|
|
|
|
return (curcpu); /* XXX */
|
|
|
|
|
else
|
|
|
|
|
return (cpuid);
|
2022-02-07 21:22:03 -05:00
|
|
|
#endif
|
2014-05-18 18:39:01 -04:00
|
|
|
/*
|
|
|
|
|
* We don't have a flowid -> cpuid mapping, so cheat and
|
|
|
|
|
* just map unknown cpuids to curcpu. Not the best, but
|
|
|
|
|
* apparently better than defaulting to swi 0.
|
|
|
|
|
*/
|
|
|
|
|
cpuid = inp->inp_flowid % (mp_maxid + 1);
|
|
|
|
|
if (! CPU_ABSENT(cpuid))
|
|
|
|
|
return (cpuid);
|
|
|
|
|
return (curcpu);
|
2022-02-07 21:22:03 -05:00
|
|
|
} else {
|
2014-05-18 18:39:01 -04:00
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-20 15:47:30 -04:00
|
|
|
|
1994-05-24 06:09:53 -04:00
|
|
|
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
2003-06-04 06:03:55 -04:00
|
|
|
{ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
|
1994-05-24 06:09:53 -04:00
|
|
|
|
2018-06-07 14:18:13 -04:00
|
|
|
int tcp_totbackoff = 2559; /* sum of tcp_backoff[] */
|
1995-10-03 12:54:17 -04:00
|
|
|
|
2007-09-07 05:19:22 -04:00
|
|
|
/*
|
|
|
|
|
* TCP timer processing.
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
*
|
|
|
|
|
* Each connection has 5 timers associated with it, which can be scheduled
|
|
|
|
|
* simultaneously. They all are serviced by one callout tcp_timer_enter().
|
|
|
|
|
* This function executes the next timer via tcp_timersw[] vector. Each
|
|
|
|
|
* timer is supposed to return 'true' unless the connection was destroyed.
|
|
|
|
|
* In the former case tcp_timer_enter() will schedule callout for next timer.
|
2007-09-07 05:19:22 -04:00
|
|
|
*/
|
2007-04-11 05:45:16 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
typedef bool tcp_timer_t(struct tcpcb *);
|
|
|
|
|
static tcp_timer_t tcp_timer_delack;
|
|
|
|
|
static tcp_timer_t tcp_timer_2msl;
|
|
|
|
|
static tcp_timer_t tcp_timer_keep;
|
|
|
|
|
static tcp_timer_t tcp_timer_persist;
|
|
|
|
|
static tcp_timer_t tcp_timer_rexmt;
|
|
|
|
|
|
|
|
|
|
static tcp_timer_t * const tcp_timersw[TT_N] = {
|
|
|
|
|
[TT_DELACK] = tcp_timer_delack,
|
|
|
|
|
[TT_REXMT] = tcp_timer_rexmt,
|
|
|
|
|
[TT_PERSIST] = tcp_timer_persist,
|
|
|
|
|
[TT_KEEP] = tcp_timer_keep,
|
|
|
|
|
[TT_2MSL] = tcp_timer_2msl,
|
|
|
|
|
};
|
1994-05-24 06:09:53 -04:00
|
|
|
|
2022-10-04 01:21:55 -04:00
|
|
|
/*
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
* tcp_output_locked() s a timer specific variation of call to tcp_output(),
|
|
|
|
|
* see tcp_var.h for the rest. It handles drop request from advanced stacks,
|
|
|
|
|
* but keeps tcpcb locked unless tcp_drop() destroyed it.
|
|
|
|
|
* Returns true if tcpcb is valid and locked.
|
2022-10-04 01:21:55 -04:00
|
|
|
*/
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static inline bool
|
|
|
|
|
tcp_output_locked(struct tcpcb *tp)
|
2016-08-16 08:40:56 -04:00
|
|
|
{
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
int rv;
|
2022-10-04 01:21:55 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(tptoinpcb(tp));
|
2022-10-04 01:21:55 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if ((rv = tp->t_fb->tfb_tcp_output(tp)) < 0) {
|
|
|
|
|
KASSERT(tp->t_fb->tfb_flags & TCP_FUNC_OUTPUT_CANDROP,
|
|
|
|
|
("TCP stack %s requested tcp_drop(%p)",
|
|
|
|
|
tp->t_fb->tfb_tcp_block_name, tp));
|
|
|
|
|
tp = tcp_drop(tp, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (tp != NULL);
|
2022-10-04 01:21:55 -04:00
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static bool
|
|
|
|
|
tcp_timer_delack(struct tcpcb *tp)
|
2022-10-04 01:21:55 -04:00
|
|
|
{
|
|
|
|
|
struct epoch_tracker et;
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
#if defined(INVARIANTS) || defined(VIMAGE)
|
2022-11-08 13:24:40 -05:00
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
#endif
|
|
|
|
|
bool rv;
|
2022-10-04 01:21:55 -04:00
|
|
|
|
|
|
|
|
INP_WLOCK_ASSERT(inp);
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
CURVNET_SET(inp->inp_vnet);
|
|
|
|
|
tp->t_flags |= TF_ACKNOW;
|
|
|
|
|
TCPSTAT_INC(tcps_delack);
|
2022-10-04 01:21:55 -04:00
|
|
|
NET_EPOCH_ENTER(et);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
rv = tcp_output_locked(tp);
|
2022-10-04 01:21:55 -04:00
|
|
|
NET_EPOCH_EXIT(et);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
CURVNET_RESTORE();
|
|
|
|
|
|
|
|
|
|
return (rv);
|
2016-08-16 08:40:56 -04:00
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static bool
|
|
|
|
|
tcp_timer_2msl(struct tcpcb *tp)
|
1999-08-30 17:17:07 -04:00
|
|
|
{
|
2022-11-08 13:24:40 -05:00
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
bool close = false;
|
1994-05-24 06:09:53 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
|
2022-11-08 13:24:40 -05:00
|
|
|
CURVNET_SET(inp->inp_vnet);
|
2022-09-26 15:20:18 -04:00
|
|
|
tcp_log_end_status(tp, TCP_EI_STATUS_2MSL);
|
2007-09-07 05:19:22 -04:00
|
|
|
tcp_free_sackholes(tp);
|
1994-05-24 06:09:53 -04:00
|
|
|
/*
|
|
|
|
|
* 2 MSL timeout in shutdown went off. If we're closed but
|
|
|
|
|
* still waiting for peer to close and connection has been idle
|
2015-08-18 04:27:26 -04:00
|
|
|
* too long delete connection control block. Otherwise, check
|
|
|
|
|
* again in a bit.
|
|
|
|
|
*
|
2020-02-12 08:31:36 -05:00
|
|
|
* If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed,
|
|
|
|
|
* there's no point in hanging onto FIN_WAIT_2 socket. Just close it.
|
2007-02-26 17:25:21 -05:00
|
|
|
* Ignore fact that there were recent incoming segments.
|
2022-11-08 13:24:39 -05:00
|
|
|
*
|
|
|
|
|
* XXXGL: check if inp_socket shall always be !NULL here?
|
1994-05-24 06:09:53 -04:00
|
|
|
*/
|
2022-10-06 22:22:23 -04:00
|
|
|
if (tp->t_state == TCPS_TIME_WAIT) {
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
close = true;
|
2022-10-06 22:22:23 -04:00
|
|
|
} else if (tp->t_state == TCPS_FIN_WAIT_2 &&
|
2022-11-08 13:24:40 -05:00
|
|
|
tcp_fast_finwait2_recycle && inp->inp_socket &&
|
|
|
|
|
(inp->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_finwait2_drops);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
close = true;
|
2007-02-26 17:25:21 -05:00
|
|
|
} else {
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp))
|
|
|
|
|
tcp_timer_activate(tp, TT_2MSL, TP_KEEPINTVL(tp));
|
|
|
|
|
else
|
|
|
|
|
close = true;
|
2018-07-03 22:47:16 -04:00
|
|
|
}
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if (close) {
|
|
|
|
|
struct epoch_tracker et;
|
1999-08-30 17:17:07 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
|
|
|
|
tp = tcp_close(tp);
|
|
|
|
|
NET_EPOCH_EXIT(et);
|
|
|
|
|
}
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 11:37:58 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
return (tp != NULL);
|
1999-08-30 17:17:07 -04:00
|
|
|
}
|
1994-05-24 06:09:53 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static bool
|
|
|
|
|
tcp_timer_keep(struct tcpcb *tp)
|
1999-08-30 17:17:07 -04:00
|
|
|
{
|
2022-11-08 13:24:40 -05:00
|
|
|
struct epoch_tracker et;
|
|
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
2001-06-22 23:21:46 -04:00
|
|
|
struct tcptemp *t_template;
|
1999-08-30 17:17:07 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
|
2022-11-08 13:24:40 -05:00
|
|
|
CURVNET_SET(inp->inp_vnet);
|
2016-10-14 10:57:43 -04:00
|
|
|
/*
|
|
|
|
|
* Because we don't regularly reset the keepalive callout in
|
|
|
|
|
* the ESTABLISHED state, it may be that we don't actually need
|
|
|
|
|
* to send a keepalive yet. If that occurs, schedule another
|
|
|
|
|
* call for the next time the keepalive timer might expire.
|
|
|
|
|
*/
|
|
|
|
|
if (TCPS_HAVEESTABLISHED(tp->t_state)) {
|
|
|
|
|
u_int idletime;
|
|
|
|
|
|
|
|
|
|
idletime = ticks - tp->t_rcvtime;
|
|
|
|
|
if (idletime < TP_KEEPIDLE(tp)) {
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tcp_timer_activate(tp, TT_KEEP,
|
|
|
|
|
TP_KEEPIDLE(tp) - idletime);
|
2016-10-14 10:57:43 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
return (true);
|
2016-10-14 10:57:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1994-05-24 06:09:53 -04:00
|
|
|
/*
|
1999-08-30 17:17:07 -04:00
|
|
|
* Keep-alive timer went off; send something
|
|
|
|
|
* or drop connection if idle for too long.
|
1994-05-24 06:09:53 -04:00
|
|
|
*/
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_keeptimeo);
|
1999-08-30 17:17:07 -04:00
|
|
|
if (tp->t_state < TCPS_ESTABLISHED)
|
|
|
|
|
goto dropit;
|
2020-01-08 18:30:26 -05:00
|
|
|
if ((V_tcp_always_keepalive ||
|
2018-01-30 18:01:37 -05:00
|
|
|
inp->inp_socket->so_options & SO_KEEPALIVE) &&
|
1999-08-30 17:17:07 -04:00
|
|
|
tp->t_state <= TCPS_CLOSING) {
|
2012-02-05 11:53:02 -05:00
|
|
|
if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
|
1999-08-30 17:17:07 -04:00
|
|
|
goto dropit;
|
1994-05-24 06:09:53 -04:00
|
|
|
/*
|
1999-08-30 17:17:07 -04:00
|
|
|
* Send a packet designed to force a response
|
|
|
|
|
* if the peer is up and reachable:
|
|
|
|
|
* either an ACK if the connection is still alive,
|
|
|
|
|
* or an RST if the peer has closed the connection
|
|
|
|
|
* due to timeout or reboot.
|
|
|
|
|
* Using sequence number tp->snd_una-1
|
|
|
|
|
* causes the transmitted zero-length segment
|
|
|
|
|
* to lie outside the receive window;
|
|
|
|
|
* by the protocol spec, this requires the
|
|
|
|
|
* correspondent TCP to respond.
|
1994-05-24 06:09:53 -04:00
|
|
|
*/
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_keepprobe);
|
2003-02-19 17:18:06 -05:00
|
|
|
t_template = tcpip_maketemplate(inp);
|
2001-06-22 23:21:46 -04:00
|
|
|
if (t_template) {
|
2020-01-22 00:51:22 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
2001-06-22 23:21:46 -04:00
|
|
|
tcp_respond(tp, t_template->tt_ipgen,
|
|
|
|
|
&t_template->tt_t, (struct mbuf *)NULL,
|
|
|
|
|
tp->rcv_nxt, tp->snd_una - 1, 0);
|
2020-01-22 00:51:22 -05:00
|
|
|
NET_EPOCH_EXIT(et);
|
2008-06-02 10:20:26 -04:00
|
|
|
free(t_template, M_TEMP);
|
2001-06-22 23:21:46 -04:00
|
|
|
}
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINTVL(tp));
|
2016-08-16 08:40:56 -04:00
|
|
|
} else
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
|
1999-08-30 17:17:07 -04:00
|
|
|
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 11:37:58 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
return (true);
|
1999-08-30 17:17:07 -04:00
|
|
|
|
|
|
|
|
dropit:
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_keepdrops);
|
2019-11-06 19:27:23 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
2022-09-26 15:20:18 -04:00
|
|
|
tcp_log_end_status(tp, TCP_EI_STATUS_KEEP_MAX);
|
2007-09-07 05:19:22 -04:00
|
|
|
tp = tcp_drop(tp, ETIMEDOUT);
|
2019-11-06 19:27:23 -05:00
|
|
|
NET_EPOCH_EXIT(et);
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 11:37:58 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
return (tp != NULL);
|
1999-08-30 17:17:07 -04:00
|
|
|
}
|
|
|
|
|
|
2022-09-27 13:38:20 -04:00
|
|
|
/*
|
|
|
|
|
* Has this session exceeded the maximum time without seeing a substantive
|
|
|
|
|
* acknowledgement? If so, return true; otherwise false.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
tcp_maxunacktime_check(struct tcpcb *tp)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/* Are we tracking this timer for this session? */
|
|
|
|
|
if (TP_MAXUNACKTIME(tp) == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* Do we have a current measurement. */
|
|
|
|
|
if (tp->t_acktime == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* Are we within the acceptable range? */
|
|
|
|
|
if (TSTMP_GT(TP_MAXUNACKTIME(tp) + tp->t_acktime, (u_int)ticks))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* We exceeded the timer. */
|
|
|
|
|
TCPSTAT_INC(tcps_progdrops);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static bool
|
|
|
|
|
tcp_timer_persist(struct tcpcb *tp)
|
1999-08-30 17:17:07 -04:00
|
|
|
{
|
2018-07-03 22:47:16 -04:00
|
|
|
struct epoch_tracker et;
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
#if defined(INVARIANTS) || defined(VIMAGE)
|
2022-11-08 13:24:40 -05:00
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
1999-08-30 17:17:07 -04:00
|
|
|
#endif
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
bool progdrop, rv;
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
|
|
|
|
|
CURVNET_SET(inp->inp_vnet);
|
1994-05-24 06:09:53 -04:00
|
|
|
/*
|
2016-05-03 14:05:43 -04:00
|
|
|
* Persistence timer into zero window.
|
1994-05-24 06:09:53 -04:00
|
|
|
* Force a byte to be output, if possible.
|
|
|
|
|
*/
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_persisttimeo);
|
1999-08-30 17:17:07 -04:00
|
|
|
/*
|
|
|
|
|
* Hack: if the peer is dead/unreachable, we do not
|
|
|
|
|
* time out if the window is closed. After a full
|
|
|
|
|
* backoff, drop the connection if the idle time
|
|
|
|
|
* (no responses to probes) reaches the maximum
|
|
|
|
|
* backoff that we would use if retransmitting.
|
2022-09-27 13:38:20 -04:00
|
|
|
* Also, drop the connection if we haven't been making
|
|
|
|
|
* progress.
|
1999-08-30 17:17:07 -04:00
|
|
|
*/
|
2022-09-27 13:38:20 -04:00
|
|
|
progdrop = tcp_maxunacktime_check(tp);
|
2023-06-06 16:56:44 -04:00
|
|
|
if (progdrop || (tp->t_rxtshift >= V_tcp_retries &&
|
2009-06-16 15:00:48 -04:00
|
|
|
(ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
|
2022-09-27 13:38:20 -04:00
|
|
|
ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff))) {
|
|
|
|
|
if (!progdrop)
|
|
|
|
|
TCPSTAT_INC(tcps_persistdrop);
|
2022-09-26 15:20:18 -04:00
|
|
|
tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
goto dropit;
|
1999-08-30 17:17:07 -04:00
|
|
|
}
|
2012-10-28 15:58:20 -04:00
|
|
|
/*
|
|
|
|
|
* If the user has closed the socket then drop a persisting
|
|
|
|
|
* connection after a much reduced timeout.
|
|
|
|
|
*/
|
|
|
|
|
if (tp->t_state > TCPS_CLOSE_WAIT &&
|
|
|
|
|
(ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) {
|
|
|
|
|
TCPSTAT_INC(tcps_persistdrop);
|
2022-09-26 15:20:18 -04:00
|
|
|
tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
goto dropit;
|
2012-10-28 15:58:20 -04:00
|
|
|
}
|
1999-08-30 17:17:07 -04:00
|
|
|
tcp_setpersist(tp);
|
2005-05-20 20:38:29 -04:00
|
|
|
tp->t_flags |= TF_FORCEDATA;
|
2020-01-22 00:53:16 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if ((rv = tcp_output_locked(tp)))
|
|
|
|
|
tp->t_flags &= ~TF_FORCEDATA;
|
|
|
|
|
NET_EPOCH_EXIT(et);
|
|
|
|
|
CURVNET_RESTORE();
|
1999-08-30 17:17:07 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
return (rv);
|
|
|
|
|
|
|
|
|
|
dropit:
|
|
|
|
|
NET_EPOCH_ENTER(et);
|
|
|
|
|
tp = tcp_drop(tp, ETIMEDOUT);
|
2021-12-26 11:48:19 -05:00
|
|
|
NET_EPOCH_EXIT(et);
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 11:37:58 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
return (tp != NULL);
|
1999-08-30 17:17:07 -04:00
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static bool
|
|
|
|
|
tcp_timer_rexmt(struct tcpcb *tp)
|
1999-08-30 17:17:07 -04:00
|
|
|
{
|
2022-11-08 13:24:40 -05:00
|
|
|
struct epoch_tracker et;
|
|
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
int rexmt;
|
|
|
|
|
bool isipv6, rv;
|
1999-08-30 17:17:07 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
|
2022-11-08 13:24:40 -05:00
|
|
|
CURVNET_SET(inp->inp_vnet);
|
2004-06-23 17:04:37 -04:00
|
|
|
tcp_free_sackholes(tp);
|
2016-05-17 05:53:22 -04:00
|
|
|
if (tp->t_fb->tfb_tcp_rexmit_tmr) {
|
|
|
|
|
/* The stack has a timer action too. */
|
|
|
|
|
(*tp->t_fb->tfb_tcp_rexmit_tmr)(tp);
|
|
|
|
|
}
|
1999-08-30 17:17:07 -04:00
|
|
|
/*
|
|
|
|
|
* Retransmission timer went off. Message has not
|
|
|
|
|
* been acked within retransmit interval. Back off
|
|
|
|
|
* to a longer retransmit interval and retransmit one segment.
|
2022-09-27 13:38:20 -04:00
|
|
|
*
|
|
|
|
|
* If we've either exceeded the maximum number of retransmissions,
|
|
|
|
|
* or we've gone long enough without making progress, then drop
|
|
|
|
|
* the session.
|
1999-08-30 17:17:07 -04:00
|
|
|
*/
|
2023-06-06 16:56:44 -04:00
|
|
|
if (++tp->t_rxtshift > V_tcp_retries || tcp_maxunacktime_check(tp)) {
|
|
|
|
|
if (tp->t_rxtshift > V_tcp_retries)
|
2022-09-27 13:38:20 -04:00
|
|
|
TCPSTAT_INC(tcps_timeoutdrop);
|
2023-06-06 16:56:44 -04:00
|
|
|
tp->t_rxtshift = V_tcp_retries;
|
2022-09-26 15:20:18 -04:00
|
|
|
tcp_log_end_status(tp, TCP_EI_STATUS_RETRAN);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
|
|
|
|
tp = tcp_drop(tp, ETIMEDOUT);
|
|
|
|
|
NET_EPOCH_EXIT(et);
|
2022-10-04 01:21:55 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
return (tp != NULL);
|
1999-08-30 17:17:07 -04:00
|
|
|
}
|
2012-10-28 13:25:08 -04:00
|
|
|
if (tp->t_state == TCPS_SYN_SENT) {
|
|
|
|
|
/*
|
|
|
|
|
* If the SYN was retransmitted, indicate CWND to be
|
|
|
|
|
* limited to 1 segment in cc_conn_init().
|
|
|
|
|
*/
|
|
|
|
|
tp->snd_cwnd = 1;
|
|
|
|
|
} else if (tp->t_rxtshift == 1) {
|
1995-07-29 14:48:44 -04:00
|
|
|
/*
|
1999-08-30 17:17:07 -04:00
|
|
|
* first retransmit; record ssthresh and cwnd so they can
|
2004-08-16 14:32:07 -04:00
|
|
|
* be recovered if this turns out to be a "bad" retransmit.
|
|
|
|
|
* A retransmit is considered "bad" if an ACK for this
|
1999-08-30 17:17:07 -04:00
|
|
|
* segment is received within RTT/2 interval; the assumption
|
2004-08-16 14:32:07 -04:00
|
|
|
* here is that the ACK was already in flight. See
|
1999-08-30 17:17:07 -04:00
|
|
|
* "On Estimating End-to-End Network Path Properties" by
|
|
|
|
|
* Allman and Paxson for more details.
|
1995-07-29 14:48:44 -04:00
|
|
|
*/
|
1999-08-30 17:17:07 -04:00
|
|
|
tp->snd_cwnd_prev = tp->snd_cwnd;
|
|
|
|
|
tp->snd_ssthresh_prev = tp->snd_ssthresh;
|
2003-07-15 17:49:53 -04:00
|
|
|
tp->snd_recover_prev = tp->snd_recover;
|
2010-11-12 01:41:55 -05:00
|
|
|
if (IN_FASTRECOVERY(tp->t_flags))
|
|
|
|
|
tp->t_flags |= TF_WASFRECOVERY;
|
2003-07-15 17:49:53 -04:00
|
|
|
else
|
2010-11-12 01:41:55 -05:00
|
|
|
tp->t_flags &= ~TF_WASFRECOVERY;
|
|
|
|
|
if (IN_CONGRECOVERY(tp->t_flags))
|
|
|
|
|
tp->t_flags |= TF_WASCRECOVERY;
|
|
|
|
|
else
|
|
|
|
|
tp->t_flags &= ~TF_WASCRECOVERY;
|
2018-05-07 22:22:34 -04:00
|
|
|
if ((tp->t_flags & TF_RCVD_TSTMP) == 0)
|
|
|
|
|
tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
|
|
|
|
|
/* In the event that we've negotiated timestamps
|
|
|
|
|
* badrxtwin will be set to the value that we set
|
|
|
|
|
* the retransmitted packet's to_tsval to by tcp_output
|
|
|
|
|
*/
|
2011-04-29 11:40:12 -04:00
|
|
|
tp->t_flags |= TF_PREVVALID;
|
|
|
|
|
} else
|
|
|
|
|
tp->t_flags &= ~TF_PREVVALID;
|
2009-04-11 18:07:19 -04:00
|
|
|
TCPSTAT_INC(tcps_rexmttimeo);
|
2015-12-24 14:09:48 -05:00
|
|
|
if ((tp->t_state == TCPS_SYN_SENT) ||
|
|
|
|
|
(tp->t_state == TCPS_SYN_RECEIVED))
|
2019-03-23 17:36:59 -04:00
|
|
|
rexmt = tcp_rexmit_initial * tcp_backoff[tp->t_rxtshift];
|
2001-02-26 16:33:55 -05:00
|
|
|
else
|
|
|
|
|
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
1999-08-30 17:17:07 -04:00
|
|
|
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
|
|
|
|
tp->t_rttmin, TCPTV_REXMTMAX);
|
2014-10-07 17:50:28 -04:00
|
|
|
|
2014-10-13 17:06:21 -04:00
|
|
|
/*
|
|
|
|
|
* We enter the path for PLMTUD if connection is established or, if
|
|
|
|
|
* connection is FIN_WAIT_1 status, reason for the last is that if
|
|
|
|
|
* amount of data we send is very small, we could send it in couple of
|
|
|
|
|
* packets and process straight to FIN. In that case we won't catch
|
|
|
|
|
* ESTABLISHED state.
|
|
|
|
|
*/
|
2014-10-07 17:50:28 -04:00
|
|
|
#ifdef INET6
|
2022-11-08 13:24:40 -05:00
|
|
|
isipv6 = (inp->inp_vflag & INP_IPV6) ? true : false;
|
2020-03-31 11:54:54 -04:00
|
|
|
#else
|
|
|
|
|
isipv6 = false;
|
2014-10-07 17:50:28 -04:00
|
|
|
#endif
|
2020-03-31 11:54:54 -04:00
|
|
|
if (((V_tcp_pmtud_blackhole_detect == 1) ||
|
|
|
|
|
(V_tcp_pmtud_blackhole_detect == 2 && !isipv6) ||
|
|
|
|
|
(V_tcp_pmtud_blackhole_detect == 3 && isipv6)) &&
|
|
|
|
|
((tp->t_state == TCPS_ESTABLISHED) ||
|
|
|
|
|
(tp->t_state == TCPS_FIN_WAIT_1))) {
|
2020-04-14 12:35:05 -04:00
|
|
|
if (tp->t_rxtshift == 1) {
|
|
|
|
|
/*
|
|
|
|
|
* We enter blackhole detection after the first
|
|
|
|
|
* unsuccessful timer based retransmission.
|
|
|
|
|
* Then we reduce up to two times the MSS, each
|
|
|
|
|
* candidate giving two tries of retransmissions.
|
|
|
|
|
* But we give a candidate only two tries, if it
|
|
|
|
|
* actually reduces the MSS.
|
|
|
|
|
*/
|
|
|
|
|
tp->t_blackhole_enter = 2;
|
|
|
|
|
tp->t_blackhole_exit = tp->t_blackhole_enter;
|
|
|
|
|
if (isipv6) {
|
|
|
|
|
#ifdef INET6
|
|
|
|
|
if (tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss)
|
|
|
|
|
tp->t_blackhole_exit += 2;
|
|
|
|
|
if (tp->t_maxseg > V_tcp_v6mssdflt &&
|
|
|
|
|
V_tcp_v6pmtud_blackhole_mss > V_tcp_v6mssdflt)
|
|
|
|
|
tp->t_blackhole_exit += 2;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
#ifdef INET
|
|
|
|
|
if (tp->t_maxseg > V_tcp_pmtud_blackhole_mss)
|
|
|
|
|
tp->t_blackhole_exit += 2;
|
|
|
|
|
if (tp->t_maxseg > V_tcp_mssdflt &&
|
|
|
|
|
V_tcp_pmtud_blackhole_mss > V_tcp_mssdflt)
|
|
|
|
|
tp->t_blackhole_exit += 2;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-07 17:50:28 -04:00
|
|
|
if (((tp->t_flags2 & (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) ==
|
|
|
|
|
(TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) &&
|
2020-04-14 12:35:05 -04:00
|
|
|
(tp->t_rxtshift >= tp->t_blackhole_enter &&
|
|
|
|
|
tp->t_rxtshift < tp->t_blackhole_exit &&
|
|
|
|
|
(tp->t_rxtshift - tp->t_blackhole_enter) % 2 == 0)) {
|
2014-10-07 17:50:28 -04:00
|
|
|
/*
|
|
|
|
|
* Enter Path MTU Black-hole Detection mechanism:
|
|
|
|
|
* - Disable Path MTU Discovery (IP "DF" bit).
|
|
|
|
|
* - Reduce MTU to lower value than what we
|
|
|
|
|
* negotiated with peer.
|
|
|
|
|
*/
|
2017-08-28 07:41:18 -04:00
|
|
|
if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) == 0) {
|
|
|
|
|
/* Record that we may have found a black hole. */
|
|
|
|
|
tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
|
|
|
|
|
/* Keep track of previous MSS. */
|
|
|
|
|
tp->t_pmtud_saved_maxseg = tp->t_maxseg;
|
|
|
|
|
}
|
2014-10-07 17:50:28 -04:00
|
|
|
|
2020-02-12 08:31:36 -05:00
|
|
|
/*
|
2014-10-07 17:50:28 -04:00
|
|
|
* Reduce the MSS to blackhole value or to the default
|
|
|
|
|
* in an attempt to retransmit.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef INET6
|
|
|
|
|
if (isipv6 &&
|
2020-04-14 12:35:05 -04:00
|
|
|
tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss &&
|
|
|
|
|
V_tcp_v6pmtud_blackhole_mss > V_tcp_v6mssdflt) {
|
2014-10-07 17:50:28 -04:00
|
|
|
/* Use the sysctl tuneable blackhole MSS. */
|
2016-01-06 19:14:42 -05:00
|
|
|
tp->t_maxseg = V_tcp_v6pmtud_blackhole_mss;
|
2017-08-25 15:41:38 -04:00
|
|
|
TCPSTAT_INC(tcps_pmtud_blackhole_activated);
|
2014-10-07 17:50:28 -04:00
|
|
|
} else if (isipv6) {
|
|
|
|
|
/* Use the default MSS. */
|
2016-01-06 19:14:42 -05:00
|
|
|
tp->t_maxseg = V_tcp_v6mssdflt;
|
2014-10-07 17:50:28 -04:00
|
|
|
/*
|
|
|
|
|
* Disable Path MTU Discovery when we switch to
|
|
|
|
|
* minmss.
|
|
|
|
|
*/
|
|
|
|
|
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
|
2017-08-25 15:41:38 -04:00
|
|
|
TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
|
2014-10-07 17:50:28 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(INET6) && defined(INET)
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef INET
|
2020-04-14 12:35:05 -04:00
|
|
|
if (tp->t_maxseg > V_tcp_pmtud_blackhole_mss &&
|
|
|
|
|
V_tcp_pmtud_blackhole_mss > V_tcp_mssdflt) {
|
2014-10-07 17:50:28 -04:00
|
|
|
/* Use the sysctl tuneable blackhole MSS. */
|
2016-01-06 19:14:42 -05:00
|
|
|
tp->t_maxseg = V_tcp_pmtud_blackhole_mss;
|
2017-08-25 15:41:38 -04:00
|
|
|
TCPSTAT_INC(tcps_pmtud_blackhole_activated);
|
2014-10-07 17:50:28 -04:00
|
|
|
} else {
|
|
|
|
|
/* Use the default MSS. */
|
2016-01-06 19:14:42 -05:00
|
|
|
tp->t_maxseg = V_tcp_mssdflt;
|
2014-10-07 17:50:28 -04:00
|
|
|
/*
|
|
|
|
|
* Disable Path MTU Discovery when we switch to
|
|
|
|
|
* minmss.
|
|
|
|
|
*/
|
|
|
|
|
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
|
2017-08-25 15:41:38 -04:00
|
|
|
TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
|
2014-10-07 17:50:28 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/*
|
|
|
|
|
* Reset the slow-start flight size
|
|
|
|
|
* as it may depend on the new MSS.
|
|
|
|
|
*/
|
|
|
|
|
if (CC_ALGO(tp)->conn_init != NULL)
|
tcp: embed inpcb into tcpcb
For the TCP protocol inpcb storage specify allocation size that would
provide space to most of the data a TCP connection needs, embedding
into struct tcpcb several structures, that previously were allocated
separately.
The most import one is the inpcb itself. With embedding we can provide
strong guarantee that with a valid TCP inpcb the tcpcb is always valid
and vice versa. Also we reduce number of allocs/frees per connection.
The embedded inpcb is placed in the beginning of the struct tcpcb,
since in_pcballoc() requires that. However, later we may want to move
it around for cache line efficiency, and this can be done with a little
effort. The new intotcpcb() macro is ready for such move.
The congestion algorithm data, the TCP timers and osd(9) data are
also embedded into tcpcb, and temprorary struct tcpcb_mem goes away.
There was no extra allocation here, but we went through extra pointer
every time we accessed this data.
One interesting side effect is that now TCP data is allocated from
SMR-protected zone. Potentially this allows the TCP stacks or other
TCP related modules to utilize that for their own synchronization.
Large part of the change was done with sed script:
s/tp->ccv->/tp->t_ccv./g
s/tp->ccv/\&tp->t_ccv/g
s/tp->cc_algo/tp->t_cc/g
s/tp->t_timers->tt_/tp->tt_/g
s/CCV\(ccv, osd\)/\&CCV(ccv, t_osd)/g
Dependency side effect is that code that needs to know struct tcpcb
should also know struct inpcb, that added several <netinet/in_pcb.h>.
Differential revision: https://reviews.freebsd.org/D37127
2022-12-07 12:00:48 -05:00
|
|
|
CC_ALGO(tp)->conn_init(&tp->t_ccv);
|
2014-10-07 17:50:28 -04:00
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
* If further retransmissions are still unsuccessful
|
|
|
|
|
* with a lowered MTU, maybe this isn't a blackhole and
|
|
|
|
|
* we restore the previous MSS and blackhole detection
|
|
|
|
|
* flags.
|
|
|
|
|
*/
|
|
|
|
|
if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) &&
|
2020-04-14 12:35:05 -04:00
|
|
|
(tp->t_rxtshift >= tp->t_blackhole_exit)) {
|
2014-10-07 17:50:28 -04:00
|
|
|
tp->t_flags2 |= TF2_PLPMTU_PMTUD;
|
|
|
|
|
tp->t_flags2 &= ~TF2_PLPMTU_BLACKHOLE;
|
2016-01-06 19:14:42 -05:00
|
|
|
tp->t_maxseg = tp->t_pmtud_saved_maxseg;
|
2017-08-25 15:41:38 -04:00
|
|
|
TCPSTAT_INC(tcps_pmtud_blackhole_failed);
|
2014-10-07 17:50:28 -04:00
|
|
|
/*
|
|
|
|
|
* Reset the slow-start flight size as it
|
|
|
|
|
* may depend on the new MSS.
|
|
|
|
|
*/
|
|
|
|
|
if (CC_ALGO(tp)->conn_init != NULL)
|
tcp: embed inpcb into tcpcb
For the TCP protocol inpcb storage specify allocation size that would
provide space to most of the data a TCP connection needs, embedding
into struct tcpcb several structures, that previously were allocated
separately.
The most import one is the inpcb itself. With embedding we can provide
strong guarantee that with a valid TCP inpcb the tcpcb is always valid
and vice versa. Also we reduce number of allocs/frees per connection.
The embedded inpcb is placed in the beginning of the struct tcpcb,
since in_pcballoc() requires that. However, later we may want to move
it around for cache line efficiency, and this can be done with a little
effort. The new intotcpcb() macro is ready for such move.
The congestion algorithm data, the TCP timers and osd(9) data are
also embedded into tcpcb, and temprorary struct tcpcb_mem goes away.
There was no extra allocation here, but we went through extra pointer
every time we accessed this data.
One interesting side effect is that now TCP data is allocated from
SMR-protected zone. Potentially this allows the TCP stacks or other
TCP related modules to utilize that for their own synchronization.
Large part of the change was done with sed script:
s/tp->ccv->/tp->t_ccv./g
s/tp->ccv/\&tp->t_ccv/g
s/tp->cc_algo/tp->t_cc/g
s/tp->t_timers->tt_/tp->tt_/g
s/CCV\(ccv, osd\)/\&CCV(ccv, t_osd)/g
Dependency side effect is that code that needs to know struct tcpcb
should also know struct inpcb, that added several <netinet/in_pcb.h>.
Differential revision: https://reviews.freebsd.org/D37127
2022-12-07 12:00:48 -05:00
|
|
|
CC_ALGO(tp)->conn_init(&tp->t_ccv);
|
2014-10-07 17:50:28 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-31 15:24:49 -04:00
|
|
|
/*
|
2012-10-28 15:22:18 -04:00
|
|
|
* Disable RFC1323 and SACK if we haven't got any response to
|
2004-08-16 14:32:07 -04:00
|
|
|
* our third SYN to work-around some broken terminal servers
|
|
|
|
|
* (most of which have hopefully been retired) that have bad VJ
|
|
|
|
|
* header compression code which trashes TCP segments containing
|
2001-05-31 15:24:49 -04:00
|
|
|
* unknown-to-them TCP options.
|
|
|
|
|
*/
|
2013-01-09 15:27:06 -05:00
|
|
|
if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
|
|
|
|
|
(tp->t_rxtshift == 3))
|
2012-10-28 15:20:23 -04:00
|
|
|
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
|
1994-05-24 06:09:53 -04:00
|
|
|
/*
|
2017-02-11 12:05:08 -05:00
|
|
|
* If we backed off this far, notify the L3 protocol that we're having
|
|
|
|
|
* connection problems.
|
1994-05-24 06:09:53 -04:00
|
|
|
*/
|
2017-02-11 12:05:08 -05:00
|
|
|
if (tp->t_rxtshift > TCP_RTT_INVALIDATE) {
|
2000-01-09 14:17:30 -05:00
|
|
|
#ifdef INET6
|
2022-11-08 13:24:40 -05:00
|
|
|
if ((inp->inp_vflag & INP_IPV6) != 0)
|
|
|
|
|
in6_losing(inp);
|
2016-03-24 03:54:56 -04:00
|
|
|
else
|
2000-01-09 14:17:30 -05:00
|
|
|
#endif
|
2022-11-08 13:24:40 -05:00
|
|
|
in_losing(inp);
|
1994-05-24 06:09:53 -04:00
|
|
|
}
|
1999-08-30 17:17:07 -04:00
|
|
|
tp->snd_nxt = tp->snd_una;
|
2003-07-15 17:49:53 -04:00
|
|
|
tp->snd_recover = tp->snd_max;
|
1999-08-30 17:17:07 -04:00
|
|
|
/*
|
|
|
|
|
* Force a segment to be sent.
|
|
|
|
|
*/
|
|
|
|
|
tp->t_flags |= TF_ACKNOW;
|
|
|
|
|
/*
|
|
|
|
|
* If timing a segment in this window, stop the timer.
|
|
|
|
|
*/
|
|
|
|
|
tp->t_rtttime = 0;
|
2010-11-12 01:41:55 -05:00
|
|
|
|
2010-12-01 19:47:55 -05:00
|
|
|
cc_cong_signal(tp, NULL, CC_RTO);
|
2020-01-22 00:53:16 -05:00
|
|
|
NET_EPOCH_ENTER(et);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
rv = tcp_output_locked(tp);
|
2021-12-26 11:48:19 -05:00
|
|
|
NET_EPOCH_EXIT(et);
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 11:37:58 -04:00
|
|
|
CURVNET_RESTORE();
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
return (rv);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-21 16:38:18 -05:00
|
|
|
static void
|
|
|
|
|
tcp_bblog_timer(struct tcpcb *tp, tt_which which, tt_what what, uint32_t ticks)
|
|
|
|
|
{
|
|
|
|
|
struct tcp_log_buffer *lgb;
|
|
|
|
|
uint64_t ms;
|
|
|
|
|
|
|
|
|
|
INP_WLOCK_ASSERT(tptoinpcb(tp));
|
2023-03-16 11:43:16 -04:00
|
|
|
if (tcp_bblogging_on(tp))
|
|
|
|
|
lgb = tcp_log_event(tp, NULL, NULL, NULL, TCP_LOG_RTO, 0, 0,
|
2023-02-21 16:38:18 -05:00
|
|
|
NULL, false, NULL, NULL, 0, NULL);
|
|
|
|
|
else
|
|
|
|
|
lgb = NULL;
|
|
|
|
|
if (lgb != NULL) {
|
|
|
|
|
lgb->tlb_flex1 = (what << 8) | which;
|
|
|
|
|
if (what == TT_STARTING) {
|
|
|
|
|
/* Convert ticks to ms and store it in tlb_flex2. */
|
|
|
|
|
if (hz == 1000)
|
|
|
|
|
lgb->tlb_flex2 = ticks;
|
|
|
|
|
else {
|
|
|
|
|
ms = (((uint64_t)ticks * 1000) + (hz - 1)) / hz;
|
|
|
|
|
if (ms > UINT32_MAX)
|
|
|
|
|
lgb->tlb_flex2 = UINT32_MAX;
|
|
|
|
|
else
|
|
|
|
|
lgb->tlb_flex2 = (uint32_t)ms;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
static inline tt_which
|
|
|
|
|
tcp_timer_next(struct tcpcb *tp, sbintime_t *precision)
|
|
|
|
|
{
|
|
|
|
|
tt_which i, rv;
|
|
|
|
|
sbintime_t after, before;
|
|
|
|
|
|
|
|
|
|
for (i = 0, rv = TT_N, after = before = SBT_MAX; i < TT_N; i++) {
|
|
|
|
|
if (tp->t_timers[i] < after) {
|
|
|
|
|
after = tp->t_timers[i];
|
|
|
|
|
rv = i;
|
|
|
|
|
}
|
|
|
|
|
before = MIN(before, tp->t_timers[i] + tp->t_precisions[i]);
|
|
|
|
|
}
|
|
|
|
|
if (precision != NULL)
|
|
|
|
|
*precision = before - after;
|
|
|
|
|
|
|
|
|
|
return (rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
tcp_timer_enter(void *xtp)
|
|
|
|
|
{
|
|
|
|
|
struct tcpcb *tp = xtp;
|
|
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
|
|
|
|
sbintime_t precision;
|
|
|
|
|
tt_which which;
|
2023-02-21 16:38:18 -05:00
|
|
|
bool tp_valid;
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
|
|
|
|
|
INP_WLOCK_ASSERT(inp);
|
|
|
|
|
MPASS((curthread->td_pflags & TDP_INTCPCALLOUT) == 0);
|
|
|
|
|
|
|
|
|
|
curthread->td_pflags |= TDP_INTCPCALLOUT;
|
|
|
|
|
|
|
|
|
|
which = tcp_timer_next(tp, NULL);
|
|
|
|
|
MPASS(which < TT_N);
|
|
|
|
|
tp->t_timers[which] = SBT_MAX;
|
|
|
|
|
tp->t_precisions[which] = 0;
|
|
|
|
|
|
2023-02-21 16:38:18 -05:00
|
|
|
tcp_bblog_timer(tp, which, TT_PROCESSING, 0);
|
|
|
|
|
tp_valid = tcp_timersw[which](tp);
|
|
|
|
|
if (tp_valid) {
|
|
|
|
|
tcp_bblog_timer(tp, which, TT_PROCESSED, 0);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if ((which = tcp_timer_next(tp, &precision)) != TT_N) {
|
|
|
|
|
callout_reset_sbt_on(&tp->t_callout,
|
|
|
|
|
tp->t_timers[which], precision, tcp_timer_enter,
|
|
|
|
|
tp, inp_to_cpuid(inp), C_ABSOLUTE);
|
|
|
|
|
}
|
|
|
|
|
INP_WUNLOCK(inp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curthread->td_pflags &= ~TDP_INTCPCALLOUT;
|
2007-09-07 05:19:22 -04:00
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
/*
|
|
|
|
|
* Activate or stop (delta == 0) a TCP timer.
|
|
|
|
|
*/
|
2007-09-07 05:19:22 -04:00
|
|
|
void
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tcp_timer_activate(struct tcpcb *tp, tt_which which, u_int delta)
|
2007-09-07 05:19:22 -04:00
|
|
|
{
|
2022-11-08 13:24:40 -05:00
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
sbintime_t precision;
|
2023-02-21 16:38:18 -05:00
|
|
|
tt_what what;
|
2007-09-07 05:19:22 -04:00
|
|
|
|
2012-06-19 03:34:13 -04:00
|
|
|
#ifdef TCP_OFFLOAD
|
|
|
|
|
if (tp->t_flags & TF_TOE)
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
2015-04-16 06:00:06 -04:00
|
|
|
|
2023-02-21 16:38:18 -05:00
|
|
|
if (delta > 0) {
|
|
|
|
|
what = TT_STARTING;
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
callout_when(tick_sbt * delta, 0, C_HARDCLOCK,
|
|
|
|
|
&tp->t_timers[which], &tp->t_precisions[which]);
|
2023-02-21 16:38:18 -05:00
|
|
|
} else {
|
|
|
|
|
what = TT_STOPPING;
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tp->t_timers[which] = SBT_MAX;
|
2023-02-21 16:38:18 -05:00
|
|
|
}
|
|
|
|
|
tcp_bblog_timer(tp, which, what, delta);
|
2007-09-07 05:19:22 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
if ((which = tcp_timer_next(tp, &precision)) != TT_N)
|
|
|
|
|
callout_reset_sbt_on(&tp->t_callout, tp->t_timers[which],
|
|
|
|
|
precision, tcp_timer_enter, tp, inp_to_cpuid(inp),
|
|
|
|
|
C_ABSOLUTE);
|
|
|
|
|
else
|
|
|
|
|
callout_stop(&tp->t_callout);
|
1994-05-24 06:09:53 -04:00
|
|
|
}
|
2009-09-16 01:33:15 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
bool
|
|
|
|
|
tcp_timer_active(struct tcpcb *tp, tt_which which)
|
2021-11-18 23:26:09 -05:00
|
|
|
{
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(tptoinpcb(tp));
|
2022-11-08 13:24:40 -05:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
return (tp->t_timers[which] != SBT_MAX);
|
2021-11-18 23:26:09 -05:00
|
|
|
}
|
|
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
/*
|
|
|
|
|
* Stop all timers associated with tcpcb.
|
|
|
|
|
*
|
|
|
|
|
* Called only on tcpcb destruction. The tcpcb shall already be dropped from
|
|
|
|
|
* the pcb lookup database and socket is not losing the last reference.
|
|
|
|
|
*
|
|
|
|
|
* XXXGL: unfortunately our callout(9) is not able to fully stop a locked
|
|
|
|
|
* callout even when only two threads are involved: the callout itself and the
|
|
|
|
|
* thread that does callout_stop(). See where softclock_call_cc() swaps the
|
|
|
|
|
* callwheel lock to callout lock and then checks cc_exec_cancel(). This is
|
|
|
|
|
* the race window. If it happens, the tcp_timer_enter() won't be executed,
|
|
|
|
|
* however pcb lock will be locked and released, hence we can't free memory.
|
|
|
|
|
* Until callout(9) is improved, just keep retrying. In my profiling I've seen
|
|
|
|
|
* such event happening less than 1 time per hour with 20-30 Gbit/s of traffic.
|
|
|
|
|
*/
|
2015-04-16 06:00:06 -04:00
|
|
|
void
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
tcp_timer_stop(struct tcpcb *tp)
|
2015-04-16 06:00:06 -04:00
|
|
|
{
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
struct inpcb *inp = tptoinpcb(tp);
|
2015-04-16 06:00:06 -04:00
|
|
|
|
tcp: use single locked callout per tcpcb for the TCP timers
Use only one callout structure per tcpcb that is responsible for handling
all five TCP timeouts. Use locked version of callout, of course. The
callout function tcp_timer_enter() chooses soonest timer and executes it
with lock held. Unless the timer reports that the tcpcb has been freed,
the callout is rescheduled for next soonest timer, if there is any.
With single callout per tcpcb on connection teardown we should be able
to fully stop the callout and immediately free it, avoiding use of
callout_async_drain(). There is one gotcha here: callout_stop() can
actually touch our memory when a rare race condition happens. See
comment above tcp_timer_stop(). Synchronous stop of the callout makes
tcp_discardcb() the single entry point for tcpcb destructor, merging the
tcp_freecb() to the end of the function.
While here, also remove lots of lingering checks in the beginning of
TCP timer functions. With a locked callout they are unnecessary.
While here, clean unused parts of timer KPI for the pluggable TCP stacks.
While here, remove TCPDEBUG from tcp_timer.c, as this allows for more
simplification of TCP timers. The TCPDEBUG is scheduled for removal.
Move the DTrace probes in timers to the beginning of a function, where
a tcpcb is always existing.
Discussed with: rrs, tuexen, rscheff (the TCP part of the diff)
Reviewed by: hselasky, kib, mav (the callout part)
Differential revision: https://reviews.freebsd.org/D37321
2022-12-07 12:00:48 -05:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
|
|
|
|
|
|
|
|
|
if (curthread->td_pflags & TDP_INTCPCALLOUT) {
|
|
|
|
|
int stopped __diagused;
|
|
|
|
|
|
|
|
|
|
stopped = callout_stop(&tp->t_callout);
|
|
|
|
|
MPASS(stopped == 0);
|
|
|
|
|
} else while(__predict_false(callout_stop(&tp->t_callout) == 0)) {
|
|
|
|
|
INP_WUNLOCK(inp);
|
|
|
|
|
kern_yield(PRI_UNCHANGED);
|
|
|
|
|
INP_WLOCK(inp);
|
2015-04-16 06:00:06 -04:00
|
|
|
}
|
|
|
|
|
}
|