]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
tcp: Restore correct ECT marking behavior on SACK retransmissions
authorRichard Scheffenegger <rscheff@FreeBSD.org>
Fri, 25 Feb 2022 19:05:15 +0000 (20:05 +0100)
committerRichard Scheffenegger <rscheff@FreeBSD.org>
Fri, 25 Feb 2022 19:05:32 +0000 (20:05 +0100)
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
sys/netinet/tcp_ecn.h
sys/netinet/tcp_output.c
sys/netinet/tcp_stacks/rack.c

index 17b3c90a46fbe7ad7da57910ae25a601b71711b4..20f84a0c9d98347e0db7a969bd37b85c4f914fee 100644 (file)
@@ -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;
index b8a52bac83b2ff00d2ae0c647460784ab71255d5..38ac2f398e548308ad12a1e710311c10ac397129 100644 (file)
@@ -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 *);
index 0817997c72d3bc80da00e6f5740835578e91588c..83ce5b061f09b4f7da391bf050ac85bb28e9046b 100644 (file)
@@ -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;
index 7bab75a637fac97e71491b792a57affb2cc63c87..f8734c08bbbddfe166b7922b5216f10607cfeb30 100644 (file)
@@ -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;