aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/outqueue.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2010-04-30 22:41:10 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2010-04-30 22:41:10 -0400
commitea862c8d1f4a0d193979c7412c3b946f600721ce (patch)
tree929dd96e2562258a96739373c758ab6dcbc2bb1b /net/sctp/outqueue.c
parent65883371894be2631603d5d412f90f8c09290fef (diff)
sctp: correctly mark missing chunks in fast recovery
According to RFC 4960 Section 7.2.4: If an endpoint is in Fast Recovery and a SACK arrives that advances the Cumulative TSN Ack Point, the miss indications are incremented for all TSNs reported missing in the SACK. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r--net/sctp/outqueue.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 786c4ff97ae4..b491a1aac3e4 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1154,6 +1154,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1154 struct sctp_transport *primary = asoc->peer.primary_path; 1154 struct sctp_transport *primary = asoc->peer.primary_path;
1155 int count_of_newacks = 0; 1155 int count_of_newacks = 0;
1156 int gap_ack_blocks; 1156 int gap_ack_blocks;
1157 u8 accum_moved = 0;
1157 1158
1158 /* Grab the association's destination address list. */ 1159 /* Grab the association's destination address list. */
1159 transport_list = &asoc->peer.transport_addr_list; 1160 transport_list = &asoc->peer.transport_addr_list;
@@ -1232,16 +1233,22 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1232 count_of_newacks ++; 1233 count_of_newacks ++;
1233 } 1234 }
1234 1235
1236 /* Move the Cumulative TSN Ack Point if appropriate. */
1237 if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) {
1238 asoc->ctsn_ack_point = sack_ctsn;
1239 accum_moved = 1;
1240 }
1241
1235 if (gap_ack_blocks) { 1242 if (gap_ack_blocks) {
1243
1244 if (asoc->fast_recovery && accum_moved)
1245 highest_new_tsn = highest_tsn;
1246
1236 list_for_each_entry(transport, transport_list, transports) 1247 list_for_each_entry(transport, transport_list, transports)
1237 sctp_mark_missing(q, &transport->transmitted, transport, 1248 sctp_mark_missing(q, &transport->transmitted, transport,
1238 highest_new_tsn, count_of_newacks); 1249 highest_new_tsn, count_of_newacks);
1239 } 1250 }
1240 1251
1241 /* Move the Cumulative TSN Ack Point if appropriate. */
1242 if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn))
1243 asoc->ctsn_ack_point = sack_ctsn;
1244
1245 /* Update unack_data field in the assoc. */ 1252 /* Update unack_data field in the assoc. */
1246 sctp_sack_update_unack_data(asoc, sack); 1253 sctp_sack_update_unack_data(asoc, sack);
1247 1254
@@ -1685,7 +1692,8 @@ static void sctp_mark_missing(struct sctp_outq *q,
1685 struct sctp_chunk *chunk; 1692 struct sctp_chunk *chunk;
1686 __u32 tsn; 1693 __u32 tsn;
1687 char do_fast_retransmit = 0; 1694 char do_fast_retransmit = 0;
1688 struct sctp_transport *primary = q->asoc->peer.primary_path; 1695 struct sctp_association *asoc = q->asoc;
1696 struct sctp_transport *primary = asoc->peer.primary_path;
1689 1697
1690 list_for_each_entry(chunk, transmitted_queue, transmitted_list) { 1698 list_for_each_entry(chunk, transmitted_queue, transmitted_list) {
1691 1699