Author: rscheff Date: Thu May 21 21:33:15 2020 New Revision: 361347 URL: https://svnweb.freebsd.org/changeset/base/361347
Log: 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 continous reduction of the congestion window, and very poor performance when ECN is enabled. Reviewed by: rgrimes (mentor), rrs Approved by: rgrimes (mentor), tuexen (mentor) MFC after: 3 days Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D23364 Modified: head/sys/netinet/tcp_input.c head/sys/netinet/tcp_output.c head/sys/netinet/tcp_stacks/rack.c Modified: head/sys/netinet/tcp_input.c ============================================================================== --- head/sys/netinet/tcp_input.c Thu May 21 21:26:21 2020 (r361346) +++ head/sys/netinet/tcp_input.c Thu May 21 21:33:15 2020 (r361347) @@ -447,9 +447,15 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, ui } 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_flags2 & TF2_ECN_PERMIT) tp->t_flags2 |= TF2_ECN_SND_CWR; } Modified: head/sys/netinet/tcp_output.c ============================================================================== --- head/sys/netinet/tcp_output.c Thu May 21 21:26:21 2020 (r361346) +++ head/sys/netinet/tcp_output.c Thu May 21 21:33:15 2020 (r361347) @@ -1170,7 +1170,8 @@ send: */ if (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) && (sack_rxmit == 0) && - !((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); @@ -1178,14 +1179,14 @@ send: #endif ip->ip_tos |= IPTOS_ECN_ECT0; TCPSTAT_INC(tcps_ecn_ect0); - } - - /* - * Reply with proper ECN notifications. - */ - if (tp->t_flags2 & TF2_ECN_SND_CWR) { - flags |= TH_CWR; - tp->t_flags2 &= ~TF2_ECN_SND_CWR; + /* + * Reply with proper ECN notifications. + * Only set CWR on new data segments. + */ + if (tp->t_flags2 & TF2_ECN_SND_CWR) { + flags |= TH_CWR; + tp->t_flags2 &= ~TF2_ECN_SND_CWR; + } } if (tp->t_flags2 & TF2_ECN_SND_ECE) flags |= TH_ECE; Modified: head/sys/netinet/tcp_stacks/rack.c ============================================================================== --- head/sys/netinet/tcp_stacks/rack.c Thu May 21 21:26:21 2020 (r361346) +++ head/sys/netinet/tcp_stacks/rack.c Thu May 21 21:33:15 2020 (r361347) @@ -4095,9 +4095,15 @@ rack_cong_signal(struct tcpcb *tp, struct tcphdr *th, } 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); KMOD_TCPSTAT_INC(tcps_ecn_rcwnd); - tp->snd_recover = tp->snd_max; + tp->snd_recover = tp->snd_max + 1; if (tp->t_flags2 & TF2_ECN_PERMIT) tp->t_flags2 |= TF2_ECN_SND_CWR; } @@ -13556,13 +13562,14 @@ send: #endif ip->ip_tos |= IPTOS_ECN_ECT0; KMOD_TCPSTAT_INC(tcps_ecn_ect0); - } - /* - * Reply with proper ECN notifications. - */ - if (tp->t_flags2 & TF2_ECN_SND_CWR) { - flags |= TH_CWR; - tp->t_flags2 &= ~TF2_ECN_SND_CWR; + /* + * Reply with proper ECN notifications. + * Only set CWR on new data segments. + */ + if (tp->t_flags2 & TF2_ECN_SND_CWR) { + flags |= TH_CWR; + tp->t_flags2 &= ~TF2_ECN_SND_CWR; + } } if (tp->t_flags2 & TF2_ECN_SND_ECE) flags |= TH_ECE; _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"