Merge branch 'fixes-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
[sfrench/cifs-2.6.git] / net / sctp / outqueue.c
index 992f361084b741115f3e14006bb00bb0772a4fcf..fa76f235169bfac3cedcb8517d4c62b0cd8daa5c 100644 (file)
@@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new)
 /* Mark all the eligible packets on a transport for retransmission.  */
 void sctp_retransmit_mark(struct sctp_outq *q,
                          struct sctp_transport *transport,
-                         __u8 fast_retransmit)
+                         __u8 reason)
 {
        struct list_head *lchunk, *ltemp;
        struct sctp_chunk *chunk;
@@ -412,15 +412,22 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                        continue;
                }
 
-               /* If we are doing retransmission due to a fast retransmit,
-                * only the chunk's that are marked for fast retransmit
-                * should be added to the retransmit queue.  If we are doing
-                * retransmission due to a timeout or pmtu discovery, only the
-                * chunks that are not yet acked should be added to the
-                * retransmit queue.
+               /* If we are doing  retransmission due to a timeout or pmtu
+                * discovery, only the  chunks that are not yet acked should
+                * be added to the retransmit queue.
                 */
-               if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
-                  (!fast_retransmit && !chunk->tsn_gap_acked)) {
+               if ((reason == SCTP_RTXR_FAST_RTX  &&
+                           (chunk->fast_retransmit > 0)) ||
+                   (reason != SCTP_RTXR_FAST_RTX  && !chunk->tsn_gap_acked)) {
+                       /* If this chunk was sent less then 1 rto ago, do not
+                        * retransmit this chunk, but give the peer time
+                        * to acknowlege it.  Do this only when
+                        * retransmitting due to T3 timeout.
+                        */
+                       if (reason == SCTP_RTXR_T3_RTX &&
+                           (jiffies - chunk->sent_at) < transport->last_rto)
+                               continue;
+
                        /* RFC 2960 6.2.1 Processing a Received SACK
                         *
                         * C) Any time a DATA chunk is marked for
@@ -460,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                }
        }
 
-       SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, "
+       SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
                          "cwnd: %d, ssthresh: %d, flight_size: %d, "
                          "pba: %d\n", __FUNCTION__,
-                         transport, fast_retransmit,
+                         transport, reason,
                          transport->cwnd, transport->ssthresh,
                          transport->flight_size,
                          transport->partial_bytes_acked);
@@ -477,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
                     sctp_retransmit_reason_t reason)
 {
        int error = 0;
-       __u8 fast_retransmit = 0;
 
        switch(reason) {
        case SCTP_RTXR_T3_RTX:
@@ -492,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
        case SCTP_RTXR_FAST_RTX:
                SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
                sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
-               fast_retransmit = 1;
                break;
        case SCTP_RTXR_PMTUD:
                SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
                break;
+       case SCTP_RTXR_T1_RTX:
+               SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
+               break;
        default:
                BUG();
        }
 
-       sctp_retransmit_mark(q, transport, fast_retransmit);
+       sctp_retransmit_mark(q, transport, reason);
 
        /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination,
         * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by
@@ -634,7 +642,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
 
                /* If we are here due to a retransmit timeout or a fast
                 * retransmit and if there are any chunks left in the retransmit
-                * queue that could not fit in the PMTU sized packet, they need                  * to be marked as ineligible for a subsequent fast retransmit.
+                * queue that could not fit in the PMTU sized packet, they need
+                * to be marked as ineligible for a subsequent fast retransmit.
                 */
                if (rtx_timeout && !lchunk) {
                        list_for_each(lchunk1, lqueue) {
@@ -653,10 +662,9 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
 int sctp_outq_uncork(struct sctp_outq *q)
 {
        int error = 0;
-       if (q->cork) {
+       if (q->cork)
                q->cork = 0;
-               error = sctp_outq_flush(q, 0);
-       }
+       error = sctp_outq_flush(q, 0);
        return error;
 }