summaryrefslogtreecommitdiff
path: root/sys
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 /sys
parentb50ff2261bea0c0418f8b2b31cf82158e957a130 (diff)
Notes
Diffstat (limited to 'sys')
-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;
}