Author: tuexen
Date: Sat Nov  6 13:30:54 2010
New Revision: 214876
URL: http://svn.freebsd.org/changeset/base/214876

Log:
  * Fix an accounting bug regarding SACK/NR-SACK chunks.
  * Fix the generation of the SACK/NR-SACK gap lists.
  
  MFC after: 3 days.

Modified:
  head/sys/netinet/sctp_output.c

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Sat Nov  6 13:03:33 2010        
(r214875)
+++ head/sys/netinet/sctp_output.c      Sat Nov  6 13:30:54 2010        
(r214876)
@@ -9927,7 +9927,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
        caddr_t limit;
        uint32_t *dup;
        int limit_reached = 0;
-       unsigned int i, sel_start, siz, j, starting_index;
+       unsigned int i, sel_start, siz, j;
        unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space;
        int num_dups = 0;
        int space_req;
@@ -9954,7 +9954,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
                if (chk->rec.chunk_id.id == type) {
                        /* Hmm, found a sack already on queue, remove it */
                        TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
-                       asoc->ctrl_queue_cnt++;
+                       asoc->ctrl_queue_cnt--;
                        a_chk = chk;
                        if (a_chk->data) {
                                sctp_m_freem(a_chk->data);
@@ -9993,15 +9993,13 @@ sctp_send_sack(struct sctp_tcb *stcb)
        a_chk->whoTo = NULL;
 
        if ((asoc->numduptsns) ||
-           (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)
-           ) {
+           (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)) 
{
                /*-
                 * Ok, we have some duplicates or the destination for the
                 * sack is unreachable, lets see if we can select an
                 * alternate than asoc->last_data_chunk_from
                 */
-               if ((!(asoc->last_data_chunk_from->dest_state &
-                   SCTP_ADDR_NOT_REACHABLE)) &&
+               if ((!(asoc->last_data_chunk_from->dest_state & 
SCTP_ADDR_NOT_REACHABLE)) &&
                    (asoc->used_alt_onsack > asoc->numnets)) {
                        /* We used an alt last time, don't this time */
                        a_chk->whoTo = NULL;
@@ -10120,53 +10118,25 @@ sctp_send_sack(struct sctp_tcb *stcb)
                }
        }
 
-       if (compare_with_wrap(asoc->mapping_array_base_tsn, 
asoc->cumulative_tsn, MAX_TSN)) {
-               offset = 1;
-               /*-
-                * The base TSN is intialized to be the first TSN the peer
-                * will send us. If the cum-ack is behind this then when they
-                * send us the next in sequence it will mark the base_tsn bit.
-                * Thus we need to use the very first selector and the offset
-                * is 1. Our table is built for this case.
-                */
-               starting_index = 0;
+       if (((type == SCTP_SELECTIVE_ACK) &&
+           (((asoc->mapping_array[0] | asoc->nr_mapping_array[0]) & 0x01) == 
0x00)) ||
+           ((type == SCTP_NR_SELECTIVE_ACK) &&
+           ((asoc->mapping_array[0] & 0x01) == 0x00))) {
                sel_start = 0;
        } else {
-               /*-
-                * we skip the first selector  when the cum-ack is at or above 
the
-                * mapping array base. This is because the bits at the base or 
above
-                * are turned on and our first selector in the table assumes 
they are
-                * off. We thus will use the second selector (first is 0). We 
use
-                * the reverse of our macro to fix the offset, in bits, that our
-                * table is at. Note that this method assumes that the cum-tsn 
is
-                * within the first bit, i.e. its value is 0-7 which means the
-                * result to our offset will be either a 0 - -7. If the cumack
-                * is NOT in the first byte (0) (which it should be since we did
-                * a mapping array slide above) then we need to calculate the 
starting
-                * index i.e. which byte of the mapping array we should start 
at. We
-                * do this by dividing by 8 and pushing the remainder (mod) 
into offset.
-                * then we multiply the offset to be negative, since we need a 
negative
-                * offset into the selector table.
-                */
-               SCTP_CALC_TSN_TO_GAP(offset, asoc->cumulative_tsn, 
asoc->mapping_array_base_tsn);
-               if (offset > 7) {
-                       starting_index = offset / 8;
-                       offset = offset % 8;
-                       printf("Strange starting index is %d offset:%d (not 
0/x)\n",
-                           starting_index, offset);
-               } else {
-                       starting_index = 0;
-               }
-               /* We need a negative offset in our table */
-               offset *= -1;
                sel_start = 1;
        }
+       if (compare_with_wrap(asoc->mapping_array_base_tsn, 
asoc->cumulative_tsn, MAX_TSN)) {
+               offset = 1;
+       } else {
+               offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
+       }
        if (((type == SCTP_SELECTIVE_ACK) &&
            compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) ||
            ((type == SCTP_NR_SELECTIVE_ACK) &&
            compare_with_wrap(asoc->highest_tsn_inside_map, 
asoc->cumulative_tsn, MAX_TSN))) {
                /* we have a gap .. maybe */
-               for (i = starting_index; i < siz; i++) {
+               for (i = 0; i < siz; i++) {
                        if (type == SCTP_SELECTIVE_ACK) {
                                selector = &sack_array[asoc->mapping_array[i] | 
asoc->nr_mapping_array[i]];
                        } else {
@@ -10224,25 +10194,21 @@ sctp_send_sack(struct sctp_tcb *stcb)
 
                mergeable = 0;
 
-               if (asoc->highest_tsn_inside_nr_map > 
asoc->mapping_array_base_tsn)
+               if (asoc->highest_tsn_inside_nr_map > 
asoc->mapping_array_base_tsn) {
                        siz = (((asoc->highest_tsn_inside_nr_map - 
asoc->mapping_array_base_tsn) + 1) + 7) / 8;
-               else
+               } else {
                        siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + 
asoc->highest_tsn_inside_nr_map + 7) / 8;
+               }
 
+               if ((asoc->nr_mapping_array[0] & 0x01) == 0x00) {
+                       sel_start = 0;
+               } else {
+                       sel_start = 1;
+               }
                if (compare_with_wrap(asoc->mapping_array_base_tsn, 
asoc->cumulative_tsn, MAX_TSN)) {
                        offset = 1;
-                       /*-
-                       * cum-ack behind the mapping array, so we start and use 
all
-                       * entries.
-                       */
-                       sel_start = 0;
                } else {
                        offset = asoc->mapping_array_base_tsn - 
asoc->cumulative_tsn;
-                       /*-
-                       * we skip the first one when the cum-ack is at or above 
the
-                       * mapping array base. Note this only works if
-                       */
-                       sel_start = 1;
                }
                if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, 
asoc->cumulative_tsn, MAX_TSN)) {
                        /* we have a gap .. maybe */
_______________________________________________
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