svn commit: r206137 - in head/sys: netinet netinet6

Michael Tuexen tuexen at FreeBSD.org
Sat Apr 3 15:40:14 UTC 2010


Author: tuexen
Date: Sat Apr  3 15:40:14 2010
New Revision: 206137
URL: http://svn.freebsd.org/changeset/base/206137

Log:
  * Fix some race condition in SACK/NR-SACK processing.
  * Fix handling of mapping arrays when draining mbufs or processing
    FORWARD-TSN chunks.
  * Cleanup code (no duplicate code anymore for SACKs and NR-SACKs).
  Part of this code was developed together with rrs.
  MFC after: 2 weeks.

Modified:
  head/sys/netinet/sctp_asconf.c
  head/sys/netinet/sctp_constants.h
  head/sys/netinet/sctp_indata.c
  head/sys/netinet/sctp_indata.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctp_output.h
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_pcb.h
  head/sys/netinet/sctp_structs.h
  head/sys/netinet/sctp_usrreq.c
  head/sys/netinet/sctp_var.h
  head/sys/netinet/sctputil.c
  head/sys/netinet/sctputil.h
  head/sys/netinet6/sctp6_usrreq.c

Modified: head/sys/netinet/sctp_asconf.c
==============================================================================
--- head/sys/netinet/sctp_asconf.c	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_asconf.c	Sat Apr  3 15:40:14 2010	(r206137)
@@ -556,9 +556,9 @@ sctp_process_asconf_set_primary(struct m
 		 * PRIMARY with DELETE IP ADDRESS of the previous primary
 		 * destination, unacknowledged DATA are retransmitted
 		 * immediately to the new primary destination for seamless
-		 * handover.  If the destination is UNCONFIRMED and marked
-		 * to REQ_PRIM, The retransmission occur when reception of
-		 * the HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
+		 * handover. If the destination is UNCONFIRMED and marked to
+		 * REQ_PRIM, The retransmission occur when reception of the
+		 * HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
 		 * sctp_input.c) Also, when change of the primary
 		 * destination, it is better that all subsequent new DATA
 		 * containing already queued DATA are transmitted to the new
@@ -1166,7 +1166,7 @@ sctp_path_check_and_react(struct sctp_tc
 
 	/*
 	 * If number of local valid addresses is 1, the valid address is
-	 * probably newly added address.  Several valid addresses in this
+	 * probably newly added address. Several valid addresses in this
 	 * association.  A source address may not be changed.  Additionally,
 	 * they can be configured on a same interface as "alias" addresses.
 	 * (by micchie)
@@ -1210,7 +1210,7 @@ sctp_path_check_and_react(struct sctp_tc
 		/*
 		 * Check if the nexthop is corresponding to the new address.
 		 * If the new address is corresponding to the current
-		 * nexthop, the path will be changed.  If the new address is
+		 * nexthop, the path will be changed. If the new address is
 		 * NOT corresponding to the current nexthop, the path will
 		 * not be changed.
 		 */

Modified: head/sys/netinet/sctp_constants.h
==============================================================================
--- head/sys/netinet/sctp_constants.h	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_constants.h	Sat Apr  3 15:40:14 2010	(r206137)
@@ -544,13 +544,7 @@ __FBSDID("$FreeBSD$");
 #define SCTP_INITIAL_MAPPING_ARRAY  16
 /* how much we grow the mapping array each call */
 #define SCTP_MAPPING_ARRAY_INCR     32
-/* EY 05/13/08 - nr_sack version of the previous 3 constants */
-/* Maximum the nr mapping array will  grow to (TSN mapping array) */
-#define SCTP_NR_MAPPING_ARRAY	512
-/* size of the inital malloc on the nr mapping array */
-#define SCTP_INITIAL_NR_MAPPING_ARRAY  16
-/* how much we grow the nr mapping array each call */
-#define SCTP_NR_MAPPING_ARRAY_INCR     32
+
 /*
  * Here we define the timer types used by the implementation as arguments in
  * the set/get timer type calls.
@@ -933,6 +927,13 @@ __FBSDID("$FreeBSD$");
 #define SCTP_IS_TSN_PRESENT(arry, gap) ((arry[(gap >> 3)] >> (gap & 0x07)) & 0x01)
 #define SCTP_SET_TSN_PRESENT(arry, gap) (arry[(gap >> 3)] |= (0x01 << ((gap & 0x07))))
 #define SCTP_UNSET_TSN_PRESENT(arry, gap) (arry[(gap >> 3)] &= ((~(0x01 << ((gap & 0x07)))) & 0xff))
+#define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \
+	                if (tsn >= mapping_tsn) { \
+						gap = tsn - mapping_tsn; \
+					} else { \
+						gap = (MAX_TSN - mapping_tsn) + tsn + 1; \
+					} \
+                  } while(0)
 
 
 #define SCTP_RETRAN_DONE -1

Modified: head/sys/netinet/sctp_indata.c
==============================================================================
--- head/sys/netinet/sctp_indata.c	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_indata.c	Sat Apr  3 15:40:14 2010	(r206137)
@@ -45,13 +45,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/sctp_uio.h>
 #include <netinet/sctp_timer.h>
 
-#define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \
-	                if (tsn >= mapping_tsn) { \
-						gap = tsn - mapping_tsn; \
-					} else { \
-						gap = (MAX_TSN - mapping_tsn) + tsn + 1; \
-					} \
-                  } while(0)
 
 /*
  * NOTES: On the outbound side of things I need to check the sack timer to
@@ -303,13 +296,13 @@ sctp_mark_non_revokable(struct sctp_asso
 		return;
 	}
 	SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
-#ifdef INVARIANTS
 	if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
 		printf("gap:%x tsn:%x\n", gap, tsn);
 		sctp_print_mapping_array(asoc);
+#ifdef INVARIANTS
 		panic("Things are really messed up now!!");
-	}
 #endif
+	}
 	SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
 	SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
 	if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
@@ -317,7 +310,8 @@ sctp_mark_non_revokable(struct sctp_asso
 	}
 	if (tsn == asoc->highest_tsn_inside_map) {
 		/* We must back down to see what the new highest is */
-		for (i = tsn - 1; compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN); i--) {
+		for (i = tsn - 1; (compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN) ||
+		    (i == asoc->mapping_array_base_tsn)); i--) {
 			SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn);
 			if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
 				asoc->highest_tsn_inside_map = i;
@@ -411,6 +405,7 @@ abandon:
 				end = 1;
 			else
 				end = 0;
+			sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
 			sctp_add_to_readq(stcb->sctp_ep,
 			    stcb, control, &stcb->sctp_socket->so_rcv, end,
 			    SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
@@ -420,6 +415,7 @@ abandon:
 				end = 1;
 			else
 				end = 0;
+			sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
 			if (sctp_append_to_readq(stcb->sctp_ep, stcb,
 			    stcb->asoc.control_pdapi,
 			    chk->data, end, chk->rec.data.TSN_seq,
@@ -454,7 +450,6 @@ abandon:
 		}
 		/* pull it we did it */
 		TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
-		sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
 		if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
 			asoc->fragmented_delivery_inprogress = 0;
 			if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) {
@@ -501,11 +496,11 @@ abandon:
 						asoc->size_on_all_streams -= ctl->length;
 						sctp_ucount_decr(asoc->cnt_on_all_streams);
 						strm->last_sequence_delivered++;
+						sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 						sctp_add_to_readq(stcb->sctp_ep, stcb,
 						    ctl,
 						    &stcb->sctp_socket->so_rcv, 1,
 						    SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
-						sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 						ctl = ctlat;
 					} else {
 						break;
@@ -616,11 +611,11 @@ protocol_error:
 		sctp_ucount_decr(asoc->cnt_on_all_streams);
 		strm->last_sequence_delivered++;
 
+		sctp_mark_non_revokable(asoc, control->sinfo_tsn);
 		sctp_add_to_readq(stcb->sctp_ep, stcb,
 		    control,
 		    &stcb->sctp_socket->so_rcv, 1,
 		    SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
-		sctp_mark_non_revokable(asoc, control->sinfo_tsn);
 		control = TAILQ_FIRST(&strm->inqueue);
 		while (control != NULL) {
 			/* all delivered */
@@ -641,13 +636,12 @@ protocol_error:
 					sctp_log_strm_del(control, NULL,
 					    SCTP_STR_LOG_FROM_IMMED_DEL);
 				}
-				/* EY will be used to calculate nr-gap */
+				sctp_mark_non_revokable(asoc, control->sinfo_tsn);
 				sctp_add_to_readq(stcb->sctp_ep, stcb,
 				    control,
 				    &stcb->sctp_socket->so_rcv, 1,
 				    SCTP_READ_LOCK_NOT_HELD,
 				    SCTP_SO_NOT_LOCKED);
-				sctp_mark_non_revokable(asoc, control->sinfo_tsn);
 				control = at;
 				continue;
 			}
@@ -965,8 +959,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 					*abort_flag = 1;
 				} else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) !=
 					    SCTP_DATA_UNORDERED &&
-					    chk->rec.data.stream_seq !=
-				    asoc->ssn_of_pdapi) {
+				    chk->rec.data.stream_seq != asoc->ssn_of_pdapi) {
 					/* Got to be the right STR Seq */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n",
 					    chk->rec.data.stream_seq,
@@ -1623,7 +1616,6 @@ sctp_process_a_data_chunk(struct sctp_tc
 		}
 		SCTP_STAT_INCR(sctps_badsid);
 		SCTP_TCB_LOCK_ASSERT(stcb);
-
 		SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
 		if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
 			asoc->highest_tsn_inside_nr_map = tsn;
@@ -1787,6 +1779,7 @@ sctp_process_a_data_chunk(struct sctp_tc
 			    SCTP_STR_LOG_FROM_EXPRS_DEL);
 		}
 		control = NULL;
+
 		SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
 		if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
 			asoc->highest_tsn_inside_nr_map = tsn;
@@ -1853,10 +1846,6 @@ failed_express_del:
 					need_reasm_check = 1;
 				}
 			}
-			SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
-			if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
-				asoc->highest_tsn_inside_nr_map = tsn;
-			}
 			control = NULL;
 			goto finish_express_del;
 		}
@@ -2059,10 +2048,10 @@ failed_pdapi_express_del:
 		/* ok, if we reach here we have passed the sanity checks */
 		if (chunk_flags & SCTP_DATA_UNORDERED) {
 			/* queue directly into socket buffer */
+			sctp_mark_non_revokable(asoc, control->sinfo_tsn);
 			sctp_add_to_readq(stcb->sctp_ep, stcb,
 			    control,
 			    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
-
 		} else {
 			/*
 			 * Special check for when streams are resetting. We
@@ -2134,10 +2123,6 @@ failed_pdapi_express_del:
 		}
 	}
 finish_express_del:
-	if (tsn == (asoc->cumulative_tsn + 1)) {
-		/* Update cum-ack */
-		asoc->cumulative_tsn = tsn;
-	}
 	if (last_chunk) {
 		*m = NULL;
 	}
@@ -2215,43 +2200,43 @@ finish_express_del:
 }
 
 int8_t sctp_map_lookup_tab[256] = {
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 4,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 5,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 4,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 6,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 4,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 5,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 4,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 3,
-	-1, 0, -1, 1, -1, 0, -1, 2,
-	-1, 0, -1, 1, -1, 0, -1, 7,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 5,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 6,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 5,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 7,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 5,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 6,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 5,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 4,
+	0, 1, 0, 2, 0, 1, 0, 3,
+	0, 1, 0, 2, 0, 1, 0, 8
 };
 
 
 void
-sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort_flag)
+sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
 {
 	/*
 	 * Now we also need to check the mapping array in a couple of ways.
@@ -2259,7 +2244,6 @@ sctp_sack_check(struct sctp_tcb *stcb, i
 	 */
 	struct sctp_association *asoc;
 	int at;
-	int last_all_ones = 0;
 	int slide_from, slide_end, lgap, distance;
 
 	/* EY nr_mapping array variables */
@@ -2279,19 +2263,16 @@ sctp_sack_check(struct sctp_tcb *stcb, i
 	 * offset of the current cum-ack as the starting point.
 	 */
 	at = 0;
-	for (slide_from = 0; slide_from < stcb->asoc.nr_mapping_array_size; slide_from++) {
+	for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) {
 		if (asoc->nr_mapping_array[slide_from] == 0xff) {
 			at += 8;
-			last_all_ones = 1;
 		} else {
 			/* there is a 0 bit */
 			at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]];
-			last_all_ones = 0;
 			break;
 		}
 	}
-	asoc->cumulative_tsn = asoc->nr_mapping_array_base_tsn + (at - last_all_ones);
-	at++;
+	asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - 1);
 
 	if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) &&
 	    compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)
@@ -2320,18 +2301,22 @@ sctp_sack_check(struct sctp_tcb *stcb, i
 	if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) {
 		/* The complete array was completed by a single FR */
 		/* highest becomes the cum-ack */
-		int clr;
+		int clr, i;
 
 		/* clear the array */
-		clr = (at >> 3) + 1;
+		clr = ((at + 7) >> 3);
 		if (clr > asoc->mapping_array_size) {
 			clr = asoc->mapping_array_size;
 		}
 		memset(asoc->mapping_array, 0, clr);
 		memset(asoc->nr_mapping_array, 0, clr);
-
+		for (i = 0; i < asoc->mapping_array_size; i++) {
+			if ((asoc->mapping_array[i]) || (asoc->nr_mapping_array[i])) {
+				printf("Error Mapping array's not clean at clear\n");
+				sctp_print_mapping_array(asoc);
+			}
+		}
 		asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1;
-		asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1;
 		asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
 	} else if (at >= 8) {
 		/* we can slide the mapping array down */
@@ -2393,12 +2378,11 @@ sctp_sack_check(struct sctp_tcb *stcb, i
 				    asoc->nr_mapping_array[slide_from + ii];
 
 			}
-			for (ii = distance; ii <= slide_end; ii++) {
+			for (ii = distance; ii <= asoc->mapping_array_size; ii++) {
 				asoc->mapping_array[ii] = 0;
 				asoc->nr_mapping_array[ii] = 0;
 			}
 			asoc->mapping_array_base_tsn += (slide_from << 3);
-			asoc->nr_mapping_array_base_tsn += (slide_from << 3);
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
 				sctp_log_map(asoc->mapping_array_base_tsn,
 				    asoc->cumulative_tsn, asoc->highest_tsn_inside_map,
@@ -2406,95 +2390,95 @@ sctp_sack_check(struct sctp_tcb *stcb, i
 			}
 		}
 	}
+}
+
+
+void
+sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
+{
+	struct sctp_association *asoc;
+	uint32_t highest_tsn;
+
+	asoc = &stcb->asoc;
+	if (compare_with_wrap(asoc->highest_tsn_inside_nr_map,
+	    asoc->highest_tsn_inside_map,
+	    MAX_TSN)) {
+		highest_tsn = asoc->highest_tsn_inside_nr_map;
+	} else {
+		highest_tsn = asoc->highest_tsn_inside_map;
+	}
+
 	/*
 	 * Now we need to see if we need to queue a sack or just start the
 	 * timer (if allowed).
 	 */
-	if (ok_to_sack) {
-		if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
-			/*
-			 * Ok special case, in SHUTDOWN-SENT case. here we
-			 * maker sure SACK timer is off and instead send a
-			 * SHUTDOWN and a SACK
-			 */
-			if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
-				sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
-				    stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
-			}
-			sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
-			/*
-			 * EY if nr_sacks used then send an nr-sack , a sack
-			 * otherwise
-			 */
-			if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack)
-				sctp_send_nr_sack(stcb);
-			else
-				sctp_send_sack(stcb);
-		} else {
-			int is_a_gap;
+	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
+		/*
+		 * Ok special case, in SHUTDOWN-SENT case. here we maker
+		 * sure SACK timer is off and instead send a SHUTDOWN and a
+		 * SACK
+		 */
+		if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
+			sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
+			    stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
+		}
+		sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+		sctp_send_sack(stcb);
+	} else {
+		int is_a_gap;
 
-			/* is there a gap now ? */
-			is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
+		/* is there a gap now ? */
+		is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
 
-			/*
-			 * CMT DAC algorithm: increase number of packets
-			 * received since last ack
-			 */
-			stcb->asoc.cmt_dac_pkts_rcvd++;
+		/*
+		 * CMT DAC algorithm: increase number of packets received
+		 * since last ack
+		 */
+		stcb->asoc.cmt_dac_pkts_rcvd++;
 
-			if ((stcb->asoc.send_sack == 1) ||	/* We need to send a
-								 * SACK */
-			    ((was_a_gap) && (is_a_gap == 0)) ||	/* was a gap, but no
-								 * longer is one */
-			    (stcb->asoc.numduptsns) ||	/* we have dup's */
-			    (is_a_gap) ||	/* is still a gap */
-			    (stcb->asoc.delayed_ack == 0) ||	/* Delayed sack disabled */
-			    (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq)	/* hit limit of pkts */
-			    ) {
+		if ((stcb->asoc.send_sack == 1) ||	/* We need to send a
+							 * SACK */
+		    ((was_a_gap) && (is_a_gap == 0)) ||	/* was a gap, but no
+							 * longer is one */
+		    (stcb->asoc.numduptsns) ||	/* we have dup's */
+		    (is_a_gap) ||	/* is still a gap */
+		    (stcb->asoc.delayed_ack == 0) ||	/* Delayed sack disabled */
+		    (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq)	/* hit limit of pkts */
+		    ) {
 
-				if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
-				    (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
-				    (stcb->asoc.send_sack == 0) &&
-				    (stcb->asoc.numduptsns == 0) &&
-				    (stcb->asoc.delayed_ack) &&
-				    (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) {
+			if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
+			    (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
+			    (stcb->asoc.send_sack == 0) &&
+			    (stcb->asoc.numduptsns == 0) &&
+			    (stcb->asoc.delayed_ack) &&
+			    (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) {
 
-					/*
-					 * CMT DAC algorithm: With CMT,
-					 * delay acks even in the face of
-					 * 
-					 * reordering. Therefore, if acks that
-					 * do not have to be sent because of
-					 * the above reasons, will be
-					 * delayed. That is, acks that would
-					 * have been sent due to gap reports
-					 * will be delayed with DAC. Start
-					 * the delayed ack timer.
-					 */
-					sctp_timer_start(SCTP_TIMER_TYPE_RECV,
-					    stcb->sctp_ep, stcb, NULL);
-				} else {
-					/*
-					 * Ok we must build a SACK since the
-					 * timer is pending, we got our
-					 * first packet OR there are gaps or
-					 * duplicates.
-					 */
-					(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
-					/*
-					 * EY if nr_sacks used then send an
-					 * nr-sack , a sack otherwise
-					 */
-					if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack)
-						sctp_send_nr_sack(stcb);
-					else
-						sctp_send_sack(stcb);
-				}
+				/*
+				 * CMT DAC algorithm: With CMT, delay acks
+				 * even in the face of
+				 * 
+				 * reordering. Therefore, if acks that do not
+				 * have to be sent because of the above
+				 * reasons, will be delayed. That is, acks
+				 * that would have been sent due to gap
+				 * reports will be delayed with DAC. Start
+				 * the delayed ack timer.
+				 */
+				sctp_timer_start(SCTP_TIMER_TYPE_RECV,
+				    stcb->sctp_ep, stcb, NULL);
 			} else {
-				if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
-					sctp_timer_start(SCTP_TIMER_TYPE_RECV,
-					    stcb->sctp_ep, stcb, NULL);
-				}
+				/*
+				 * Ok we must build a SACK since the timer
+				 * is pending, we got our first packet OR
+				 * there are gaps or duplicates.
+				 */
+				(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
+				sctp_send_sack(stcb);
+			}
+		} else {
+			if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
+				sctp_timer_start(SCTP_TIMER_TYPE_RECV,
+				    stcb->sctp_ep, stcb, NULL);
 			}
 		}
 	}
@@ -2834,14 +2818,7 @@ sctp_process_data(struct mbuf **mm, int 
 			if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
 				(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
 			}
-			/*
-			 * EY if nr_sacks used then send an nr-sack , a sack
-			 * otherwise
-			 */
-			if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack)
-				sctp_send_nr_sack(stcb);
-			else
-				sctp_send_sack(stcb);
+			sctp_send_sack(stcb);
 		} else {
 			if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
 				sctp_timer_start(SCTP_TIMER_TYPE_RECV,
@@ -2849,7 +2826,7 @@ sctp_process_data(struct mbuf **mm, int 
 			}
 		}
 	} else {
-		sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
+		sctp_sack_check(stcb, was_a_gap, &abort_flag);
 	}
 	if (abort_flag)
 		return (2);
@@ -2867,7 +2844,7 @@ sctp_process_segment_range(struct sctp_t
 {
 	struct sctp_tmit_chunk *tp1;
 	unsigned int theTSN;
-	int j, wake_him = 0;
+	int j, wake_him = 0, circled = 0;
 
 	/* Recover the tp1 we last saw */
 	tp1 = *p_tp1;
@@ -3045,12 +3022,6 @@ sctp_process_segment_range(struct sctp_t
 					}
 					/* NR Sack code here */
 					if (nr_sacking) {
-						if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
-							tp1->sent = SCTP_DATAGRAM_NR_MARKED;
-						/*
-						 * TAILQ_REMOVE(&asoc->sent_q
-						 * ueue, tp1, sctp_next);
-						 */
 						if (tp1->data) {
 							/*
 							 * sa_ignore
@@ -3058,13 +3029,8 @@ sctp_process_segment_range(struct sctp_t
 							 */
 							sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
 							sctp_m_freem(tp1->data);
+							tp1->data = NULL;
 						}
-						tp1->data = NULL;
-						/* asoc->sent_queue_cnt--; */
-						/*
-						 * sctp_free_a_chunk(stcb,
-						 * tp1);
-						 */
 						wake_him++;
 					}
 				}
@@ -3075,11 +3041,16 @@ sctp_process_segment_range(struct sctp_t
 				break;
 
 			tp1 = TAILQ_NEXT(tp1, sctp_next);
+			if ((tp1 == NULL) && (circled == 0)) {
+				circled++;
+				tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
+			}
 		}		/* end while (tp1) */
-		/* In case the fragments were not in order we must reset */
 		if (tp1 == NULL) {
+			circled = 0;
 			tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
 		}
+		/* In case the fragments were not in order we must reset */
 	}			/* end for (j = fragStart */
 	*p_tp1 = tp1;
 	return (wake_him);	/* Return value only used for nr-sack */
@@ -3158,6 +3129,9 @@ sctp_handle_segments(struct mbuf *m, int
 		} 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)) {
@@ -3961,6 +3935,7 @@ sctp_express_handle_sack(struct sctp_tcb
 #ifdef INVARIANTS
 			panic("Impossible sack 1");
 #else
+
 			*abort_now = 1;
 			/* XXX */
 			oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
@@ -4439,50 +4414,6 @@ again:
 	}
 }
 
-/* EY- nr_sack */
-/* Identifies the non-renegable tsns that are revoked*/
-static void
-sctp_check_for_nr_revoked(struct sctp_tcb *stcb,
-    struct sctp_association *asoc, uint32_t cumack,
-    uint32_t biggest_tsn_acked)
-{
-	struct sctp_tmit_chunk *tp1;
-
-	for (tp1 = TAILQ_FIRST(&asoc->sent_queue); tp1; tp1 = TAILQ_NEXT(tp1, sctp_next)) {
-		if (compare_with_wrap(tp1->rec.data.TSN_seq, cumack,
-		    MAX_TSN)) {
-			/*
-			 * ok this guy is either ACK or MARKED. If it is
-			 * ACKED it has been previously acked but not this
-			 * time i.e. revoked.  If it is MARKED it was ACK'ed
-			 * again.
-			 */
-			if (compare_with_wrap(tp1->rec.data.TSN_seq, biggest_tsn_acked,
-			    MAX_TSN))
-				break;
-
-
-			if (tp1->sent == SCTP_DATAGRAM_NR_ACKED) {
-				/*
-				 * EY! a non-renegable TSN is revoked, need
-				 * to abort the association
-				 */
-				/*
-				 * EY TODO: put in the code to abort the
-				 * assoc.
-				 */
-				return;
-			} else if (tp1->sent == SCTP_DATAGRAM_NR_MARKED) {
-				/* it has been re-acked in this SACK */
-				tp1->sent = SCTP_DATAGRAM_NR_ACKED;
-			}
-		}
-		if (tp1->sent == SCTP_DATAGRAM_UNSENT)
-			break;
-	}
-	return;
-}
-
 void
 sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
     struct sctp_tcb *stcb, struct sctp_nets *net_from,
@@ -4588,22 +4519,23 @@ sctp_handle_sack(struct mbuf *m, int off
 			    sctpchunk_listhead);
 			send_s = tp1->rec.data.TSN_seq + 1;
 		} else {
+			tp1 = NULL;
 			send_s = asoc->sending_seq;
 		}
 		if (cum_ack == send_s ||
 		    compare_with_wrap(cum_ack, send_s, MAX_TSN)) {
-#ifndef INVARIANTS
 			struct mbuf *oper;
 
-#endif
-#ifdef INVARIANTS
-	hopeless_peer:
-			panic("Impossible sack 1");
-#else
 			/*
 			 * no way, we have not even sent this TSN out yet.
 			 * Peer is hopelessly messed up with us.
 			 */
+			printf("NEW cum_ack:%x send_s:%x is smaller or equal\n",
+			    cum_ack, send_s);
+			if (tp1) {
+				printf("Got send_s from tsn:%x + 1 of tp1:%p\n",
+				    tp1->rec.data.TSN_seq, tp1);
+			}
 	hopeless_peer:
 			*abort_now = 1;
 			/* XXX */
@@ -4624,7 +4556,6 @@ sctp_handle_sack(struct mbuf *m, int off
 			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
 			sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
 			return;
-#endif
 		}
 	}
 	/**********************/
@@ -4844,6 +4775,10 @@ sctp_handle_sack(struct mbuf *m, int off
 				 * peer is either confused or we are under
 				 * attack. We must abort.
 				 */
+				printf("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n",
+				    biggest_tsn_acked,
+				    send_s);
+
 				goto hopeless_peer;
 			}
 		}
@@ -4991,15 +4926,9 @@ done_with_it:
 				 */
 				if ((tp1->sent == SCTP_DATAGRAM_NR_ACKED) ||
 				    (tp1->sent == SCTP_DATAGRAM_NR_MARKED)) {
-					/*
-					 * EY! - TODO: Something previously
-					 * nr_gapped is reneged, abort the
-					 * association
-					 */
-					return;
+					continue;
 				}
-				if ((tp1->sent > SCTP_DATAGRAM_RESEND) &&
-				    (tp1->sent < SCTP_FORWARD_TSN_SKIP)) {
+				if (tp1->sent == SCTP_DATAGRAM_ACKED) {
 					tp1->sent = SCTP_DATAGRAM_SENT;
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
 						sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
@@ -5028,15 +4957,11 @@ done_with_it:
 		}
 		asoc->saw_sack_with_frags = 0;
 	}
-	if (num_seg)
+	if (num_seg || num_nr_seg)
 		asoc->saw_sack_with_frags = 1;
 	else
 		asoc->saw_sack_with_frags = 0;
 
-	/* EY! - not sure about if there should be an IF */
-	if (num_nr_seg > 0)
-		sctp_check_for_nr_revoked(stcb, asoc, cum_ack, biggest_tsn_acked);
-
 	/* 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);
 
@@ -5457,11 +5382,10 @@ sctp_kick_prsctp_reorder_queue(struct sc
 			sctp_ucount_decr(asoc->cnt_on_all_streams);
 			/* deliver it to at least the delivery-q */
 			if (stcb->sctp_socket) {
-				/* EY need the tsn info for calculating nr */
+				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 				sctp_add_to_readq(stcb->sctp_ep, stcb,
 				    ctl,
 				    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
-				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 			}
 		} else {
 			/* no more delivery now. */
@@ -5486,10 +5410,10 @@ sctp_kick_prsctp_reorder_queue(struct sc
 			/* deliver it to at least the delivery-q */
 			strmin->last_sequence_delivered = ctl->sinfo_ssn;
 			if (stcb->sctp_socket) {
+				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 				sctp_add_to_readq(stcb->sctp_ep, stcb,
 				    ctl,
 				    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
-				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
 
 			}
 			tt = strmin->last_sequence_delivered + 1;
@@ -5593,7 +5517,8 @@ sctp_flush_reassm_for_str_seq(struct sct
 
 void
 sctp_handle_forward_tsn(struct sctp_tcb *stcb,
-    struct sctp_forward_tsn_chunk *fwd, int *abort_flag, struct mbuf *m, int offset)
+    struct sctp_forward_tsn_chunk *fwd,
+    int *abort_flag, struct mbuf *m, int offset)
 {
 	/*
 	 * ISSUES that MUST be fixed for ECN! When we are the sender of the
@@ -5619,8 +5544,8 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 	 * report where we are.
 	 */
 	struct sctp_association *asoc;
-	uint32_t new_cum_tsn, gap;
-	unsigned int i, fwd_sz, cumack_set_flag, m_size;
+	uint32_t new_cum_tsn, tsn, gap;
+	unsigned int i, fwd_sz, cumack_set_flag, m_size, fnd = 0;
 	uint32_t str_seq;
 	struct sctp_stream_in *strm;
 	struct sctp_tmit_chunk *chk, *at;
@@ -5657,7 +5582,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 	 * now we know the new TSN is more advanced, let's find the actual
 	 * gap
 	 */
-	SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->nr_mapping_array_base_tsn);
+	SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn);
 	asoc->cumulative_tsn = new_cum_tsn;
 	if (gap >= m_size) {
 		if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) {
@@ -5697,8 +5622,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 		asoc->mapping_array_base_tsn = new_cum_tsn + 1;
 		asoc->highest_tsn_inside_map = new_cum_tsn;
 
-		memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size);
-		asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1;
+		memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
 		asoc->highest_tsn_inside_nr_map = new_cum_tsn;
 
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
@@ -5710,14 +5634,32 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 		for (i = 0; i <= gap; i++) {
 			SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i);
 			SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i);
+			/* FIX ME add something to set up highest TSN in map */
+		}
+		if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+			asoc->highest_tsn_inside_nr_map = new_cum_tsn;
+		}
+		if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map, MAX_TSN) ||
+		    new_cum_tsn == asoc->highest_tsn_inside_map) {
+			/* We must back down to see what the new highest is */
+			for (tsn = new_cum_tsn; (compare_with_wrap(tsn, asoc->mapping_array_base_tsn, MAX_TSN) ||
+			    (tsn == asoc->mapping_array_base_tsn)); tsn--) {
+				SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
+				if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
+					asoc->highest_tsn_inside_map = tsn;
+					fnd = 1;
+					break;
+				}
+			}
+			if (!fnd) {
+				asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1;
+			}
 		}
 		/*
 		 * Now after marking all, slide thing forward but no sack
 		 * please.
 		 */
-		sctp_sack_check(stcb, 0, 0, abort_flag);
-		if (*abort_flag)
-			return;
+		sctp_slide_mapping_arrays(stcb);
 	}
 	/*************************************************************/
 	/* 2. Clear up re-assembly queue                             */

Modified: head/sys/netinet/sctp_indata.h
==============================================================================
--- head/sys/netinet/sctp_indata.h	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_indata.h	Sat Apr  3 15:40:14 2010	(r206137)
@@ -121,7 +121,9 @@ sctp_process_data(struct mbuf **, int, i
     struct sctp_inpcb *, struct sctp_tcb *,
     struct sctp_nets *, uint32_t *);
 
-void sctp_sack_check(struct sctp_tcb *, int, int, int *);
+void sctp_slide_mapping_arrays(struct sctp_tcb *stcb);
+
+void sctp_sack_check(struct sctp_tcb *, int, int *);
 
 #endif
 #endif

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_input.c	Sat Apr  3 15:40:14 2010	(r206137)
@@ -343,11 +343,6 @@ sctp_process_init(struct sctp_init_chunk
 	asoc->str_reset_seq_in = asoc->asconf_seq_in + 1;
 
 	asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
-	/*
-	 * EY 05/13/08 - nr_sack: initialize nr_mapping array's base tsn
-	 * like above
-	 */
-	asoc->nr_mapping_array_base_tsn = ntohl(init->initial_tsn);
 	asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in;
 	asoc->last_echo_tsn = asoc->asconf_seq_in;
 	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
@@ -1862,7 +1857,7 @@ sctp_process_cookie_existing(struct mbuf
 		}
 		if (asoc->nr_mapping_array) {
 			memset(asoc->nr_mapping_array, 0,
-			    asoc->nr_mapping_array_size);
+			    asoc->mapping_array_size);
 		}
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_INP_INFO_WLOCK();
@@ -2027,7 +2022,7 @@ sctp_process_cookie_new(struct mbuf *m, 
 	 * socket is unbound and we must do an implicit bind. Since we are
 	 * getting a cookie, we cannot be unbound.
 	 */
-	stcb = sctp_aloc_assoc(inp, init_src, 0, &error,
+	stcb = sctp_aloc_assoc(inp, init_src, &error,
 	    ntohl(initack_cp->init.initiate_tag), vrf_id,
 	    (struct thread *)NULL
 	    );
@@ -3236,13 +3231,10 @@ process_chunk_drop(struct sctp_tcb *stcb
 		}
 		break;
 	case SCTP_SELECTIVE_ACK:
+	case SCTP_NR_SELECTIVE_ACK:
 		/* resend the sack */
 		sctp_send_sack(stcb);
 		break;
-		/* EY for nr_sacks */
-	case SCTP_NR_SELECTIVE_ACK:
-		sctp_send_nr_sack(stcb);	/* EY resend the nr-sack */
-		break;
 	case SCTP_HEARTBEAT_REQUEST:
 		/* resend a demand HB */
 		if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) {
@@ -3514,8 +3506,7 @@ sctp_handle_stream_reset_response(struct
 					memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
 
 					stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map;
-					stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.mapping_array_base_tsn;
-					memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size);
+					memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
 
 					stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn);
 					stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn;
@@ -3624,8 +3615,7 @@ sctp_handle_str_reset_request_tsn(struct
 		stcb->asoc.mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1;
 		memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
 		stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map;
-		stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1;
-		memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size);
+		memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
 		atomic_add_int(&stcb->asoc.sending_seq, 1);
 		/* save off historical data for retrans */
 		stcb->asoc.last_sending_seq[1] = stcb->asoc.last_sending_seq[0];
@@ -5636,7 +5626,7 @@ sctp_common_input_processing(struct mbuf
 			was_a_gap = 1;
 		}
 		stcb->asoc.send_sack = 1;
-		sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
+		sctp_sack_check(stcb, was_a_gap, &abort_flag);
 		if (abort_flag) {
 			/* Again, we aborted so NO UNLOCK needed */
 			goto out_now;

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c	Sat Apr  3 12:34:32 2010	(r206136)
+++ head/sys/netinet/sctp_output.c	Sat Apr  3 15:40:14 2010	(r206137)
@@ -9003,6 +9003,11 @@ sctp_chunk_retransmission(struct sctp_in
 			/* No, not sent to this net or not ready for rtx */
 			continue;
 		}
+		if (chk->data == NULL) {
+			printf("TSN:%x chk->snd_count:%d chk->sent:%d can't retran - no data\n",
+			    chk->rec.data.TSN_seq, chk->snd_count, chk->sent);
+			continue;
+		}
 		if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) &&
 		    (chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) {
 			/* Gak, we have exceeded max unlucky retran, abort! */
@@ -9426,14 +9431,7 @@ sctp_chunk_output(struct sctp_inpcb *inp
 	 * running, if so piggy-back the sack.
 	 */
 	if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
-		/*
-		 * EY if nr_sacks used then send an nr-sack , a sack
-		 * otherwise
-		 */
-		if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list