aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Scheffenegger <rscheff@FreeBSD.org>2020-05-27 22:34:46 +0000
committerRichard Scheffenegger <rscheff@FreeBSD.org>2020-05-27 22:34:46 +0000
commit0788d8fe94f0f2cffe3f312288dc1596d6277387 (patch)
tree41bb2284fb313acfe6ce33fb898b1367015fd441
parentb50ff2261bea0c0418f8b2b31cf82158e957a130 (diff)
downloadsrc-0788d8fe94f0f2cffe3f312288dc1596d6277387.tar.gz
src-0788d8fe94f0f2cffe3f312288dc1596d6277387.zip
MFS r361436: MFC r361347: With RFC3168 ECN, CWR SHOULD only be sent with new data.
Overly conservative data receivers may ignore the CWR flag on other packets, and keep ECE latched. This can result in continuous reduction of the congestion window, and very poor performance when ECN is enabled. This does NOT contain the merge of the change to RACK since at this time that code does not exist in stable/11, and there is no plan to merge RACK to stable/11. PR: 243590 Reviewed by: rgrimes (mentor), rrs Approved by: re(gjb) Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D23364
Notes
Notes: svn path=/releng/11.4/; revision=361565
-rw-r--r--sys/netinet/tcp_input.c10
-rw-r--r--sys/netinet/tcp_output.c19
2 files changed, 18 insertions, 11 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index d6814986137c..4d48cdd7a685 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -417,9 +417,15 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
}
break;
case CC_ECN:
- if (!IN_CONGRECOVERY(tp->t_flags)) {
+ if (!IN_CONGRECOVERY(tp->t_flags) ||
+ /*
+ * Allow ECN reaction on ACK to CWR, if
+ * that data segment was also CE marked.
+ */
+ SEQ_GEQ(th->th_ack, tp->snd_recover)) {
+ EXIT_CONGRECOVERY(tp->t_flags);
TCPSTAT_INC(tcps_ecn_rcwnd);
- tp->snd_recover = tp->snd_max;
+ tp->snd_recover = tp->snd_max + 1;
if (tp->t_flags & TF_ECN_PERMIT)
tp->t_flags |= TF_ECN_SND_CWR;
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 1c62ac3151c7..d7fcd626d9cd 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1161,7 +1161,8 @@ send:
* Ignore pure ack packets, retransmissions and window probes.
*/
if (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) &&
- !((tp->t_flags & TF_FORCEDATA) && len == 1)) {
+ !((tp->t_flags & TF_FORCEDATA) && len == 1 &&
+ SEQ_LT(tp->snd_una, tp->snd_max))) {
#ifdef INET6
if (isipv6)
ip6->ip6_flow |= htonl(IPTOS_ECN_ECT0 << 20);
@@ -1169,15 +1170,15 @@ send:
#endif
ip->ip_tos |= IPTOS_ECN_ECT0;
TCPSTAT_INC(tcps_ecn_ect0);
+ /*
+ * Reply with proper ECN notifications.
+ * Only set CWR on new data segments.
+ */
+ if (tp->t_flags & TF_ECN_SND_CWR) {
+ flags |= TH_CWR;
+ tp->t_flags &= ~TF_ECN_SND_CWR;
+ }
}
-
- /*
- * Reply with proper ECN notifications.
- */
- if (tp->t_flags & TF_ECN_SND_CWR) {
- flags |= TH_CWR;
- tp->t_flags &= ~TF_ECN_SND_CWR;
- }
if (tp->t_flags & TF_ECN_SND_ECE)
flags |= TH_ECE;
}