Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 May 2015 12:54:31 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r283724 - in stable/10: lib/libc/net sys/netinet
Message-ID:  <201505291254.t4TCsVEX042831@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Fri May 29 12:54:30 2015
New Revision: 283724
URL: https://svnweb.freebsd.org/changeset/base/283724

Log:
  MFC r279859:
  
  Add a SCTP socket option to limit the cwnd for each path.

Modified:
  stable/10/lib/libc/net/sctp_sys_calls.c
  stable/10/sys/netinet/sctp.h
  stable/10/sys/netinet/sctp_cc_functions.c
  stable/10/sys/netinet/sctp_input.c
  stable/10/sys/netinet/sctp_pcb.c
  stable/10/sys/netinet/sctp_pcb.h
  stable/10/sys/netinet/sctp_peeloff.c
  stable/10/sys/netinet/sctp_structs.h
  stable/10/sys/netinet/sctp_usrreq.c
  stable/10/sys/netinet/sctputil.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/sctp_sys_calls.c
==============================================================================
--- stable/10/lib/libc/net/sctp_sys_calls.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/lib/libc/net/sctp_sys_calls.c	Fri May 29 12:54:30 2015	(r283724)
@@ -383,6 +383,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
 	case SCTP_PR_ASSOC_STATUS:
 		((struct sctp_prstatus *)arg)->sprstat_assoc_id = id;
 		break;
+	case SCTP_MAX_CWND:
+		((struct sctp_assoc_value *)arg)->assoc_id = id;
+		break;
 	default:
 		break;
 	}

Modified: stable/10/sys/netinet/sctp.h
==============================================================================
--- stable/10/sys/netinet/sctp.h	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp.h	Fri May 29 12:54:30 2015	(r283724)
@@ -128,6 +128,7 @@ struct sctp_paramhdr {
 #define SCTP_RECONFIG_SUPPORTED         0x00000029
 #define SCTP_NRSACK_SUPPORTED           0x00000030
 #define SCTP_PKTDROP_SUPPORTED          0x00000031
+#define SCTP_MAX_CWND                   0x00000032
 
 /*
  * read-only options

Modified: stable/10/sys/netinet/sctp_cc_functions.c
==============================================================================
--- stable/10/sys/netinet/sctp_cc_functions.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_cc_functions.c	Fri May 29 12:54:30 2015	(r283724)
@@ -53,6 +53,19 @@ __FBSDID("$FreeBSD$");
 #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;
@@ -80,6 +93,7 @@ sctp_set_initial_cc_param(struct sctp_tc
 			net->cwnd = net->mtu - sizeof(struct sctphdr);
 		}
 	}
+	sctp_enforce_cwnd_limit(assoc, net);
 	net->ssthresh = assoc->peers_rwnd;
 	SDT_PROBE(sctp, cwnd, net, init,
 	    stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
@@ -178,6 +192,7 @@ sctp_cwnd_update_after_fr(struct sctp_tc
 					}
 				}
 				net->cwnd = net->ssthresh;
+				sctp_enforce_cwnd_limit(asoc, net);
 				SDT_PROBE(sctp, cwnd, net, fr,
 				    stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
 				    old_cwnd, net->cwnd);
@@ -426,6 +441,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, st
 			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;
@@ -457,6 +473,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, st
 			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;
@@ -488,6 +505,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, st
 		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;
@@ -882,6 +900,7 @@ sctp_cwnd_update_after_sack_common(struc
 						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);
@@ -948,6 +967,7 @@ sctp_cwnd_update_after_sack_common(struc
 						break;
 					}
 					net->cwnd += incr;
+					sctp_enforce_cwnd_limit(asoc, net);
 					SDT_PROBE(sctp, cwnd, net, ack,
 					    stcb->asoc.my_vtag,
 					    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
@@ -1227,6 +1247,7 @@ sctp_cwnd_update_after_packet_dropped(st
 		/* 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 */
 		SDT_PROBE(sctp, cwnd, net, pd,
@@ -1251,6 +1272,7 @@ sctp_cwnd_update_after_output(struct sct
 		net->ssthresh = net->cwnd;
 	if (burst_limit) {
 		net->cwnd = (net->flight_size + (burst_limit * net->mtu));
+		sctp_enforce_cwnd_limit(&stcb->asoc, net);
 		SDT_PROBE(sctp, cwnd, net, bl,
 		    stcb->asoc.my_vtag,
 		    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
@@ -1589,6 +1611,7 @@ 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;
@@ -1597,14 +1620,8 @@ sctp_hs_cwnd_increase(struct sctp_tcb *s
 		/* 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++) {
@@ -1616,9 +1633,10 @@ sctp_hs_cwnd_increase(struct sctp_tcb *s
 		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);
 	}
 }
 
@@ -1657,6 +1675,7 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *s
 			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);
 	}
@@ -1788,9 +1807,7 @@ sctp_hs_cwnd_update_after_sack(struct sc
 			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,
@@ -1804,6 +1821,7 @@ sctp_hs_cwnd_update_after_sack(struct sc
 				    (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);
@@ -2042,6 +2060,7 @@ htcp_cong_avoid(struct sctp_tcb *stcb, s
 					    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,
@@ -2063,6 +2082,7 @@ htcp_cong_avoid(struct sctp_tcb *stcb, s
 			 */
 			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,
@@ -2109,6 +2129,7 @@ sctp_htcp_set_initial_cc_param(struct sc
 	 */
 	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)) {
@@ -2212,6 +2233,7 @@ sctp_htcp_cwnd_update_after_fr(struct sc
 				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);
@@ -2291,6 +2313,7 @@ sctp_htcp_cwnd_update_after_ecn_echo(str
 			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);
 		}

Modified: stable/10/sys/netinet/sctp_input.c
==============================================================================
--- stable/10/sys/netinet/sctp_input.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_input.c	Fri May 29 12:54:30 2015	(r283724)
@@ -2763,6 +2763,7 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			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;

Modified: stable/10/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_pcb.c	Fri May 29 12:54:30 2015	(r283724)
@@ -2474,6 +2474,7 @@ sctp_inpcb_alloc(struct socket *so, uint
 	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);

Modified: stable/10/sys/netinet/sctp_pcb.h
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.h	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_pcb.h	Fri May 29 12:54:30 2015	(r283724)
@@ -404,6 +404,7 @@ struct sctp_inpcb {
 	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;

Modified: stable/10/sys/netinet/sctp_peeloff.c
==============================================================================
--- stable/10/sys/netinet/sctp_peeloff.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_peeloff.c	Fri May 29 12:54:30 2015	(r283724)
@@ -127,6 +127,7 @@ sctp_do_peeloff(struct socket *head, str
 	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 */

Modified: stable/10/sys/netinet/sctp_structs.h
==============================================================================
--- stable/10/sys/netinet/sctp_structs.h	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_structs.h	Fri May 29 12:54:30 2015	(r283724)
@@ -1199,6 +1199,7 @@ struct sctp_association {
 	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

Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctp_usrreq.c	Fri May 29 12:54:30 2015	(r283724)
@@ -3694,6 +3694,33 @@ flags_out:
 			}
 			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;
@@ -6572,6 +6599,42 @@ sctp_setopt(struct socket *so, int optna
 			}
 			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;

Modified: stable/10/sys/netinet/sctputil.c
==============================================================================
--- stable/10/sys/netinet/sctputil.c	Fri May 29 12:50:53 2015	(r283723)
+++ stable/10/sys/netinet/sctputil.c	Fri May 29 12:54:30 2015	(r283724)
@@ -936,6 +936,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
 	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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505291254.t4TCsVEX042831>