summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_output.c
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-06-23 08:38:01 +0000
committersephe <sephe@FreeBSD.org>2016-06-23 08:38:01 +0000
commit282e77a422a97b67e7f2e912d83f5646fe2692ae (patch)
treea366d1ce003df14d08538944ec431daee7eb7ed3 /sys/netinet/tcp_output.c
parent847d6fbcde077b6521c4c9e9cb0fe11adc76fb0f (diff)
downloadFreeBSD-src-282e77a422a97b67e7f2e912d83f5646fe2692ae.zip
FreeBSD-src-282e77a422a97b67e7f2e912d83f5646fe2692ae.tar.gz
MFC 300981
tcp: Don't prematurely drop receiving-only connections If the connection was persistent and receiving-only, several (12) sporadic device insufficient buffers would cause the connection be dropped prematurely: Upon ENOBUFS in tcp_output() for an ACK, retransmission timer is started. No one will stop this retransmission timer for receiving- only connection, so the retransmission timer promises to expire and t_rxtshift is promised to be increased. And t_rxtshift will not be reset to 0, since no RTT measurement will be done for receiving-only connection. If this receiving-only connection lived long enough (e.g. >350sec, given the RTO starts from 200ms), and it suffered 12 sporadic device insufficient buffers, i.e. t_rxtshift >= 12, this receiving-only connection would be dropped prematurely by the retransmission timer. We now assert that for data segments, SYNs or FINs either rexmit or persist timer was wired upon ENOBUFS. And don't set rexmit timer for other cases, i.e. ENOBUFS upon ACKs. Discussed with: lstewart, hiren, jtl, Mike Karels MFC after: 3 weeks Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5872
Diffstat (limited to 'sys/netinet/tcp_output.c')
-rw-r--r--sys/netinet/tcp_output.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 57332be..b5781d3 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -127,6 +127,16 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
+/*
+ * Make sure that either retransmit or persist timer is set for SYN, FIN and
+ * non-ACK.
+ */
+#define TCP_XMIT_TIMER_ASSERT(tp, len, th_flags) \
+ KASSERT(((len) == 0 && ((th_flags) & (TH_SYN | TH_FIN)) == 0) ||\
+ tcp_timer_active((tp), TT_REXMT) || \
+ tcp_timer_active((tp), TT_PERSIST), \
+ ("neither rexmt nor persist timer is set"))
+
static void inline hhook_run_tcp_est_out(struct tcpcb *tp,
struct tcphdr *th, struct tcpopt *to,
long len, int tso);
@@ -1531,9 +1541,7 @@ timer:
tp->t_softerror = error;
return (error);
case ENOBUFS:
- if (!tcp_timer_active(tp, TT_REXMT) &&
- !tcp_timer_active(tp, TT_PERSIST))
- tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+ TCP_XMIT_TIMER_ASSERT(tp, len, flags);
tp->snd_cwnd = tp->t_maxseg;
return (0);
case EMSGSIZE:
OpenPOWER on IntegriCloud