[SCTP]: Fix 'fast retransmit' to send a TSN only once.
authorVlad Yasevich <vladislav.yasevich@hp.com>
Fri, 3 Feb 2006 00:57:31 +0000 (16:57 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 3 Feb 2006 00:57:31 +0000 (16:57 -0800)
SCTP used to "fast retransmit" a TSN every time we hit the number
of missing reports for the TSN.  However the Implementers Guide
specifies that we should only "fast retransmit" a given TSN once.
Subsequent retransmits should be timeouts only. Also change the
number of missing reports to 3 as per the latest IG(similar to TCP).

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sctp/structs.h
net/sctp/output.c
net/sctp/outqueue.c

index 8c522ae..072f407 100644 (file)
@@ -700,7 +700,7 @@ struct sctp_chunk {
        __u8 ecn_ce_done;       /* Have we processed the ECN CE bit? */
        __u8 pdiscard;          /* Discard the whole packet now? */
        __u8 tsn_gap_acked;     /* Is this chunk acked by a GAP ACK? */
-       __u8 fast_retransmit;    /* Is this chunk fast retransmitted? */
+       __s8 fast_retransmit;    /* Is this chunk fast retransmitted? */
        __u8 tsn_missing_report; /* Data chunk missing counter. */
 };
 
index a40991e..437cba7 100644 (file)
@@ -608,7 +608,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
         *    When a Fast Retransmit is being performed the sender SHOULD
         *    ignore the value of cwnd and SHOULD NOT delay retransmission.
         */
-       if (!chunk->fast_retransmit)
+       if (chunk->fast_retransmit <= 0)
                if (transport->flight_size >= transport->cwnd) {
                        retval = SCTP_XMIT_RWND_FULL;
                        goto finish;
index efb72fa..f148f95 100644 (file)
@@ -406,7 +406,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                 * chunks that are not yet acked should be added to the
                 * retransmit queue.
                 */
-               if ((fast_retransmit && chunk->fast_retransmit) ||
+               if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
                   (!fast_retransmit && !chunk->tsn_gap_acked)) {
                        /* RFC 2960 6.2.1 Processing a Received SACK
                         *
@@ -603,7 +603,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
                        /* Mark the chunk as ineligible for fast retransmit 
                         * after it is retransmitted.
                         */
-                       chunk->fast_retransmit = 0;
+                       if (chunk->fast_retransmit > 0)
+                               chunk->fast_retransmit = -1;
 
                        *start_timer = 1;
                        q->empty = 0;
@@ -621,7 +622,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
                        list_for_each(lchunk1, lqueue) {
                                chunk1 = list_entry(lchunk1, struct sctp_chunk,
                                                    transmitted_list);
-                               chunk1->fast_retransmit = 0;
+                               if (chunk1->fast_retransmit > 0)
+                                       chunk1->fast_retransmit = -1;
                        }
                }
        }
@@ -1562,11 +1564,11 @@ static void sctp_mark_missing(struct sctp_outq *q,
                /*
                 * M4) If any DATA chunk is found to have a
                 * 'TSN.Missing.Report'
-                * value larger than or equal to 4, mark that chunk for
+                * value larger than or equal to 3, mark that chunk for
                 * retransmission and start the fast retransmit procedure.
                 */
 
-               if (chunk->tsn_missing_report >= 4) {
+               if (chunk->tsn_missing_report >= 3) {
                        chunk->fast_retransmit = 1;
                        do_fast_retransmit = 1;
                }