| From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> |
| Date: Tue, 24 Apr 2018 18:17:35 -0300 |
| Subject: sctp: fix identification of new acks for SFR-CACC |
| |
| commit 51446780fc33e45cb790c05a7fa2c5bf7e8bc53b upstream. |
| |
| 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> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| net/sctp/outqueue.c | 48 ++++++++++++++++++++++----------------------- |
| 1 file changed, 23 insertions(+), 25 deletions(-) |
| |
| --- a/net/sctp/outqueue.c |
| +++ b/net/sctp/outqueue.c |
| @@ -1346,7 +1346,7 @@ static void sctp_check_transmitted(struc |
| * 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. |
| @@ -1358,14 +1358,34 @@ static void sctp_check_transmitted(struc |
| * first instance of the packet or a later |
| * instance). |
| */ |
| - if (!tchunk->tsn_gap_acked && |
| - !tchunk->resent && |
| + if (!tchunk->resent && |
| 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, |
| @@ -1397,28 +1417,6 @@ static void sctp_check_transmitted(struc |
| 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 { |