svn commit: r215578 - stable/8/sys/netinet

Michael Tuexen tuexen at FreeBSD.org
Sat Nov 20 19:26:35 UTC 2010


Author: tuexen
Date: Sat Nov 20 19:26:35 2010
New Revision: 215578
URL: http://svn.freebsd.org/changeset/base/215578

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

Modified:
  stable/8/sys/netinet/sctp_output.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/netinet/sctp_output.c
==============================================================================
--- stable/8/sys/netinet/sctp_output.c	Sat Nov 20 19:23:16 2010	(r215577)
+++ stable/8/sys/netinet/sctp_output.c	Sat Nov 20 19:26:35 2010	(r215578)
@@ -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 */


More information about the svn-src-all mailing list