Bug 1146096: update usrsctp to rev 9209 from upstream rs=jesup
authorRandell Jesup <rjesup@jesup.org>
Thu, 26 Mar 2015 17:15:43 -0400
changeset 266332 1ee51b896998fa22c14a06d3e97f1a8e159538b4
parent 266331 c297ede37ac5ed5d6f3be298d0355ed3bbc2ab90
child 266333 1d2301ec8a53d88275d759937fb3bd13d96dd607
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1146096
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1146096: update usrsctp to rev 9209 from upstream rs=jesup Pick up build fixes for musl-libc from upstream and a null-deref fix
netwerk/sctp/sctp_update.log
netwerk/sctp/src/netinet/sctp.h
netwerk/sctp/src/netinet/sctp_bsd_addr.c
netwerk/sctp/src/netinet/sctp_cc_functions.c
netwerk/sctp/src/netinet/sctp_indata.c
netwerk/sctp/src/netinet/sctp_input.c
netwerk/sctp/src/netinet/sctp_os_userspace.h
netwerk/sctp/src/netinet/sctp_output.c
netwerk/sctp/src/netinet/sctp_pcb.c
netwerk/sctp/src/netinet/sctp_pcb.h
netwerk/sctp/src/netinet/sctp_peeloff.c
netwerk/sctp/src/netinet/sctp_structs.h
netwerk/sctp/src/netinet/sctp_timer.c
netwerk/sctp/src/netinet/sctp_usrreq.c
netwerk/sctp/src/netinet/sctputil.c
netwerk/sctp/src/user_queue.h
--- a/netwerk/sctp/sctp_update.log
+++ b/netwerk/sctp/sctp_update.log
@@ -10,8 +10,9 @@ sctp updated to version 8131 from SVN on
 sctp updated to version 8165 from SVN on Wed Sep  5 09:39:43 EDT 2012
 sctp updated to version 8176 from SVN on Wed Sep  5 18:02:08 EDT 2012
 sctp updated to version 8263 from SVN on Sun Sep 16 00:48:48 EDT 2012
 sctp updated to version 8279 from SVN on Thu Sep 20 18:19:24 EDT 2012
 sctp updated to version 8397 from SVN on Wed Jan  9 00:41:16 EST 2013
 sctp updated to version 8443 from SVN on Sun Mar 31 09:05:07 EDT 2013
 sctp updated to version 8815 from SVN on Tue Mar  4 08:50:51 EST 2014
 sctp updated to version 9168 from SVN on Tue Mar  3 12:11:40 EST 2015
+sctp updated to version 9209 from SVN on Tue Mar 24 18:11:59 EDT 2015
--- a/netwerk/sctp/src/netinet/sctp.h
+++ b/netwerk/sctp/src/netinet/sctp.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 269945 2014-08-13 15:50:16Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_H_
 #define _NETINET_SCTP_H_
 
 #if (defined(__APPLE__) || defined(__Userspace_os_Linux) || defined(__Userspace_os_Darwin))
 #include <stdint.h>
 #endif
@@ -133,16 +133,17 @@ struct sctp_paramhdr {
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
 #define SCTP_ECN_SUPPORTED              0x00000025
 #define SCTP_PR_SUPPORTED               0x00000026
 #define SCTP_AUTH_SUPPORTED             0x00000027
 #define SCTP_ASCONF_SUPPORTED           0x00000028
 #define SCTP_RECONFIG_SUPPORTED         0x00000029
 #define SCTP_NRSACK_SUPPORTED           0x00000030
 #define SCTP_PKTDROP_SUPPORTED          0x00000031
+#define SCTP_MAX_CWND                   0x00000032
 
 /*
  * read-only options
  */
 #define SCTP_STATUS			0x00000100
 #define SCTP_GET_PEER_ADDR_INFO		0x00000101
 /* authentication support */
 #define SCTP_PEER_AUTH_CHUNKS 		0x00000102
--- a/netwerk/sctp/src/netinet/sctp_bsd_addr.c
+++ b/netwerk/sctp/src/netinet/sctp_bsd_addr.c
@@ -43,24 +43,19 @@
 #include <netinet/sctp_output.h>
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_uio.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_indata.h>
-#if defined(ANDROID)
-#include <unistd.h>
-#include <ifaddrs-android-ext.h>
-#else
 #if defined(__FreeBSD__)
 #include <sys/unistd.h>
 #endif
-#endif
 
 /* Declare all of our malloc named types */
 #ifndef __Panda__
 MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor");
 MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array");
 MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array");
 MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address");
 MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator");
--- a/netwerk/sctp/src/netinet/sctp_cc_functions.c
+++ b/netwerk/sctp/src/netinet/sctp_cc_functions.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 271672 2014-09-16 13:48:46Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -52,16 +52,29 @@
 #include <netinet/sctp_dtrace_declare.h>
 #endif
 
 #define SHIFT_MPTCP_MULTI_N 40
 #define SHIFT_MPTCP_MULTI_Z 16
 #define SHIFT_MPTCP_MULTI 8
 
 static void
+sctp_enforce_cwnd_limit(struct sctp_association *assoc, struct sctp_nets *net)
+{
+	if ((assoc->max_cwnd > 0) &&
+	    (net->cwnd > assoc->max_cwnd) &&
+	    (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
+		net->cwnd = assoc->max_cwnd ;
+		if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
+			net->cwnd = net->mtu - sizeof(struct sctphdr);
+		}
+	}
+}
+
+static void
 sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 	struct sctp_association *assoc;
 	uint32_t cwnd_in_mtu;
 
 	assoc = &stcb->asoc;
 	cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
 	if (cwnd_in_mtu == 0) {
@@ -79,16 +92,17 @@ sctp_set_initial_cc_param(struct sctp_tc
 	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
 	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
 		/* In case of resource pooling initialize appropriately */
 		net->cwnd /= assoc->numnets;
 		if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
 			net->cwnd = net->mtu - sizeof(struct sctphdr);
 		}
 	}
+	sctp_enforce_cwnd_limit(assoc, net);
 	net->ssthresh = assoc->peers_rwnd;
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 	SDT_PROBE(sctp, cwnd, net, init,
 	          stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
 	          0, net->cwnd);
 #endif
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) &
 	    (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
@@ -174,16 +188,17 @@ sctp_cwnd_update_after_fr(struct sctp_tc
 					}
 				} else {
 					net->ssthresh = net->cwnd / 2;
 					if (net->ssthresh < (net->mtu * 2)) {
 						net->ssthresh = 2 * net->mtu;
 					}
 				}
 				net->cwnd = net->ssthresh;
+				sctp_enforce_cwnd_limit(asoc, net);
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 				SDT_PROBE(sctp, cwnd, net, fr,
 					  stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
 					  old_cwnd, net->cwnd);
 #endif
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
 						SCTP_CWND_LOG_FROM_FR);
@@ -295,17 +310,17 @@ cc_bw_same(struct sctp_tcb *stcb SCTP_UN
 					net->cc_mod.rtcc.vol_reduce++;
 				} else {
 					net->cc_mod.rtcc.step_cnt = 0;
 				}
 			}
 		}
 		return (1);
 	}
-	if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
+	if (net->rtt < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
 		/*
 		 * rtt decreased, there could be more room.
 		 * we update both the bw and the rtt here to
 		 * lock this in as a good step down.
 		 */
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 		/* Probe point 6 */
 		probepoint |=  ((6 << 16) | 0);
@@ -456,16 +471,17 @@ cc_bw_decrease(struct sctp_tcb *stcb SCT
 				  probepoint);
 #endif
 			/* Did we voluntarily give up some? if so take
 			 * one back please
 			 */
 			if ((net->cc_mod.rtcc.vol_reduce) &&
 			    (inst_ind != SCTP_INST_GAINING)) {
 				net->cwnd += net->mtu;
+				sctp_enforce_cwnd_limit(&stcb->asoc, net);
 				net->cc_mod.rtcc.vol_reduce--;
 			}
 			net->cc_mod.rtcc.last_step_state = 2;
 			net->cc_mod.rtcc.step_cnt = 0;
 		}
 		goto out_decision;
 	} else  if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
 		/* bw & rtt decreased */
@@ -491,16 +507,17 @@ cc_bw_decrease(struct sctp_tcb *stcb SCT
 				  ((net->cc_mod.rtcc.lbw << 32) | nbw),
 				  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
 				  oth,
 				  probepoint);
 #endif
 			if ((net->cc_mod.rtcc.vol_reduce) &&
 			    (inst_ind != SCTP_INST_GAINING)) {
 				net->cwnd += net->mtu;
+				sctp_enforce_cwnd_limit(&stcb->asoc, net);
 				net->cc_mod.rtcc.vol_reduce--;
 			}
 			net->cc_mod.rtcc.last_step_state = 3;
 			net->cc_mod.rtcc.step_cnt = 0;
 		}
 		goto out_decision;
 	}
 	/* The bw decreased but rtt stayed the same */
@@ -526,16 +543,17 @@ cc_bw_decrease(struct sctp_tcb *stcb SCT
 			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
 			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
 			  oth,
 			  probepoint);
 #endif
 		if ((net->cc_mod.rtcc.vol_reduce) &&
 		    (inst_ind != SCTP_INST_GAINING)) {
 			net->cwnd += net->mtu;
+			sctp_enforce_cwnd_limit(&stcb->asoc, net);
 			net->cc_mod.rtcc.vol_reduce--;
 		}
 		net->cc_mod.rtcc.last_step_state = 4;
 		net->cc_mod.rtcc.step_cnt = 0;
 	}
 out_decision:
 	net->cc_mod.rtcc.lbw = nbw;
 	net->cc_mod.rtcc.lbw_rtt = net->rtt;
@@ -956,16 +974,17 @@ sctp_cwnd_update_after_sack_common(struc
 					default:
 						incr = net->net_ack;
 						if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
 							incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
 						}
 						break;
 					}
 					net->cwnd += incr;
+					sctp_enforce_cwnd_limit(asoc, net);
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 						sctp_log_cwnd(stcb, net, incr,
 						              SCTP_CWND_LOG_FROM_SS);
 					}
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 					SDT_PROBE(sctp, cwnd, net, ack,
 					          stcb->asoc.my_vtag,
 					          ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
@@ -1023,16 +1042,17 @@ sctp_cwnd_update_after_sack_common(struc
 							incr = net->mtu;
 						}
 						break;
 					default:
 						incr = net->mtu;
 						break;
 					}
 					net->cwnd += incr;
+					sctp_enforce_cwnd_limit(asoc, net);
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 					SDT_PROBE(sctp, cwnd, net, ack,
 						  stcb->asoc.my_vtag,
 						  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
 						  net,
 						  old_cwnd, net->cwnd);
 #endif
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
@@ -1310,17 +1330,17 @@ sctp_cwnd_update_after_packet_dropped(st
 	if (net->cwnd > bw_avail) {
 		/* We can't exceed the pipe size */
 		net->cwnd = bw_avail;
 	}
 	if (net->cwnd < net->mtu) {
 		/* We always have 1 MTU */
 		net->cwnd = net->mtu;
 	}
-
+	sctp_enforce_cwnd_limit(&stcb->asoc, net);
 	if (net->cwnd - old_cwnd != 0) {
 		/* log only changes */
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 		SDT_PROBE(sctp, cwnd, net, pd,
 			  stcb->asoc.my_vtag,
 			  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
 			  net,
 			  old_cwnd, net->cwnd);
@@ -1337,16 +1357,17 @@ sctp_cwnd_update_after_output(struct sct
 			      struct sctp_nets *net, int burst_limit)
 {
 	int old_cwnd = net->cwnd;
 
 	if (net->ssthresh < net->cwnd)
 		net->ssthresh = net->cwnd;
 	if (burst_limit) {
 		net->cwnd = (net->flight_size + (burst_limit * net->mtu));
+		sctp_enforce_cwnd_limit(&stcb->asoc, net);
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 		SDT_PROBE(sctp, cwnd, net, bl,
 			  stcb->asoc.my_vtag,
 			  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
 			  net,
 			  old_cwnd, net->cwnd);
 #endif
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
@@ -1676,46 +1697,42 @@ struct sctp_hs_raise_drop sctp_cwnd_adju
 	{89053, 72, 10},	/* 71  */
 	{94717, 73, 9}		/* 72  */
 };
 
 static void
 sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 	int cur_val, i, indx, incr;
+	int old_cwnd = net->cwnd;
 
 	cur_val = net->cwnd >> 10;
 	indx = SCTP_HS_TABLE_SIZE - 1;
 
 	if (cur_val < sctp_cwnd_adjust[0].cwnd) {
 		/* normal mode */
 		if (net->net_ack > net->mtu) {
 			net->cwnd += net->mtu;
-			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
-				sctp_log_cwnd(stcb, net, net->mtu, SCTP_CWND_LOG_FROM_SS);
-			}
 		} else {
 			net->cwnd += net->net_ack;
-			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
-				sctp_log_cwnd(stcb, net, net->net_ack, SCTP_CWND_LOG_FROM_SS);
-			}
 		}
 	} else {
 		for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
 			if (cur_val < sctp_cwnd_adjust[i].cwnd) {
 				indx = i;
 				break;
 			}
 		}
 		net->last_hs_used = indx;
 		incr = ((sctp_cwnd_adjust[indx].increase) << 10);
 		net->cwnd += incr;
-		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
-			sctp_log_cwnd(stcb, net, incr, SCTP_CWND_LOG_FROM_SS);
-		}
+	}
+	sctp_enforce_cwnd_limit(&stcb->asoc, net);
+	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+		sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SS);
 	}
 }
 
 static void
 sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 	int cur_val, i, indx;
 	int old_cwnd = net->cwnd;
@@ -1744,16 +1761,17 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *s
 			for (i = indx; i >= 1; i--) {
 				if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
 					break;
 				}
 			}
 			net->last_hs_used = indx;
 		}
 	}
+	sctp_enforce_cwnd_limit(&stcb->asoc, net);
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 		sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
 	}
 }
 
 static void
 sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
                              struct sctp_association *asoc)
@@ -1872,32 +1890,31 @@ sctp_hs_cwnd_update_after_sack(struct sc
 		 * moved.
 		 */
 		if (accum_moved ||
 		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
 			/* If the cumulative ack moved we can proceed */
 			if (net->cwnd <= net->ssthresh) {
 				/* We are in slow start */
 				if (net->flight_size + net->net_ack >= net->cwnd) {
-
 					sctp_hs_cwnd_increase(stcb, net);
-
 				} else {
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
 						sctp_log_cwnd(stcb, net, net->net_ack,
 							SCTP_CWND_LOG_NOADV_SS);
 					}
 				}
 			} else {
 				/* We are in congestion avoidance */
 				net->partial_bytes_acked += net->net_ack;
 				if ((net->flight_size + net->net_ack >= net->cwnd) &&
 				    (net->partial_bytes_acked >= net->cwnd)) {
 					net->partial_bytes_acked -= net->cwnd;
 					net->cwnd += net->mtu;
+					sctp_enforce_cwnd_limit(asoc, net);
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 						sctp_log_cwnd(stcb, net, net->mtu,
 							SCTP_CWND_LOG_FROM_CA);
 					}
 				} else {
 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
 						sctp_log_cwnd(stcb, net, net->net_ack,
 							SCTP_CWND_LOG_NOADV_CA);
@@ -2126,16 +2143,17 @@ htcp_cong_avoid(struct sctp_tcb *stcb, s
 			} else {
 				net->cwnd += net->net_ack;
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 					sctp_log_cwnd(stcb, net, net->net_ack,
 						SCTP_CWND_LOG_FROM_SS);
 				}
 
 			}
+			sctp_enforce_cwnd_limit(&stcb->asoc, net);
 		} else {
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
 				sctp_log_cwnd(stcb, net, net->net_ack,
 					SCTP_CWND_LOG_NOADV_SS);
 			}
 		}
 	} else {
 		measure_rtt(net);
@@ -2146,16 +2164,17 @@ htcp_cong_avoid(struct sctp_tcb *stcb, s
 		/* What is snd_cwnd_cnt?? */
 		if (((net->partial_bytes_acked/net->mtu * net->cc_mod.htcp_ca.alpha) >> 7)*net->mtu >= net->cwnd) {
                         /*-
 			 * Does SCTP have a cwnd clamp?
 			 * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
 			 */
 			net->cwnd += net->mtu;
 			net->partial_bytes_acked = 0;
+			sctp_enforce_cwnd_limit(&stcb->asoc, net);
 			htcp_alpha_update(&net->cc_mod.htcp_ca);
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 				sctp_log_cwnd(stcb, net, net->mtu,
 					SCTP_CWND_LOG_FROM_CA);
 			}
 		} else {
 			net->partial_bytes_acked += net->net_ack;
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -2191,16 +2210,17 @@ static void
 sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 	/*
 	 * We take the max of the burst limit times a MTU or the
 	 * INITIAL_CWND. We then limit this to 4 MTU's of sending.
 	 */
 	net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
 	net->ssthresh = stcb->asoc.peers_rwnd;
+	sctp_enforce_cwnd_limit(&stcb->asoc, net);
 	htcp_init(net);
 
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
 		sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
 	}
 }
 
 static void
@@ -2270,17 +2290,17 @@ sctp_htcp_cwnd_update_after_sack(struct 
 	}
 }
 
 static void
 sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
 		struct sctp_association *asoc)
 {
 	struct sctp_nets *net;
-		/*
+	/*
 	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
 	 * (net->fast_retran_loss_recovery == 0)))
 	 */
 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
 		if ((asoc->fast_retran_loss_recovery == 0) ||
 		    (asoc->sctp_cmt_on_off > 0)) {
 			/* out of a RFC2582 Fast recovery window? */
 			if (net->net_ack > 0) {
@@ -2292,16 +2312,17 @@ sctp_htcp_cwnd_update_after_fr(struct sc
 				 */
 				struct sctp_tmit_chunk *lchk;
 				int old_cwnd = net->cwnd;
 
 				/* JRS - reset as if state were changed */
 				htcp_reset(&net->cc_mod.htcp_ca);
 				net->ssthresh = htcp_recalc_ssthresh(net);
 				net->cwnd = net->ssthresh;
+				sctp_enforce_cwnd_limit(asoc, net);
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
 						SCTP_CWND_LOG_FROM_FR);
 				}
 				lchk = TAILQ_FIRST(&asoc->send_queue);
 
 				net->partial_bytes_acked = 0;
 				/* Turn on fast recovery window */
@@ -2370,16 +2391,17 @@ sctp_htcp_cwnd_update_after_ecn_echo(str
 		SCTP_STAT_INCR(sctps_ecnereducedcwnd);
 		net->ssthresh = htcp_recalc_ssthresh(net);
 		if (net->ssthresh < net->mtu) {
 			net->ssthresh = net->mtu;
 			/* here back off the timer as well, to slow us down */
 			net->RTO <<= 1;
 		}
 		net->cwnd = net->ssthresh;
+		sctp_enforce_cwnd_limit(&stcb->asoc, net);
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
 			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
 		}
 	}
 }
 
 struct sctp_cc_functions sctp_cc_functions[] = {
 {
--- a/netwerk/sctp/src/netinet/sctp_indata.c
+++ b/netwerk/sctp/src/netinet/sctp_indata.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 276914 2015-01-10 20:49:57Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 280440 2015-03-24 15:05:36Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -2614,22 +2614,24 @@ sctp_process_segment_range(struct sctp_t
 			/*-
 			 * CMT: CUCv2 algorithm. For each TSN being
 			 * processed from the sent queue, track the
 			 * next expected pseudo-cumack, or
 			 * rtx_pseudo_cumack, if required. Separate
 			 * cumack trackers for first transmissions,
 			 * and retransmissions.
 			 */
-			if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			if ((tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			    (tp1->whoTo->find_pseudo_cumack == 1) &&
 			    (tp1->snd_count == 1)) {
 				tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq;
 				tp1->whoTo->find_pseudo_cumack = 0;
 			}
-			if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			if ((tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			    (tp1->whoTo->find_rtx_pseudo_cumack == 1) &&
 			    (tp1->snd_count > 1)) {
 				tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq;
 				tp1->whoTo->find_rtx_pseudo_cumack = 0;
 			}
 			if (tp1->rec.data.TSN_seq == theTSN) {
 				if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
 					/*-
 					 * must be held until
@@ -3515,17 +3517,17 @@ static void
 sctp_window_probe_recovery(struct sctp_tcb *stcb,
 	                   struct sctp_association *asoc,
 			   struct sctp_tmit_chunk *tp1)
 {
 	tp1->window_probe = 0;
 	if ((tp1->sent >= SCTP_DATAGRAM_ACKED) || (tp1->data == NULL)) {
 		/* TSN's skipped we do NOT move back. */
 		sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD,
-			       tp1->whoTo->flight_size,
+			       tp1->whoTo ? tp1->whoTo->flight_size : 0,
 			       tp1->book_size,
 			       (uintptr_t)tp1->whoTo,
 			       tp1->rec.data.TSN_seq);
 		return;
 	}
 	/* First setup this by shrinking flight */
 	if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
 		(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
--- a/netwerk/sctp/src/netinet/sctp_input.c
+++ b/netwerk/sctp/src/netinet/sctp_input.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 277805 2015-01-27 19:35:38Z delphij $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -2892,16 +2892,17 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			    SCTP_PCB_FLAGS_IN_TCPPOOL |
 			    SCTP_PCB_FLAGS_UNBOUND |
 			    (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
 			    SCTP_PCB_FLAGS_DONT_WAKE);
 			inp->sctp_features = (*inp_p)->sctp_features;
 			inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
 			inp->sctp_socket = so;
 			inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
+			inp->max_cwnd = (*inp_p)->max_cwnd;
 			inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
 			inp->ecn_supported = (*inp_p)->ecn_supported;
 			inp->prsctp_supported = (*inp_p)->prsctp_supported;
 			inp->auth_supported = (*inp_p)->auth_supported;
 			inp->asconf_supported = (*inp_p)->asconf_supported;
 			inp->reconfig_supported = (*inp_p)->reconfig_supported;
 			inp->nrsack_supported = (*inp_p)->nrsack_supported;
 			inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
--- a/netwerk/sctp/src/netinet/sctp_os_userspace.h
+++ b/netwerk/sctp/src/netinet/sctp_os_userspace.h
@@ -268,17 +268,16 @@ typedef char* caddr_t;
 #define LITTLE_ENDIAN 0
 #ifdef WORDS_BIGENDIAN
 #define BYTE_ORDER BIG_ENDIAN
 #else
 #define BYTE_ORDER LITTLE_ENDIAN
 #endif
 
 #else /* !defined(Userspace_os_Windows) */
-#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
 #include <sys/socket.h>
 #if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl)
 #include <pthread.h>
 #endif
 typedef pthread_mutex_t userland_mutex_t;
 typedef pthread_cond_t userland_cond_t;
 typedef pthread_t userland_thread_t;
 #endif
@@ -432,20 +431,20 @@ struct selinfo {int dummy;};
 struct sx {int dummy;};
 #endif
 
 #include <stdio.h>
 #include <string.h>
 /* #include <sys/param.h>  in FreeBSD defines MSIZE */
 /* #include <sys/ktr.h> */
 /* #include <sys/systm.h> */
-#if defined(__Userspace_os_Windows)
+#if defined(HAVE_SYS_QUEUE_H)
+#include <sys/queue.h>
+#else
 #include <user_queue.h>
-#else
-#include <sys/queue.h>
 #endif
 #include <user_malloc.h>
 /* #include <sys/kernel.h> */
 /* #include <sys/sysctl.h> */
 /* #include <sys/protosw.h> */
 /* on FreeBSD, this results in a redefintion of SOCK(BUF)_(UN)LOCK and
  *  uknown type of struct mtx for sb_mtx in struct sockbuf */
 #include "user_socketvar.h" /* MALLOC_DECLARE's M_PCB. Replacement for sys/socketvar.h */
@@ -491,17 +490,17 @@ struct sx {int dummy;};
 #include <user_ip_icmp.h>
 #endif
 /* #include <netinet/in_pcb.h> ported to userspace */
 #include <user_inpcb.h>
 
 /* for getifaddrs */
 #include <sys/types.h>
 #if !defined(__Userspace_os_Windows)
-#if !defined(ANDROID) && (defined(INET) || defined(INET6))
+#if defined(INET) || defined(INET6)
 #include <ifaddrs.h>
 #endif
 
 /* for ioctl */
 #include <sys/ioctl.h>
 
 /* for close, etc. */
 #include <unistd.h>
--- a/netwerk/sctp/src/netinet/sctp_output.c
+++ b/netwerk/sctp/src/netinet/sctp_output.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 277350 2015-01-18 22:00:39Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 280371 2015-03-23 15:12:02Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #ifdef __FreeBSD__
 #include <sys/proc.h>
 #endif
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -9730,18 +9730,16 @@ sctp_send_asconf_ack(struct sctp_tcb *st
 		chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
 		chk->rec.chunk_id.can_take_data = 1;
 		chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
 		chk->whoTo = net;
 		if (chk->whoTo) {
 			atomic_add_int(&chk->whoTo->ref_count, 1);
 		}
 		chk->data = m_ack;
-		chk->send_size = 0;
-		/* Get size */
 		chk->send_size = ack->len;
 		chk->sent = SCTP_DATAGRAM_UNSENT;
 		chk->snd_count = 0;
 		chk->asoc = &stcb->asoc;
 
 		TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
 		chk->asoc->ctrl_queue_cnt++;
 	}
--- a/netwerk/sctp/src/netinet/sctp_pcb.c
+++ b/netwerk/sctp/src/netinet/sctp_pcb.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 277031 2015-01-11 21:55:30Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 280459 2015-03-24 21:12:45Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #ifdef __FreeBSD__
 #include <sys/proc.h>
 #endif
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -66,16 +66,19 @@
 #endif
 #if defined(__FreeBSD__)
 #include <sys/sched.h>
 #include <sys/smp.h>
 #include <sys/unistd.h>
 #endif
 #if defined(__Userspace__)
 #include <user_socketvar.h>
+#if !defined(__Userspace_os_Windows)
+#include <netdb.h>
+#endif
 #endif
 
 #if defined(__APPLE__)
 #define APPLE_FILE_NO 4
 #endif
 
 #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
 VNET_DEFINE(struct sctp_base_info, system_base_info);
@@ -2196,30 +2199,31 @@ sctp_isport_inuse(struct sctp_inpcb *inp
 }
 
 
 int
 sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp)
 {
 	/* For 1-2-1 with port reuse */
 	struct sctppcbhead *head;
-	struct sctp_inpcb *tinp;
+	struct sctp_inpcb *tinp, *ninp;
 
 	if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
 		/* only works with port reuse on */
 		return (-1);
 	}
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) {
 		return (0);
 	}
 	SCTP_INP_RUNLOCK(inp);
+	SCTP_INP_INFO_WLOCK();
 	head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport,
 	                                    SCTP_BASE_INFO(hashmark))];
 	/* Kick out all non-listeners to the TCP hash */
-	LIST_FOREACH(tinp, head, sctp_hash) {
+	LIST_FOREACH_SAFE(tinp, head, sctp_hash, ninp) {
 		if (tinp->sctp_lport != inp->sctp_lport) {
 			continue;
 		}
 		if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
 			continue;
 		}
 		if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
 			continue;
@@ -2237,16 +2241,17 @@ sctp_swap_inpcb_for_listen(struct sctp_i
 	SCTP_INP_WLOCK(inp);
 	/* Pull from where he was */
 	LIST_REMOVE(inp, sctp_hash);
 	inp->sctp_flags &= ~SCTP_PCB_FLAGS_IN_TCPPOOL;
 	head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, SCTP_BASE_INFO(hashmark))];
 	LIST_INSERT_HEAD(head, inp, sctp_hash);
 	SCTP_INP_WUNLOCK(inp);
 	SCTP_INP_RLOCK(inp);
+	SCTP_INP_INFO_WUNLOCK();
 	return (0);
 }
 
 
 struct sctp_inpcb *
 sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock,
 		uint32_t vrf_id)
 {
@@ -2827,16 +2832,17 @@ sctp_inpcb_alloc(struct socket *so, uint
 			inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY;
 		}
 	}
 #endif
 #endif
 	inp->sctp_associd_counter = 1;
 	inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
 	inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
+	inp->max_cwnd = 0;
 	inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
 	inp->ecn_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_ecn_enable);
 	inp->prsctp_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pr_enable);
 	inp->auth_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_auth_enable);
 	inp->asconf_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_asconf_enable);
 	inp->reconfig_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_reconfig_enable);
 	inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable);
 	inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
--- a/netwerk/sctp/src/netinet/sctp_pcb.h
+++ b/netwerk/sctp/src/netinet/sctp_pcb.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 275427 2014-12-02 20:29:29Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_PCB_H_
 #define _NETINET_SCTP_PCB_H_
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp.h>
 #include <netinet/sctp_constants.h>
@@ -473,16 +473,17 @@ struct sctp_inpcb {
 	struct sctpasochead sctp_asoc_list;
 #ifdef SCTP_TRACK_FREED_ASOCS
 	struct sctpasochead sctp_asoc_free_list;
 #endif
 	struct sctp_iterator *inp_starting_point_for_iterator;
 	uint32_t sctp_frag_point;
 	uint32_t partial_delivery_point;
 	uint32_t sctp_context;
+	uint32_t max_cwnd;
 	uint8_t local_strreset_support;
 	uint32_t sctp_cmt_on_off;
 	uint8_t ecn_supported;
 	uint8_t prsctp_supported;
 	uint8_t auth_supported;
 	uint8_t asconf_supported;
 	uint8_t reconfig_supported;
 	uint8_t nrsack_supported;
--- a/netwerk/sctp/src/netinet/sctp_peeloff.c
+++ b/netwerk/sctp/src/netinet/sctp_peeloff.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 269858 2014-08-12 11:30:16Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -129,16 +129,17 @@ sctp_do_peeloff(struct socket *head, str
 	n_inp->prsctp_supported = inp->prsctp_supported;
 	n_inp->auth_supported = inp->auth_supported;
 	n_inp->asconf_supported = inp->asconf_supported;
 	n_inp->reconfig_supported = inp->reconfig_supported;
 	n_inp->nrsack_supported = inp->nrsack_supported;
 	n_inp->pktdrop_supported = inp->pktdrop_supported;
 	n_inp->partial_delivery_point = inp->partial_delivery_point;
 	n_inp->sctp_context = inp->sctp_context;
+	n_inp->max_cwnd = inp->max_cwnd;
 	n_inp->local_strreset_support = inp->local_strreset_support;
 	n_inp->inp_starting_point_for_iterator = NULL;
 	/* copy in the authentication parameters from the original endpoint */
 	if (n_inp->sctp_ep.local_hmacs)
 		sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
 	n_inp->sctp_ep.local_hmacs =
 	    sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
 	if (n_inp->sctp_ep.local_auth_chunks)
@@ -244,16 +245,17 @@ sctp_get_peeloff(struct socket *head, sc
 	n_inp->prsctp_supported = inp->prsctp_supported;
 	n_inp->auth_supported = inp->auth_supported;
 	n_inp->asconf_supported = inp->asconf_supported;
 	n_inp->reconfig_supported = inp->reconfig_supported;
 	n_inp->nrsack_supported = inp->nrsack_supported;
 	n_inp->pktdrop_supported = inp->pktdrop_supported;
 	n_inp->partial_delivery_point = inp->partial_delivery_point;
 	n_inp->sctp_context = inp->sctp_context;
+	n_inp->max_cwnd = inp->max_cwnd;
 	n_inp->local_strreset_support = inp->local_strreset_support;
 	n_inp->inp_starting_point_for_iterator = NULL;
 #if defined(__Userspace__)
 	n_inp->ulp_info = inp->ulp_info;
 	n_inp->recv_callback = inp->recv_callback;
 	n_inp->send_callback = inp->send_callback;
 	n_inp->send_sb_threshold = inp->send_sb_threshold;
 #endif
--- a/netwerk/sctp/src/netinet/sctp_structs.h
+++ b/netwerk/sctp/src/netinet/sctp_structs.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 275483 2014-12-04 21:17:50Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 279859 2015-03-10 19:49:25Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_STRUCTS_H_
 #define _NETINET_SCTP_STRUCTS_H_
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctp_auth.h>
@@ -1244,16 +1244,17 @@ struct sctp_association {
 	uint8_t cmt_dac_pkts_rcvd;
 	uint8_t sctp_cmt_on_off;
 	uint8_t iam_blocking;
 	uint8_t cookie_how[8];
 	/* JRS 5/21/07 - CMT PF variable */
 	uint8_t sctp_cmt_pf;
 	uint8_t use_precise_time;
 	uint64_t sctp_features;
+	uint32_t max_cwnd;
 	uint16_t port; /* remote UDP encapsulation port */
 	/*
 	 * The mapping array is used to track out of order sequences above
 	 * last_acked_seq. 0 indicates packet missing 1 indicates packet
 	 * rec'd. We slide it up every time we raise last_acked_seq and 0
 	 * trailing locactions out.  If I get a TSN above the array
 	 * mappingArraySz, I discard the datagram and let retransmit happen.
 	 */
--- a/netwerk/sctp/src/netinet/sctp_timer.c
+++ b/netwerk/sctp/src/netinet/sctp_timer.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 277380 2015-01-19 11:52:08Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 279841 2015-03-10 09:16:31Z tuexen $");
 #endif
 
 #define _IP_VHL
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_pcb.h>
 #ifdef INET6
 #if defined(__Userspace_os_FreeBSD)
 #include <netinet6/sctp6_var.h>
@@ -157,17 +157,17 @@ sctp_threshold_management(struct sctp_in
 	 * We specifically do not do >= to give the assoc one more change
 	 * before we fail it.
 	 */
 	if (stcb->asoc.overall_error_count > threshold) {
 		/* Abort notification sends a ULP notify */
 		struct mbuf *op_err;
 
 		op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
-		                             "Association error couter exceeded");
+		                             "Association error counter exceeded");
 		inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_1;
 		sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
 		return (1);
 	}
 	return (0);
 }
 
 /*
--- a/netwerk/sctp/src/netinet/sctp_usrreq.c
+++ b/netwerk/sctp/src/netinet/sctp_usrreq.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 277815 2015-01-27 21:30:24Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 280459 2015-03-24 21:12:45Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #ifdef __FreeBSD__
 #include <sys/proc.h>
 #endif
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
@@ -290,31 +290,29 @@ sctp_pathmtu_adjustment(struct sctp_tcb 
 			/*
 			 * For this guy we also mark for immediate resend
 			 * since we sent to big of chunk
 			 */
 			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
 			if (chk->sent < SCTP_DATAGRAM_RESEND) {
 				sctp_flight_size_decrease(chk);
 				sctp_total_flight_decrease(stcb, chk);
-			}
-			if (chk->sent != SCTP_DATAGRAM_RESEND) {
+				chk->sent = SCTP_DATAGRAM_RESEND;
 				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
-			}
-			chk->sent = SCTP_DATAGRAM_RESEND;
-			chk->rec.data.doing_fast_retransmit = 0;
-			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
-				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
-					       chk->whoTo->flight_size,
-					       chk->book_size,
-					       (uintptr_t)chk->whoTo,
-					       chk->rec.data.TSN_seq);
-			}
-			/* Clear any time so NO RTT is being done */
-			chk->do_rtt = 0;
+				chk->rec.data.doing_fast_retransmit = 0;
+				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
+					sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
+						       chk->whoTo->flight_size,
+						       chk->book_size,
+						       (uintptr_t)chk->whoTo,
+						       chk->rec.data.TSN_seq);
+				}
+				/* Clear any time so NO RTT is being done */
+				chk->do_rtt = 0;
+			}
 		}
 	}
 }
 
 #ifdef INET
 #if !defined(__Userspace__)
 #if defined(__Panda__) || defined(__Windows__)
 void
@@ -4383,16 +4381,43 @@ sctp_getopt(struct socket *so, int optna
 			SCTP_TCB_UNLOCK(stcb);
 			*optsize = sizeof(struct sctp_prstatus);
 		} else {
 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
 			error = EINVAL;
 		}
 		break;
 	}
+	case SCTP_MAX_CWND:
+	{
+		struct sctp_assoc_value *av;
+
+		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+		if (stcb) {
+			av->assoc_value = stcb->asoc.max_cwnd;
+			SCTP_TCB_UNLOCK(stcb);
+		} else {
+			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+				SCTP_INP_RLOCK(inp);
+				av->assoc_value = inp->max_cwnd;
+				SCTP_INP_RUNLOCK(inp);
+			} else {
+				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+				error = EINVAL;
+			}
+		}
+		if (error == 0) {
+			*optsize = sizeof(struct sctp_assoc_value);
+		}
+		break;
+	}
 	default:
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
 		error = ENOPROTOOPT;
 		break;
 	} /* end switch (sopt->sopt_name) */
 	if (error) {
 		*optsize = 0;
 	}
@@ -7032,76 +7057,77 @@ sctp_setopt(struct socket *so, int optna
 				error = EAFNOSUPPORT;
 				SCTP_TCB_UNLOCK(stcb);
 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
 				break;
 			}
 		}
 		if (stcb != NULL) {
 			if (net != NULL) {
+				net->failure_threshold = thlds->spt_pathmaxrxt;
+				net->pf_threshold = thlds->spt_pathpfthld;
 				if (net->dest_state & SCTP_ADDR_PF) {
-					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
-					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
+					if ((net->error_count > net->failure_threshold) ||
+					    (net->error_count <= net->pf_threshold)) {
 						net->dest_state &= ~SCTP_ADDR_PF;
 					}
 				} else {
-					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
-					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+					if ((net->error_count > net->pf_threshold) &&
+					    (net->error_count <= net->failure_threshold)) {
 						net->dest_state |= SCTP_ADDR_PF;
 						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
 						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
 					}
 				}
 				if (net->dest_state & SCTP_ADDR_REACHABLE) {
-					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+					if (net->error_count > net->failure_threshold) {
 						net->dest_state &= ~SCTP_ADDR_REACHABLE;
 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
 					}
 				} else {
-					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+					if (net->error_count <= net->failure_threshold) {
 						net->dest_state |= SCTP_ADDR_REACHABLE;
 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
 					}
 				}
-				net->failure_threshold = thlds->spt_pathmaxrxt;
-				net->pf_threshold = thlds->spt_pathpfthld;
 			} else {
 				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+					net->failure_threshold = thlds->spt_pathmaxrxt;
+					net->pf_threshold = thlds->spt_pathpfthld;
 					if (net->dest_state & SCTP_ADDR_PF) {
-						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
-						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
+						if ((net->error_count > net->failure_threshold) ||
+						    (net->error_count <= net->pf_threshold)) {
 							net->dest_state &= ~SCTP_ADDR_PF;
 						}
 					} else {
-						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
-						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+						if ((net->error_count > net->pf_threshold) &&
+						    (net->error_count <= net->failure_threshold)) {
 							net->dest_state |= SCTP_ADDR_PF;
 							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
 							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
 							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
 						}
 					}
 					if (net->dest_state & SCTP_ADDR_REACHABLE) {
-						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+						if (net->error_count > net->failure_threshold) {
 							net->dest_state &= ~SCTP_ADDR_REACHABLE;
 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
 						}
 					} else {
-						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+						if (net->error_count <= net->failure_threshold) {
 							net->dest_state |= SCTP_ADDR_REACHABLE;
 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
 						}
 					}
-					net->failure_threshold = thlds->spt_pathmaxrxt;
-					net->pf_threshold = thlds->spt_pathpfthld;
 				}
 				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
 				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
 			}
+			SCTP_TCB_UNLOCK(stcb);
 		} else {
 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
 			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
 				SCTP_INP_WLOCK(inp);
 				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
 				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
 				SCTP_INP_WUNLOCK(inp);
@@ -7444,16 +7470,52 @@ sctp_setopt(struct socket *so, int optna
 				SCTP_INP_WUNLOCK(inp);
 			} else {
 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
 				error = EINVAL;
 			}
 		}
 		break;
 	}
+	case SCTP_MAX_CWND:
+	{
+		struct sctp_assoc_value *av;
+		struct sctp_nets *net;
+
+		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+		if (stcb) {
+			stcb->asoc.max_cwnd = av->assoc_value;
+			if (stcb->asoc.max_cwnd > 0) {
+				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+					if ((net->cwnd > stcb->asoc.max_cwnd) &&
+					    (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
+						net->cwnd = stcb->asoc.max_cwnd;
+						if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
+							net->cwnd = net->mtu - sizeof(struct sctphdr);
+						}
+					}
+				}
+			}
+			SCTP_TCB_UNLOCK(stcb);
+		} else {
+			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+				SCTP_INP_WLOCK(inp);
+				inp->max_cwnd = av->assoc_value;
+				SCTP_INP_WUNLOCK(inp);
+			} else {
+				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+				error = EINVAL;
+			}
+		}
+		break;
+	}
 	default:
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
 		error = ENOPROTOOPT;
 		break;
 	} /* end switch (opt) */
 	return (error);
 }
 
@@ -8042,54 +8104,53 @@ sctp_listen(struct socket *so, struct pr
 #ifdef SCTP_LOCK_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
 		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
 	}
 #endif
 	SOCK_LOCK(so);
 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
 	error = solisten_proto_check(so);
+	SOCK_UNLOCK(so);
 	if (error) {
-		SOCK_UNLOCK(so);
 		SCTP_INP_RUNLOCK(inp);
 		return (error);
 	}
 #endif
 	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
 		/* The unlucky case
 		 * - We are in the tcp pool with this guy.
 		 * - Someone else is in the main inp slot.
 		 * - We must move this guy (the listener) to the main slot
 		 * - We must then move the guy that was listener to the TCP Pool.
 		 */
 		if (sctp_swap_inpcb_for_listen(inp)) {
-			goto in_use;
+			SCTP_INP_RUNLOCK(inp);
+			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
+			return (EADDRINUSE);
 		}
 	}
 
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
 		/* We are already connected AND the TCP model */
-	in_use:
 		SCTP_INP_RUNLOCK(inp);
-		SOCK_UNLOCK(so);
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
 		return (EADDRINUSE);
 	}
 	SCTP_INP_RUNLOCK(inp);
 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
 		/* We must do a bind. */
-		SOCK_UNLOCK(so);
 		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
 			/* bind error, probably perm */
 			return (error);
 		}
-		SOCK_LOCK(so);
-	}
+	}
+	SOCK_LOCK(so);
 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
 	/* It appears for 7.0 and on, we must always call this. */
 	solisten_proto(so, backlog);
 #else
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
 		solisten_proto(so);
 	}
--- a/netwerk/sctp/src/netinet/sctputil.c
+++ b/netwerk/sctp/src/netinet/sctputil.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 277049 2015-01-12 07:39:52Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 280439 2015-03-24 14:51:46Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #ifdef INET6
@@ -995,16 +995,17 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
 	asoc->asconf_supported = inp->asconf_supported;
 	asoc->reconfig_supported = inp->reconfig_supported;
 	asoc->nrsack_supported = inp->nrsack_supported;
 	asoc->pktdrop_supported = inp->pktdrop_supported;
 	asoc->sctp_cmt_pf = (uint8_t)0;
 	asoc->sctp_frag_point = inp->sctp_frag_point;
 	asoc->sctp_features = inp->sctp_features;
 	asoc->default_dscp = inp->sctp_ep.default_dscp;
+	asoc->max_cwnd = inp->max_cwnd;
 #ifdef INET6
 	if (inp->sctp_ep.default_flowlabel) {
 		asoc->default_flowlabel = inp->sctp_ep.default_flowlabel;
 	} else {
 		if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
 			asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep);
 			asoc->default_flowlabel &= 0x000fffff;
 			asoc->default_flowlabel |= 0x80000000;
@@ -2858,17 +2859,21 @@ set_error:
 	if (!so_locked) {
 		SCTP_SOCKET_UNLOCK(so, 1);
 	}
 #endif
 }
 
 static void
 sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
-    struct sockaddr *sa, uint32_t error)
+    struct sockaddr *sa, uint32_t error, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+    SCTP_UNUSED
+#endif
+)
 {
 	struct mbuf *m_notify;
 	struct sctp_paddr_change *spc;
 	struct sctp_queued_to_read *control;
 
 	if ((stcb == NULL) ||
 	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
 		/* event not enabled */
@@ -2954,17 +2959,17 @@ sctp_notify_peer_addr_change(struct sctp
 	control->length = SCTP_BUF_LEN(m_notify);
 	control->spec_flags = M_NOTIFICATION;
 	/* not that we need this */
 	control->tail_mbuf = m_notify;
 	sctp_add_to_readq(stcb->sctp_ep, stcb,
 	                  control,
 	                  &stcb->sctp_socket->so_rcv, 1,
 	                  SCTP_READ_LOCK_NOT_HELD,
-	                  SCTP_SO_NOT_LOCKED);
+	                  so_locked);
 }
 
 
 static void
 sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
     struct sctp_tmit_chunk *chk, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
@@ -3752,35 +3757,35 @@ sctp_ulp_notify(uint32_t notification, s
 #endif
 		break;
 	case SCTP_NOTIFY_INTERFACE_DOWN:
 		{
 			struct sctp_nets *net;
 
 			net = (struct sctp_nets *)data;
 			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
-			    (struct sockaddr *)&net->ro._l_addr, error);
+			    (struct sockaddr *)&net->ro._l_addr, error, so_locked);
 			break;
 		}
 	case SCTP_NOTIFY_INTERFACE_UP:
 		{
 			struct sctp_nets *net;
 
 			net = (struct sctp_nets *)data;
 			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
-			    (struct sockaddr *)&net->ro._l_addr, error);
+			    (struct sockaddr *)&net->ro._l_addr, error, so_locked);
 			break;
 		}
 	case SCTP_NOTIFY_INTERFACE_CONFIRMED:
 		{
 			struct sctp_nets *net;
 
 			net = (struct sctp_nets *)data;
 			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
-			    (struct sockaddr *)&net->ro._l_addr, error);
+			    (struct sockaddr *)&net->ro._l_addr, error, so_locked);
 			break;
 		}
 	case SCTP_NOTIFY_SPECIAL_SP_FAIL:
 		sctp_notify_send_failed2(stcb, error,
 		                         (struct sctp_stream_queue_pending *)data, so_locked);
 		break;
 	case SCTP_NOTIFY_SENT_DG_FAIL:
 		sctp_notify_send_failed(stcb, 1, error,
@@ -3840,25 +3845,25 @@ sctp_ulp_notify(uint32_t notification, s
 		                         (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED));
 		break;
 	case SCTP_NOTIFY_STR_RESET_DENIED_IN:
 		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
 		                         (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_DENIED));
 		break;
 	case SCTP_NOTIFY_ASCONF_ADD_IP:
 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
-		    error);
+		    error, so_locked);
 		break;
 	case SCTP_NOTIFY_ASCONF_DELETE_IP:
 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
-		                             error);
+		                             error, so_locked);
 		break;
 	case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
-		                             error);
+		                             error, so_locked);
 		break;
 	case SCTP_NOTIFY_PEER_SHUTDOWN:
 		sctp_notify_shutdown_event(stcb);
 		break;
 	case SCTP_NOTIFY_AUTH_NEW_KEY:
 		sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
 		                           (uint16_t)(uintptr_t)data,
 		                           so_locked);
@@ -5332,27 +5337,23 @@ sctp_release_pr_sctp_chunk(struct sctp_t
 				chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
 				chk->sent = SCTP_FORWARD_TSN_SKIP;
 				chk->asoc = &stcb->asoc;
 				chk->rec.data.stream_seq = strq->next_sequence_send;
 				chk->rec.data.stream_number = sp->stream;
 				chk->rec.data.payloadtype = sp->ppid;
 				chk->rec.data.context = sp->context;
 				chk->flags = sp->act_flags;
-				if (sp->net)
-					chk->whoTo = sp->net;
-				else
-					chk->whoTo = stcb->asoc.primary_destination;
-				atomic_add_int(&chk->whoTo->ref_count, 1);
+				chk->whoTo = NULL;
 #if defined(__FreeBSD__) || defined(__Panda__)
 				chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
 #else
 				chk->rec.data.TSN_seq = stcb->asoc.sending_seq++;
 #endif
-				stcb->asoc.pr_sctp_cnt++;
+				strq->chunks_on_queues++;
 				TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
 				stcb->asoc.sent_queue_cnt++;
 				stcb->asoc.pr_sctp_cnt++;
 			} else {
 				chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
 			}
 			strq->next_sequence_send++;
 		oh_well:
--- a/netwerk/sctp/src/user_queue.h
+++ b/netwerk/sctp/src/user_queue.h
@@ -26,19 +26,16 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  */
 
 #ifndef _USER_QUEUE_H_
 #define	_USER_QUEUE_H_
 
-#if !defined (__Userspace_os_Windows)
-#include <sys/cdefs.h>
-#endif
 /*
  * This file defines four types of data structures: singly-linked lists,
  * singly-linked tail queues, lists and tail queues.
  *
  * A singly-linked list is headed by a single forward pointer. The elements
  * are singly linked for minimum space and pointer manipulation overhead at
  * the expense of O(n) removal for arbitrary elements. New elements can be
  * added to the list after an existing element or at the head of the list.