svn commit: r215198 - head/sys/netinet

Michael Tuexen tuexen at FreeBSD.org
Fri Nov 12 20:45:22 UTC 2010


Author: tuexen
Date: Fri Nov 12 20:45:21 2010
New Revision: 215198
URL: http://svn.freebsd.org/changeset/base/215198

Log:
  Fix more issues with the SACK/NR-SACK generation code.
  
  MFC after: 3 days.

Modified:
  head/sys/netinet/sctp_output.c

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c	Fri Nov 12 20:26:34 2010	(r215197)
+++ head/sys/netinet/sctp_output.c	Fri Nov 12 20:45:21 2010	(r215198)
@@ -9927,13 +9927,14 @@ sctp_send_sack(struct sctp_tcb *stcb)
 	caddr_t limit;
 	uint32_t *dup;
 	int limit_reached = 0;
-	unsigned int i, sel_start, siz, j;
+	unsigned int i, siz, j;
 	unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space;
 	int num_dups = 0;
 	int space_req;
 	uint32_t highest_tsn;
 	uint8_t flags;
 	uint8_t type;
+	uint8_t tsn_map;
 
 	if ((stcb->asoc.sctp_nr_sack_on_off == 1) &&
 	    (stcb->asoc.peer_supports_nr_sack == 1)) {
@@ -10123,24 +10124,24 @@ sctp_send_sack(struct sctp_tcb *stcb)
 	} else {
 		offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
 	}
-	if ((offset == 1) ||
-	    ((type == SCTP_NR_SELECTIVE_ACK) &&
-	    ((asoc->mapping_array[0] & (1 << (1 - offset))) == 0))) {
-		sel_start = 0;
-	} else {
-		sel_start = 1;
-	}
 	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 = 0; i < siz; i++) {
+			tsn_map = asoc->mapping_array[i];
 			if (type == SCTP_SELECTIVE_ACK) {
-				selector = &sack_array[asoc->mapping_array[i] | asoc->nr_mapping_array[i]];
-			} else {
-				selector = &sack_array[asoc->mapping_array[i]];
+				tsn_map |= asoc->nr_mapping_array[i];
+			}
+			if (i == 0) {
+				/*
+				 * Clear all bits corresponding to TSNs
+				 * smaller or equal to the cumulative TSN.
+				 */
+				tsn_map &= (~0 << (1 - offset));
 			}
+			selector = &sack_array[tsn_map];
 			if (mergeable && selector->right_edge) {
 				/*
 				 * Backup, left and right edges were ok to
@@ -10152,7 +10153,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
 			if (selector->num_entries == 0)
 				mergeable = 0;
 			else {
-				for (j = sel_start; j < selector->num_entries; j++) {
+				for (j = 0; j < selector->num_entries; j++) {
 					if (mergeable && selector->right_edge) {
 						/*
 						 * do a merge by NOT setting
@@ -10184,7 +10185,6 @@ sctp_send_sack(struct sctp_tcb *stcb)
 				/* Reached the limit stop */
 				break;
 			}
-			sel_start = 0;
 			offset += 8;
 		}
 	}
@@ -10199,11 +10199,6 @@ sctp_send_sack(struct sctp_tcb *stcb)
 			siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
 		}
 
-		if ((asoc->nr_mapping_array[0] & (1 << (1 - offset))) == 0) {
-			sel_start = 0;
-		} else {
-			sel_start = 1;
-		}
 		if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
 			offset = 1;
 		} else {
@@ -10212,7 +10207,16 @@ sctp_send_sack(struct sctp_tcb *stcb)
 		if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
 			/* we have a gap .. maybe */
 			for (i = 0; i < siz; i++) {
-				selector = &sack_array[asoc->nr_mapping_array[i]];
+				tsn_map = asoc->nr_mapping_array[i];
+				if (i == 0) {
+					/*
+					 * Clear all bits corresponding to
+					 * TSNs smaller or equal to the
+					 * cumulative TSN.
+					 */
+					tsn_map &= (~0 << (1 - offset));
+				}
+				selector = &sack_array[tsn_map];
 				if (mergeable && selector->right_edge) {
 					/*
 					 * Backup, left and right edges were
@@ -10224,7 +10228,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
 				if (selector->num_entries == 0)
 					mergeable = 0;
 				else {
-					for (j = sel_start; j < selector->num_entries; j++) {
+					for (j = 0; j < selector->num_entries; j++) {
 						if (mergeable && selector->right_edge) {
 							/*
 							 * do a merge by NOT
@@ -10257,7 +10261,6 @@ sctp_send_sack(struct sctp_tcb *stcb)
 					/* Reached the limit stop */
 					break;
 				}
-				sel_start = 0;
 				offset += 8;
 			}
 		}


More information about the svn-src-head mailing list