]> err.no Git - linux-2.6/blobdiff - net/sctp/outqueue.c
[NetLabel]: correct improper handling of non-NetLabel peer contexts
[linux-2.6] / net / sctp / outqueue.c
index efb72faba20cd50aec065d4fe498c85ecae8d4ae..37074a39ecbbfb68939c9cc6b0679e21eba71bb1 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
                         *
@@ -467,6 +467,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
 
        switch(reason) {
        case SCTP_RTXR_T3_RTX:
+               SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS);
                sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
                /* Update the retran path if the T3-rtx timer has expired for
                 * the current retran path.
@@ -475,12 +476,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
                        sctp_assoc_update_retran_path(transport->asoc);
                break;
        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:
-       default:
+               SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
                break;
+       default:
+               BUG();
        }
 
        sctp_retransmit_mark(q, transport, fast_retransmit);
@@ -603,7 +607,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 +626,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;
                        }
                }
        }
@@ -689,7 +695,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                if (!new_transport) {
                        new_transport = asoc->peer.active_path;
-               } else if (new_transport->state == SCTP_INACTIVE) {
+               } else if ((new_transport->state == SCTP_INACTIVE) ||
+                          (new_transport->state == SCTP_UNCONFIRMED)) {
                        /* If the chunk is Heartbeat or Heartbeat Ack,
                         * send it to chunk->transport, even if it's
                         * inactive.
@@ -846,7 +853,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                         */
                        new_transport = chunk->transport;
                        if (!new_transport ||
-                           new_transport->state == SCTP_INACTIVE)
+                           ((new_transport->state == SCTP_INACTIVE) ||
+                            (new_transport->state == SCTP_UNCONFIRMED)))
                                new_transport = asoc->peer.active_path;
 
                        /* Change packets if necessary.  */
@@ -1260,6 +1268,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                if (!tchunk->tsn_gap_acked &&
                                    !tchunk->resent &&
                                    tchunk->rtt_in_progress) {
+                                       tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
                                        sctp_transport_update_rto(transport,
                                                                  rtt);
@@ -1461,7 +1470,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                        /* Mark the destination transport address as
                         * active if it is not so marked.
                         */
-                       if (transport->state == SCTP_INACTIVE) {
+                       if ((transport->state == SCTP_INACTIVE) ||
+                           (transport->state == SCTP_UNCONFIRMED)) {
                                sctp_assoc_control_transport(
                                        transport->asoc,
                                        transport,
@@ -1562,11 +1572,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;
                }