git: 2ff07d9220a0 - main - tcp: Restore correct ECT marking behavior on SACK retransmissions

From: Richard Scheffenegger <rscheff_at_FreeBSD.org>
Date: Fri, 25 Feb 2022 19:07:47 UTC
The branch main has been updated by rscheff:

URL: https://cgit.FreeBSD.org/src/commit/?id=2ff07d9220a0af1ffe31849bfd66139557a9aa27

commit 2ff07d9220a0af1ffe31849bfd66139557a9aa27
Author:     Richard Scheffenegger <rscheff@FreeBSD.org>
AuthorDate: 2022-02-25 19:05:15 +0000
Commit:     Richard Scheffenegger <rscheff@FreeBSD.org>
CommitDate: 2022-02-25 19:05:32 +0000

    tcp: Restore correct ECT marking behavior on SACK retransmissions
    
    While coalescing all ECN-related code into new common source files,
    the flag to deal with SACK retransmissions was skipped. This leads
    to non-compliant ECT-marking of SACK retransmissions, as well as
    the premature sending of other TCP ECN flags (CWR).
    
    Reviewed By: rrs, #transport
    Sponsored by:        NetApp, Inc.
    Differential Revision: https://reviews.freebsd.org/D34376
---
 sys/netinet/tcp_ecn.c         | 3 ++-
 sys/netinet/tcp_ecn.h         | 2 +-
 sys/netinet/tcp_output.c      | 2 +-
 sys/netinet/tcp_stacks/rack.c | 6 +++---
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/sys/netinet/tcp_ecn.c b/sys/netinet/tcp_ecn.c
index 17b3c90a46fb..20f84a0c9d98 100644
--- a/sys/netinet/tcp_ecn.c
+++ b/sys/netinet/tcp_ecn.c
@@ -201,7 +201,7 @@ tcp_ecn_output_syn_sent(struct tcpcb *tp)
  * returning IP ECN header codepoint
  */
 int
-tcp_ecn_output_established(struct tcpcb *tp, uint16_t *thflags, int len)
+tcp_ecn_output_established(struct tcpcb *tp, uint16_t *thflags, int len, bool rxmit)
 {
 	int ipecn = IPTOS_ECN_NOTECT;
 	bool newdata;
@@ -213,6 +213,7 @@ tcp_ecn_output_established(struct tcpcb *tp, uint16_t *thflags, int len)
 	 * and window probes.
 	 */
 	newdata = (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) &&
+		    !rxmit &&
 		    !((tp->t_flags & TF_FORCEDATA) && len == 1));
 	if (newdata) {
 		ipecn = IPTOS_ECN_ECT0;
diff --git a/sys/netinet/tcp_ecn.h b/sys/netinet/tcp_ecn.h
index b8a52bac83b2..38ac2f398e54 100644
--- a/sys/netinet/tcp_ecn.h
+++ b/sys/netinet/tcp_ecn.h
@@ -45,7 +45,7 @@ void	 tcp_ecn_input_syn_sent(struct tcpcb *, uint16_t, int);
 void	 tcp_ecn_input_parallel_syn(struct tcpcb *, uint16_t, int);
 int	 tcp_ecn_input_segment(struct tcpcb *, uint16_t, int);
 uint16_t tcp_ecn_output_syn_sent(struct tcpcb *);
-int	 tcp_ecn_output_established(struct tcpcb *, uint16_t *, int);
+int	 tcp_ecn_output_established(struct tcpcb *, uint16_t *, int, bool);
 void	 tcp_ecn_syncache_socket(struct tcpcb *, struct syncache *);
 int	 tcp_ecn_syncache_add(uint16_t, int);
 uint16_t tcp_ecn_syncache_respond(uint16_t, struct syncache *);
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 0817997c72d3..83ce5b061f09 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1206,7 +1206,7 @@ send:
 	/* Also handle parallel SYN for ECN */
 	if ((TCPS_HAVERCVDSYN(tp->t_state)) &&
 	    (tp->t_flags2 & TF2_ECN_PERMIT)) {
-		int ect = tcp_ecn_output_established(tp, &flags, len);
+		int ect = tcp_ecn_output_established(tp, &flags, len, sack_rxmit);
 		if ((tp->t_state == TCPS_SYN_RECEIVED) &&
 		    (tp->t_flags2 & TF2_ECN_SND_ECE))
 			tp->t_flags2 &= ~TF2_ECN_SND_ECE;
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 7bab75a637fa..f8734c08bbbd 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -15742,7 +15742,7 @@ rack_fast_rsm_output(struct tcpcb *tp, struct tcp_rack *rack, struct rack_sendma
 	m->m_pkthdr.rcvif = (struct ifnet *)0;
 	if (TCPS_HAVERCVDSYN(tp->t_state) &&
 	    (tp->t_flags2 & TF2_ECN_PERMIT)) {
-		int ect = tcp_ecn_output_established(tp, &flags, len);
+		int ect = tcp_ecn_output_established(tp, &flags, len, true);
 		if ((tp->t_state == TCPS_SYN_RECEIVED) &&
 		    (tp->t_flags2 & TF2_ECN_SND_ECE))
 		    tp->t_flags2 &= ~TF2_ECN_SND_ECE;
@@ -16233,7 +16233,7 @@ again:
 	m->m_pkthdr.rcvif = (struct ifnet *)0;
 	if (TCPS_HAVERCVDSYN(tp->t_state) &&
 	    (tp->t_flags2 & TF2_ECN_PERMIT)) {
-		int ect = tcp_ecn_output_established(tp, &flags, len);
+		int ect = tcp_ecn_output_established(tp, &flags, len, false);
 		if ((tp->t_state == TCPS_SYN_RECEIVED) &&
 		    (tp->t_flags2 & TF2_ECN_SND_ECE))
 			tp->t_flags2 &= ~TF2_ECN_SND_ECE;
@@ -18278,7 +18278,7 @@ send:
 	/* Also handle parallel SYN for ECN */
 	if (TCPS_HAVERCVDSYN(tp->t_state) &&
 	    (tp->t_flags2 & TF2_ECN_PERMIT)) {
-		int ect = tcp_ecn_output_established(tp, &flags, len);
+		int ect = tcp_ecn_output_established(tp, &flags, len, sack_rxmit);
 		if ((tp->t_state == TCPS_SYN_RECEIVED) &&
 		    (tp->t_flags2 & TF2_ECN_SND_ECE))
 			tp->t_flags2 &= ~TF2_ECN_SND_ECE;