Author: tuexen
Date: Sat Dec  4 19:29:49 2010
New Revision: 216188
URL: http://svn.freebsd.org/changeset/base/216188

Log:
  Fix a bug where also the number of non-renegable gap reports
  was considered to be potentially renegable.
  
  MFC after: 1 day.

Modified:
  head/sys/netinet/sctp_indata.c
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_structs.h

Modified: head/sys/netinet/sctp_indata.c
==============================================================================
--- head/sys/netinet/sctp_indata.c      Sat Dec  4 18:52:05 2010        
(r216187)
+++ head/sys/netinet/sctp_indata.c      Sat Dec  4 19:29:49 2010        
(r216188)
@@ -3081,14 +3081,17 @@ sctp_handle_segments(struct mbuf *m, int
        int num_frs = 0;
        int chunk_freed;
        int non_revocable;
-       uint16_t frag_strt, frag_end;
-       uint32_t last_frag_high;
+       uint16_t frag_strt, frag_end, prev_frag_end;
 
-       tp1 = NULL;
-       last_frag_high = 0;
+       tp1 = TAILQ_FIRST(&asoc->sent_queue);
+       prev_frag_end = 0;
        chunk_freed = 0;
 
        for (i = 0; i < (num_seg + num_nr_seg); i++) {
+               if (i == num_seg) {
+                       prev_frag_end = 0;
+                       tp1 = TAILQ_FIRST(&asoc->sent_queue);
+               }
                frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset,
                    sizeof(struct sctp_gap_ack_block), (uint8_t *) & block);
                *offset += sizeof(block);
@@ -3097,58 +3100,29 @@ sctp_handle_segments(struct mbuf *m, int
                }
                frag_strt = ntohs(frag->start);
                frag_end = ntohs(frag->end);
-               /* some sanity checks on the fragment offsets */
+
                if (frag_strt > frag_end) {
-                       /* this one is malformed, skip */
+                       /* This gap report is malformed, skip it. */
                        continue;
                }
-               if (compare_with_wrap((frag_end + last_tsn), *biggest_tsn_acked,
-                   MAX_TSN))
-                       *biggest_tsn_acked = frag_end + last_tsn;
-
-               /* mark acked dgs and find out the highestTSN being acked */
-               if (tp1 == NULL) {
+               if (frag_strt <= prev_frag_end) {
+                       /* This gap report is not in order, so restart. */
                        tp1 = TAILQ_FIRST(&asoc->sent_queue);
-                       /* save the locations of the last frags */
-                       last_frag_high = frag_end + last_tsn;
-               } else {
-                       /*
-                        * now lets see if we need to reset the queue due to
-                        * a out-of-order SACK fragment
-                        */
-                       if (compare_with_wrap(frag_strt + last_tsn,
-                           last_frag_high, MAX_TSN)) {
-                               /*
-                                * if the new frag starts after the last TSN
-                                * frag covered, we are ok and this one is
-                                * beyond the last one
-                                */
-                               ;
-                       } else {
-                               /*
-                                * ok, they have reset us, so we need to
-                                * reset the queue this will cause extra
-                                * hunting but hey, they chose the
-                                * performance hit when they failed to order
-                                * their gaps
-                                */
-                               tp1 = TAILQ_FIRST(&asoc->sent_queue);
-                       }
-                       last_frag_high = frag_end + last_tsn;
+               }
+               if (compare_with_wrap((last_tsn + frag_end), 
*biggest_tsn_acked, MAX_TSN)) {
+                       *biggest_tsn_acked = last_tsn + frag_end;
                }
                if (i < num_seg) {
                        non_revocable = 0;
                } else {
                        non_revocable = 1;
                }
-               if (i == num_seg) {
-                       tp1 = NULL;
-               }
                if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, 
frag_end,
                    non_revocable, &num_frs, biggest_newly_acked_tsn,
                    this_sack_lowest_newack, ecn_seg_sums)) {
                        chunk_freed = 1;
                }
+               prev_frag_end = frag_end;
        }
        if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
                if (num_frs)
@@ -4817,7 +4791,7 @@ sctp_handle_sack(struct mbuf *m, int off
                }
        }
        /********************************************/
-       /* drop the acked chunks from the sendqueue */
+       /* drop the acked chunks from the sentqueue */
        /********************************************/
        asoc->last_acked_seq = cum_ack;
 
@@ -4925,9 +4899,10 @@ done_with_it:
         * we had some before and now we have NONE.
         */
 
-       if (num_seg)
+       if (num_seg) {
                sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked);
-       else if (asoc->saw_sack_with_frags) {
+               asoc->saw_sack_with_frags = 1;
+       } else if (asoc->saw_sack_with_frags) {
                int cnt_revoked = 0;
 
                tp1 = TAILQ_FIRST(&asoc->sent_queue);
@@ -4963,10 +4938,10 @@ done_with_it:
                }
                asoc->saw_sack_with_frags = 0;
        }
-       if (num_seg || num_nr_seg)
-               asoc->saw_sack_with_frags = 1;
+       if (num_nr_seg > 0)
+               asoc->saw_sack_with_nr_frags = 1;
        else
-               asoc->saw_sack_with_frags = 0;
+               asoc->saw_sack_with_nr_frags = 0;
 
        /* JRS - Use the congestion control given in the CC module */
        asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, 
reneged_all, will_exit_fast_recovery);

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Sat Dec  4 18:52:05 2010        
(r216187)
+++ head/sys/netinet/sctp_input.c       Sat Dec  4 19:29:49 2010        
(r216188)
@@ -4644,6 +4644,7 @@ process_control_chunks:
                                    ((compare_with_wrap(cum_ack, 
stcb->asoc.last_acked_seq, MAX_TSN)) ||
                                    (cum_ack == stcb->asoc.last_acked_seq)) &&
                                    (stcb->asoc.saw_sack_with_frags == 0) &&
+                                   (stcb->asoc.saw_sack_with_nr_frags == 0) &&
                                    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))
                                    ) {
                                        /*
@@ -4737,6 +4738,7 @@ process_control_chunks:
                                    ((compare_with_wrap(cum_ack, 
stcb->asoc.last_acked_seq, MAX_TSN)) ||
                                    (cum_ack == stcb->asoc.last_acked_seq)) &&
                                    (stcb->asoc.saw_sack_with_frags == 0) &&
+                                   (stcb->asoc.saw_sack_with_nr_frags == 0) &&
                                    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
                                        /*
                                         * We have a SIMPLE sack having no

Modified: head/sys/netinet/sctp_structs.h
==============================================================================
--- head/sys/netinet/sctp_structs.h     Sat Dec  4 18:52:05 2010        
(r216187)
+++ head/sys/netinet/sctp_structs.h     Sat Dec  4 19:29:49 2010        
(r216188)
@@ -1058,6 +1058,7 @@ struct sctp_association {
        uint8_t delayed_connection;
        uint8_t ifp_had_enobuf;
        uint8_t saw_sack_with_frags;
+       uint8_t saw_sack_with_nr_frags;
        uint8_t in_asocid_hash;
        uint8_t assoc_up_sent;
        uint8_t adaptation_needed;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to