sctp: fix identification of new acks for SFR-CACC
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Tue, 24 Apr 2018 21:17:35 +0000 (18:17 -0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Apr 2018 17:22:07 +0000 (13:22 -0400)
It's currently written as:

if (!tchunk->tsn_gap_acked) {   [1]
tchunk->tsn_gap_acked = 1;
...
}

if (TSN_lte(tsn, sack_ctsn)) {
if (!tchunk->tsn_gap_acked) {
/* SFR-CACC processing */
...
}
}

Which causes the SFR-CACC processing on ack reception to never process,
as tchunk->tsn_gap_acked is always true by then. Block [1] was
moved to that position by the commit marked below.

This patch fixes it by doing SFR-CACC processing earlier, before
tsn_gap_acked is set to true.

Fixes: 31b02e154940 ("sctp: Failover transmitted list on transport delete")
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/outqueue.c

index f211b3db6a3543073e113da121bb28518b0af491..dee7cbd5483149024f2f3195db2fe4d473b1a00a 100644 (file)
@@ -1457,7 +1457,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                         * the outstanding bytes for this chunk, so only
                         * count bytes associated with a transport.
                         */
-                       if (transport) {
+                       if (transport && !tchunk->tsn_gap_acked) {
                                /* If this chunk is being used for RTT
                                 * measurement, calculate the RTT and update
                                 * the RTO using this value.
@@ -1469,14 +1469,34 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                 * first instance of the packet or a later
                                 * instance).
                                 */
-                               if (!tchunk->tsn_gap_acked &&
-                                   !sctp_chunk_retransmitted(tchunk) &&
+                               if (!sctp_chunk_retransmitted(tchunk) &&
                                    tchunk->rtt_in_progress) {
                                        tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
                                        sctp_transport_update_rto(transport,
                                                                  rtt);
                                }
+
+                               if (TSN_lte(tsn, sack_ctsn)) {
+                                       /*
+                                        * SFR-CACC algorithm:
+                                        * 2) If the SACK contains gap acks
+                                        * and the flag CHANGEOVER_ACTIVE is
+                                        * set the receiver of the SACK MUST
+                                        * take the following action:
+                                        *
+                                        * B) For each TSN t being acked that
+                                        * has not been acked in any SACK so
+                                        * far, set cacc_saw_newack to 1 for
+                                        * the destination that the TSN was
+                                        * sent to.
+                                        */
+                                       if (sack->num_gap_ack_blocks &&
+                                           q->asoc->peer.primary_path->cacc.
+                                           changeover_active)
+                                               transport->cacc.cacc_saw_newack
+                                                       = 1;
+                               }
                        }
 
                        /* If the chunk hasn't been marked as ACKED,
@@ -1508,28 +1528,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                restart_timer = 1;
                                forward_progress = true;
 
-                               if (!tchunk->tsn_gap_acked) {
-                                       /*
-                                        * SFR-CACC algorithm:
-                                        * 2) If the SACK contains gap acks
-                                        * and the flag CHANGEOVER_ACTIVE is
-                                        * set the receiver of the SACK MUST
-                                        * take the following action:
-                                        *
-                                        * B) For each TSN t being acked that
-                                        * has not been acked in any SACK so
-                                        * far, set cacc_saw_newack to 1 for
-                                        * the destination that the TSN was
-                                        * sent to.
-                                        */
-                                       if (transport &&
-                                           sack->num_gap_ack_blocks &&
-                                           q->asoc->peer.primary_path->cacc.
-                                           changeover_active)
-                                               transport->cacc.cacc_saw_newack
-                                                       = 1;
-                               }
-
                                list_add_tail(&tchunk->transmitted_list,
                                              &q->sacked);
                        } else {