diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index 403bea4ca63..1e86415f3f0 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -263,6 +263,7 @@ struct sctp_paramhdr { #define SCTP_CC_OPT_RTCC_SETMODE 0x00002000 #define SCTP_CC_OPT_USE_DCCC_ECN 0x00002001 +#define SCTP_CC_OPT_STEADY_STEP 0x00002002 /* RS - Supported stream scheduling modules for pluggable * stream scheduling diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index dd5aab0ff16..3d52820772b 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -185,6 +185,328 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, } } +/* Defines for instantaneous bw decisions */ +#define SCTP_INST_LOOSING 1 /* Loosing to other flows */ +#define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */ +#define SCTP_INST_GAINING 3 /* Gaining, step down possible */ + + +static int +cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, + uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind) +{ + uint64_t oth, probepoint; + + probepoint = (((uint64_t) net->cwnd) << 32); + if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) { + /* + * rtt increased we don't update bw.. so we don't update the + * rtt either. + */ + /* Probe point 5 */ + probepoint |= ((5 << 16) | 1); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) { + if (net->cc_mod.rtcc.last_step_state == 5) + net->cc_mod.rtcc.step_cnt++; + else + net->cc_mod.rtcc.step_cnt = 1; + net->cc_mod.rtcc.last_step_state = 5; + if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) || + ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) && + ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) { + /* Try a step down */ + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + if (net->cwnd > (4 * net->mtu)) { + net->cwnd -= net->mtu; + 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) { + /* + * 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. + */ + /* Probe point 6 */ + probepoint |= ((6 << 16) | 0); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + if (net->cc_mod.rtcc.steady_step) { + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + if ((net->cc_mod.rtcc.last_step_state == 5) && + (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) { + /* Step down worked */ + net->cc_mod.rtcc.step_cnt = 0; + return (1); + } else { + net->cc_mod.rtcc.last_step_state = 6; + net->cc_mod.rtcc.step_cnt = 0; + } + } + net->cc_mod.rtcc.lbw = nbw; + net->cc_mod.rtcc.lbw_rtt = net->rtt; + net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; + if (inst_ind == SCTP_INST_GAINING) + return (1); + else if (inst_ind == SCTP_INST_NEUTRAL) + return (1); + else + return (0); + } + /* + * Ok bw and rtt remained the same .. no update to any + */ + /* Probe point 7 */ + probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + + if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) { + if (net->cc_mod.rtcc.last_step_state == 5) + net->cc_mod.rtcc.step_cnt++; + else + net->cc_mod.rtcc.step_cnt = 1; + net->cc_mod.rtcc.last_step_state = 5; + if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) || + ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) && + ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) { + /* Try a step down */ + if (net->cwnd > (4 * net->mtu)) { + net->cwnd -= net->mtu; + net->cc_mod.rtcc.vol_reduce++; + return (1); + } else { + net->cc_mod.rtcc.step_cnt = 0; + } + } + } + if (inst_ind == SCTP_INST_GAINING) + return (1); + else if (inst_ind == SCTP_INST_NEUTRAL) + return (1); + else + return ((int)net->cc_mod.rtcc.ret_from_eq); +} + +static int +cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset, + uint64_t vtag, uint8_t inst_ind) +{ + uint64_t oth, probepoint; + + /* Bandwidth decreased. */ + probepoint = (((uint64_t) net->cwnd) << 32); + if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) { + /* rtt increased */ + /* Did we add more */ + if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) && + (inst_ind != SCTP_INST_LOOSING)) { + /* We caused it maybe.. back off? */ + /* PROBE POINT 1 */ + probepoint |= ((1 << 16) | 1); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + + if (net->cc_mod.rtcc.ret_from_eq) { + /* + * Switch over to CA if we are less + * aggressive + */ + net->ssthresh = net->cwnd - 1; + net->partial_bytes_acked = 0; + } + return (1); + } + /* Probe point 2 */ + probepoint |= ((2 << 16) | 0); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + + /* Someone else - fight for more? */ + if (net->cc_mod.rtcc.steady_step) { + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + /* + * 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; + 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 */ + /* Probe point 3 */ + probepoint |= ((3 << 16) | 0); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + if (net->cc_mod.rtcc.steady_step) { + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + if ((net->cc_mod.rtcc.vol_reduce) && + (inst_ind != SCTP_INST_GAINING)) { + net->cwnd += net->mtu; + 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 */ + /* Probe point 4 */ + probepoint |= ((4 << 16) | 0); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + if (net->cc_mod.rtcc.steady_step) { + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + if ((net->cc_mod.rtcc.vol_reduce) && + (inst_ind != SCTP_INST_GAINING)) { + net->cwnd += net->mtu; + 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; + net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; + if (inst_ind == SCTP_INST_GAINING) { + return (1); + } else { + return (0); + } +} + +static int +cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, + uint64_t vtag, uint8_t inst_ind) +{ + uint64_t oth, probepoint; + + /* + * BW increased, so update and return 0, since all actions in our + * table say to do the normal CC update. Note that we pay no + * attention to the inst_ind since our overall sum is increasing. + */ + /* PROBE POINT 0 */ + probepoint = (((uint64_t) net->cwnd) << 32); + SDT_PROBE(sctp, cwnd, net, rttvar, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, + probepoint); + if (net->cc_mod.rtcc.steady_step) { + oth = net->cc_mod.rtcc.vol_reduce; + oth <<= 16; + oth |= net->cc_mod.rtcc.step_cnt; + oth <<= 16; + oth |= net->cc_mod.rtcc.last_step_state; + SDT_PROBE(sctp, cwnd, net, rttstep, + vtag, + ((net->cc_mod.rtcc.lbw << 32) | nbw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + oth, + probepoint); + net->cc_mod.rtcc.last_step_state = 0; + net->cc_mod.rtcc.step_cnt = 0; + net->cc_mod.rtcc.vol_reduce = 0; + } + net->cc_mod.rtcc.lbw = nbw; + net->cc_mod.rtcc.lbw_rtt = net->rtt; + net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; + return (0); +} /* RTCC Algoritm to limit growth of cwnd, return * true if you want to NOT allow cwnd growth @@ -193,6 +515,11 @@ static int cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw) { uint64_t bw_offset, rtt_offset, rtt, vtag, probepoint; + uint64_t bytes_for_this_rtt, inst_bw; + uint64_t div, inst_off; + int bw_shift; + uint8_t inst_ind; + int ret; /*- * Here we need to see if we want @@ -231,151 +558,67 @@ cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw) * RTT it stayed the same if it did not * change within 1/32nd */ + bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw); rtt = stcb->asoc.my_vtag; vtag = (rtt << 32) | (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport); probepoint = (((uint64_t) net->cwnd) << 32); rtt = net->rtt; - bw_offset = net->cc_mod.rtcc.lbw >> SCTP_BASE_SYSCTL(sctp_rttvar_bw); - if (nbw > net->cc_mod.rtcc.lbw + bw_offset) { - /* - * BW increased, so update and return 0, since all actions - * in our table say to do the normal CC update - */ - /* PROBE POINT 0 */ + if (net->cc_mod.rtcc.rtt_set_this_sack) { + net->cc_mod.rtcc.rtt_set_this_sack = 0; + bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc; + net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes; + if (net->rtt) { + div = net->rtt / 1000; + if (div) { + inst_bw = bytes_for_this_rtt / div; + inst_off = inst_bw >> bw_shift; + if (inst_bw > nbw) + inst_ind = SCTP_INST_GAINING; + else if ((inst_bw + inst_off) < nbw) + inst_ind = SCTP_INST_LOOSING; + else + inst_ind = SCTP_INST_NEUTRAL; + probepoint |= ((0xb << 16) | inst_ind); + } else { + inst_bw = bytes_for_this_rtt / (uint64_t) (net->rtt); + /* Can't determine do not change */ + inst_ind = net->cc_mod.rtcc.last_inst_ind; + probepoint |= ((0xc << 16) | inst_ind); + } + } else { + inst_bw = bytes_for_this_rtt; + /* Can't determine do not change */ + inst_ind = net->cc_mod.rtcc.last_inst_ind; + probepoint |= ((0xd << 16) | inst_ind); + } SDT_PROBE(sctp, cwnd, net, rttvar, vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, + ((nbw << 32) | inst_bw), + ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt), + net->flight_size, probepoint); - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; - return (0); + } else { + /* No rtt measurement, use last one */ + inst_ind = net->cc_mod.rtcc.last_inst_ind; + } + bw_offset = net->cc_mod.rtcc.lbw >> bw_shift; + if (nbw > net->cc_mod.rtcc.lbw + bw_offset) { + ret = cc_bw_increase(stcb, net, nbw, vtag, inst_ind); + goto out; } rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt); if (nbw < net->cc_mod.rtcc.lbw - bw_offset) { - /* Bandwidth decreased. */ - if (rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) { - /* rtt increased */ - /* Did we add more */ - if (net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) { - /* We caused it maybe.. back off */ - /* PROBE POINT 1 */ - probepoint |= ((1 << 16) | 1); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cwnd = net->cc_mod.rtcc.cwnd_at_bw_set; - if (net->cc_mod.rtcc.ret_from_eq) { - /* - * Switch over to CA if we are less - * aggressive - */ - net->ssthresh = net->cwnd - 1; - net->partial_bytes_acked = 0; - } - return (1); - } - /* Probe point 2 */ - probepoint |= ((2 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - - /* Someone else - fight for more? */ - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; - return (0); - } else if (rtt < net->cc_mod.rtcc.lbw_rtt - rtt_offset) { - /* rtt decreased */ - /* Probe point 3 */ - probepoint |= ((3 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; - return (0); - } - /* The bw decreased but rtt stayed the same */ - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; - /* Probe point 4 */ - probepoint |= ((4 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - return (0); + ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind); + goto out; } /* * If we reach here then we are in a situation where the bw stayed * the same. */ - if (rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) { - /* - * rtt increased we don't update bw.. so we don't update the - * rtt either. - */ - /* Probe point 5 */ - probepoint |= ((5 << 16) | 1); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - return (1); - } - if (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. - */ - /* Probe point 6 */ - probepoint |= ((6 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - net->cc_mod.rtcc.lbw = nbw; - net->cc_mod.rtcc.lbw_rtt = rtt; - net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd; - return (0); - } - /* - * Ok bw and rtt remained the same .. no update to any but save the - * latest cwnd. - */ - /* Probe point 7 */ - probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq); - SDT_PROBE(sctp, cwnd, net, rttvar, - vtag, - ((net->cc_mod.rtcc.lbw << 32) | nbw), - net->cc_mod.rtcc.lbw_rtt, - rtt, - probepoint); - return ((int)net->cc_mod.rtcc.ret_from_eq); + ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind); +out: + net->cc_mod.rtcc.last_inst_ind = inst_ind; + return (ret); } static void @@ -554,11 +797,15 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, SDT_PROBE(sctp, cwnd, net, rttvar, vtag, nbw, - 0, - net->rtt, + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, probepoint); net->cc_mod.rtcc.lbw = nbw; net->cc_mod.rtcc.lbw_rtt = net->rtt; + if (net->cc_mod.rtcc.rtt_set_this_sack) { + net->cc_mod.rtcc.rtt_set_this_sack = 0; + net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes; + } } } /* @@ -1014,15 +1261,22 @@ sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb, SDT_PROBE(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | 0), - net->cc_mod.rtcc.lbw_rtt, - 0, + ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), + net->flight_size, probepoint); net->cc_mod.rtcc.lbw_rtt = 0; net->cc_mod.rtcc.cwnd_at_bw_set = 0; net->cc_mod.rtcc.lbw = 0; + net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0; + net->cc_mod.rtcc.vol_reduce = 0; net->cc_mod.rtcc.bw_tot_time = 0; net->cc_mod.rtcc.bw_bytes = 0; net->cc_mod.rtcc.tls_needs_set = 0; + if (net->cc_mod.rtcc.steady_step) { + net->cc_mod.rtcc.vol_reduce = 0; + net->cc_mod.rtcc.step_cnt = 0; + net->cc_mod.rtcc.last_step_state = 0; + } if (net->cc_mod.rtcc.ret_from_eq) { /* less aggressive one - reset cwnd too */ uint32_t cwnd_in_mtu, cwnd; @@ -1075,11 +1329,20 @@ sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb, probepoint); net->cc_mod.rtcc.lbw_rtt = 0; net->cc_mod.rtcc.cwnd_at_bw_set = 0; + net->cc_mod.rtcc.vol_reduce = 0; net->cc_mod.rtcc.lbw = 0; + net->cc_mod.rtcc.vol_reduce = 0; + net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0; net->cc_mod.rtcc.bw_tot_time = 0; net->cc_mod.rtcc.bw_bytes = 0; net->cc_mod.rtcc.tls_needs_set = 0; net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret); + net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step); + net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn); + net->cc_mod.rtcc.step_cnt = 0; + net->cc_mod.rtcc.last_step_state = 0; + + } static int @@ -1106,6 +1369,10 @@ sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget, TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value; } + } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) { + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { + net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value; + } } else { return (EINVAL); } @@ -1123,6 +1390,12 @@ sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget, return (EFAULT); } cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn; + } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) { + net = TAILQ_FIRST(&stcb->asoc.nets); + if (net == NULL) { + return (EFAULT); + } + cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step; } else { return (EINVAL); } @@ -1149,6 +1422,12 @@ sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb, sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1); } +static void +sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb, + struct sctp_nets *net, struct timeval *now) +{ + net->cc_mod.rtcc.rtt_set_this_sack = 1; +} /* Here starts Sally Floyds HS-TCP */ @@ -2203,6 +2482,7 @@ struct sctp_cc_functions sctp_cc_functions[] = { .sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged, .sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins, .sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack, - .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option + .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option, + .sctp_rtt_calculated = sctp_rtt_rtcc_calculated } }; diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index 85c92ed4d58..6c2df1693fb 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -355,8 +355,8 @@ __FBSDID("$FreeBSD$"); /* RTO calculation flag to say if it * is safe to determine local lan or not. */ -#define SCTP_DETERMINE_LL_NOTOK 0 -#define SCTP_DETERMINE_LL_OK 1 +#define SCTP_RTT_FROM_NON_DATA 0 +#define SCTP_RTT_FROM_DATA 1 /* IP hdr (20/40) + 12+2+2 (enet) + sctp common 12 */ diff --git a/sys/netinet/sctp_dtrace_declare.h b/sys/netinet/sctp_dtrace_declare.h index 7279f66b77f..6f0f8b10aac 100644 --- a/sys/netinet/sctp_dtrace_declare.h +++ b/sys/netinet/sctp_dtrace_declare.h @@ -57,6 +57,7 @@ SDT_PROBE_DECLARE(sctp, cwnd, net, ecn); SDT_PROBE_DECLARE(sctp, cwnd, net, pd); /* Rttvar probe declaration */ SDT_PROBE_DECLARE(sctp, cwnd, net, rttvar); +SDT_PROBE_DECLARE(sctp, cwnd, net, rttstep); /* One to track an associations rwnd */ SDT_PROBE_DECLARE(sctp, rwnd, assoc, val); diff --git a/sys/netinet/sctp_dtrace_define.h b/sys/netinet/sctp_dtrace_define.h index f773cf105a7..5f7bf14db14 100644 --- a/sys/netinet/sctp_dtrace_define.h +++ b/sys/netinet/sctp_dtrace_define.h @@ -78,14 +78,27 @@ SDT_PROBE_DEFINE(sctp, cwnd, net, rttvar, rttvar); SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 0, "uint64_t"); /* obw | nbw */ SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 1, "uint64_t"); -/* newrtt */ +/* bwrtt | newrtt */ SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 2, "uint64_t"); -/* bwrtt */ +/* flight */ SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 3, "uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */ SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 4, "uint64_t"); +SDT_PROBE_DEFINE(sctp, cwnd, net, rttstep, rttstep); +/* The Vtag << 32 | localport << 16 | remoteport */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 0, "uint64_t"); +/* obw | nbw */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 1, "uint64_t"); +/* bwrtt | nrtt */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 2, "uint64_t"); +/* cwnd_saved | stepcnt << 16 | oldstep */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 3, "uint64_t"); +/* (cwnd << 32) | point << 16 | retval(0/1) */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 4, "uint64_t"); + + /* FastRetransmit-DECREASE */ SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr); /* The Vtag for this end */ diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 1ec465e63a7..6ea4669670f 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -2817,7 +2817,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 int *num_frs, uint32_t * biggest_newly_acked_tsn, uint32_t * this_sack_lowest_newack, - int *ecn_seg_sums) + int *ecn_seg_sums, int *rto_ok) { struct sctp_tmit_chunk *tp1; unsigned int theTSN; @@ -2956,13 +2956,19 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 * update RTO too ? */ if (tp1->do_rtt) { - tp1->whoTo->RTO = - sctp_calculate_rto(stcb, - &stcb->asoc, - tp1->whoTo, - &tp1->sent_rcv_time, - sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_OK); + if (*rto_ok) { + tp1->whoTo->RTO = + sctp_calculate_rto(stcb, + &stcb->asoc, + tp1->whoTo, + &tp1->sent_rcv_time, + sctp_align_safe_nocopy, + SCTP_RTT_FROM_DATA); + *rto_ok = 0; + } + if (tp1->whoTo->rto_needed == 0) { + tp1->whoTo->rto_needed = 1; + } tp1->do_rtt = 0; } } @@ -3033,7 +3039,8 @@ static int sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, uint32_t last_tsn, uint32_t * biggest_tsn_acked, uint32_t * biggest_newly_acked_tsn, uint32_t * this_sack_lowest_newack, - int num_seg, int num_nr_seg, int *ecn_seg_sums) + int num_seg, int num_nr_seg, int *ecn_seg_sums, + int *rto_ok) { struct sctp_gap_ack_block *frag, block; struct sctp_tmit_chunk *tp1; @@ -3079,7 +3086,7 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct } 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)) { + this_sack_lowest_newack, ecn_seg_sums, rto_ok)) { chunk_freed = 1; } prev_frag_end = frag_end; @@ -3579,6 +3586,9 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * this guy had a RTO calculation pending on * it, cancel it */ + if (tp1->whoTo->rto_needed == 0) { + tp1->whoTo->rto_needed = 1; + } tp1->do_rtt = 0; } if (alt != tp1->whoTo) { @@ -3775,6 +3785,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, int win_probe_recovery = 0; int win_probe_recovered = 0; int j, done_once = 0; + int rto_ok = 1; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) { sctp_misc_ints(SCTP_SACK_LOG_EXPRESS, cumack, @@ -3916,16 +3927,23 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, /* update RTO too? */ if (tp1->do_rtt) { - tp1->whoTo->RTO = - /* - * sa_ignore - * NO_NULL_CHK - */ - sctp_calculate_rto(stcb, - asoc, tp1->whoTo, - &tp1->sent_rcv_time, - sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_OK); + if (rto_ok) { + tp1->whoTo->RTO = + /* + * sa_ignore + * NO_NULL_CH + * K + */ + sctp_calculate_rto(stcb, + asoc, tp1->whoTo, + &tp1->sent_rcv_time, + sctp_align_safe_nocopy, + SCTP_RTT_FROM_DATA); + rto_ok = 0; + } + if (tp1->whoTo->rto_needed == 0) { + tp1->whoTo->rto_needed = 1; + } tp1->do_rtt = 0; } } @@ -4280,6 +4298,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, struct sctp_nets *net = NULL; int ecn_seg_sums = 0; int done_once; + int rto_ok = 1; uint8_t reneged_all = 0; uint8_t cmt_dac_flag; @@ -4526,12 +4545,18 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, /* update RTO too? */ if (tp1->do_rtt) { - tp1->whoTo->RTO = - sctp_calculate_rto(stcb, - asoc, tp1->whoTo, - &tp1->sent_rcv_time, - sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_OK); + if (rto_ok) { + tp1->whoTo->RTO = + sctp_calculate_rto(stcb, + asoc, tp1->whoTo, + &tp1->sent_rcv_time, + sctp_align_safe_nocopy, + SCTP_RTT_FROM_DATA); + rto_ok = 0; + } + if (tp1->whoTo->rto_needed == 0) { + tp1->whoTo->rto_needed = 1; + } tp1->do_rtt = 0; } } @@ -4606,7 +4631,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, */ if (sctp_handle_segments(m, &offset_seg, stcb, asoc, last_tsn, &biggest_tsn_acked, &biggest_tsn_newly_acked, &this_sack_lowest_newack, - num_seg, num_nr_seg, &ecn_seg_sums)) { + num_seg, num_nr_seg, &ecn_seg_sums, + &rto_ok)) { wake_him++; } if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 1329c40e52d..3c25eaabf29 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -485,7 +485,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, /* calculate the RTO */ net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_NOTOK); + SCTP_RTT_FROM_NON_DATA); retval = sctp_send_cookie_echo(m, offset, stcb, net); if (retval < 0) { @@ -630,7 +630,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, } /* Now lets do a RTO with this */ r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_OK); + SCTP_RTT_FROM_NON_DATA); /* Mobility adaptation */ if (req_prim) { if ((sctp_is_mobility_feature_on(stcb->sctp_ep, @@ -1547,7 +1547,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, net->RTO = sctp_calculate_rto(stcb, asoc, net, &cookie->time_entered, sctp_align_unsafe_makecopy, - SCTP_DETERMINE_LL_NOTOK); + SCTP_RTT_FROM_NON_DATA); if (stcb->asoc.sctp_autoclose_ticks && (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { @@ -2251,7 +2251,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, if ((netp) && (*netp)) { (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, &cookie->time_entered, sctp_align_unsafe_makecopy, - SCTP_DETERMINE_LL_NOTOK); + SCTP_RTT_FROM_NON_DATA); } /* respond with a COOKIE-ACK */ sctp_send_cookie_ack(stcb); @@ -2849,7 +2849,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp, if (asoc->overall_error_count == 0) { net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, - SCTP_DETERMINE_LL_NOTOK); + SCTP_RTT_FROM_NON_DATA); } (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); @@ -3218,6 +3218,9 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, * this guy had a RTO calculation * pending on it, cancel it */ + if (tp1->whoTo->rto_needed == 0) { + tp1->whoTo->rto_needed = 1; + } tp1->do_rtt = 0; } SCTP_STAT_INCR(sctps_pdrpmark); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 1fe48477cc7..23361baf57a 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -8254,7 +8254,10 @@ no_data_fill: } else { asoc->time_last_sent = *now; } - data_list[0]->do_rtt = 1; + if (net->rto_needed) { + data_list[0]->do_rtt = 1; + net->rto_needed = 0; + } SCTP_STAT_INCR_BY(sctps_senddata, bundle_at); sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net); if (SCTP_BASE_SYSCTL(sctp_early_fr)) { diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index a6acbeea634..79781614719 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3858,6 +3858,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, * We set this to 0, the timer code knows that this means its an * initial value */ + net->rto_needed = 1; net->RTO = 0; net->RTO_measured = 0; stcb->asoc.numnets++; diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 39b7572be0d..250b312f3d7 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -226,11 +226,20 @@ struct rtcc_cc { uint64_t bw_bytes; /* The total bytes since this sending began */ uint64_t bw_tot_time; /* The total time since sending began */ uint64_t new_tot_time; /* temp holding the new value */ - uint32_t cwnd_at_bw_set; - uint8_t ret_from_eq; - uint8_t use_dccc_ecn; + uint64_t bw_bytes_at_last_rttc; /* What bw_bytes was at last rtt calc */ + uint32_t cwnd_at_bw_set;/* Cwnd at last bw saved - lbw */ + uint32_t vol_reduce; /* cnt of voluntary reductions */ + uint16_t steady_step; /* The number required to be in steady state */ + uint16_t step_cnt; /* The current number */ + uint8_t ret_from_eq; /* When all things are equal what do I return + * 0/1 - 1 no cc advance */ + uint8_t use_dccc_ecn; /* Flag to enable DCCC ECN */ uint8_t tls_needs_set; /* Flag to indicate we need to set tls 0 or 1 * means set at send 2 not */ + uint8_t last_step_state;/* Last state if steady state stepdown is on */ + uint8_t rtt_set_this_sack; /* Flag saying this sack had RTT calc + * on it */ + uint8_t last_inst_ind; /* Last saved inst indication */ }; @@ -364,6 +373,7 @@ struct sctp_nets { uint8_t RTO_measured; /* Have we done the first measure */ uint8_t last_hs_used; /* index into the last HS table entry we used */ uint8_t lan_type; + uint8_t rto_needed; uint32_t flowid; #ifdef INVARIANTS uint8_t flowidset; @@ -671,6 +681,7 @@ struct sctp_cc_functions { void (*sctp_cwnd_prepare_net_for_sack) (struct sctp_tcb *stcb, struct sctp_nets *net); int (*sctp_cwnd_socket_option) (struct sctp_tcb *stcb, int set, struct sctp_cc_option *); + void (*sctp_rtt_calculated) (struct sctp_tcb *, struct sctp_nets *, struct timeval *); }; /* diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index 4e69e1f6438..a8d080aaaaf 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -118,6 +118,9 @@ sctp_init_sysctls() SCTP_BASE_SYSCTL(sctp_rttvar_bw) = SCTPCTL_RTTVAR_BW_DEFAULT; SCTP_BASE_SYSCTL(sctp_rttvar_rtt) = SCTPCTL_RTTVAR_RTT_DEFAULT; SCTP_BASE_SYSCTL(sctp_rttvar_eqret) = SCTPCTL_RTTVAR_EQRET_DEFAULT; + SCTP_BASE_SYSCTL(sctp_steady_step) = SCTPCTL_RTTVAR_STEADYS_DEFAULT; + SCTP_BASE_SYSCTL(sctp_use_dccc_ecn) = SCTPCTL_RTTVAR_DCCCECN_DEFAULT; + #if defined(SCTP_LOCAL_TRACE_BUF) memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log)); #endif @@ -639,6 +642,8 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS) RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_bw), SCTPCTL_RTTVAR_BW_MIN, SCTPCTL_RTTVAR_BW_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_rtt), SCTPCTL_RTTVAR_RTT_MIN, SCTPCTL_RTTVAR_RTT_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_eqret), SCTPCTL_RTTVAR_EQRET_MIN, SCTPCTL_RTTVAR_EQRET_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_steady_step), SCTPCTL_RTTVAR_STEADYS_MIN, SCTPCTL_RTTVAR_STEADYS_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX); @@ -1118,6 +1123,14 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_eqret, CTLTYPE_UINT | CTLFLAG_ &SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sysctl_sctp_check, "IU", SCTPCTL_RTTVAR_EQRET_DESC); +SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_steady_step, CTLTYPE_UINT | CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_steady_step), 0, sysctl_sctp_check, "IU", + SCTPCTL_RTTVAR_STEADYS_DESC); + +SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, use_dcccecn, CTLTYPE_UINT | CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), 0, sysctl_sctp_check, "IU", + SCTPCTL_RTTVAR_DCCCECN_DESC); + #ifdef SCTP_DEBUG SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_debug_on), 0, sysctl_sctp_check, "IU", diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h index aba691806d8..842d9b1b5f1 100644 --- a/sys/netinet/sctp_sysctl.h +++ b/sys/netinet/sctp_sysctl.h @@ -107,6 +107,8 @@ struct sctp_sysctl { uint32_t sctp_rttvar_bw; uint32_t sctp_rttvar_rtt; uint32_t sctp_rttvar_eqret; + uint32_t sctp_steady_step; + uint32_t sctp_use_dccc_ecn; #if defined(SCTP_LOCAL_TRACE_BUF) struct sctp_log sctp_log; #endif @@ -224,8 +226,8 @@ struct sctp_sysctl { #define SCTPCTL_CHUNKSCALE_MAX 0xFFFFFFFF #define SCTPCTL_CHUNKSCALE_DEFAULT SCTP_CHUNKQUEUE_SCALE -/* delayed_sack_time: Default delayed SACK timer in msec */ -#define SCTPCTL_DELAYED_SACK_TIME_DESC "Default delayed SACK timer in msec" +/* delayed_sack_time: Default delayed SACK timer in ms */ +#define SCTPCTL_DELAYED_SACK_TIME_DESC "Default delayed SACK timer in ms" #define SCTPCTL_DELAYED_SACK_TIME_MIN 0 #define SCTPCTL_DELAYED_SACK_TIME_MAX 0xFFFFFFFF #define SCTPCTL_DELAYED_SACK_TIME_DEFAULT SCTP_RECV_MSEC @@ -248,56 +250,56 @@ struct sctp_sysctl { #define SCTPCTL_ASOC_RESOURCE_MAX 0xFFFFFFFF #define SCTPCTL_ASOC_RESOURCE_DEFAULT SCTP_DEF_ASOC_RESC_LIMIT -/* heartbeat_interval: Default heartbeat interval in msec */ -#define SCTPCTL_HEARTBEAT_INTERVAL_DESC "Default heartbeat interval in msec" +/* heartbeat_interval: Default heartbeat interval in ms */ +#define SCTPCTL_HEARTBEAT_INTERVAL_DESC "Default heartbeat interval in ms" #define SCTPCTL_HEARTBEAT_INTERVAL_MIN 0 #define SCTPCTL_HEARTBEAT_INTERVAL_MAX 0xFFFFFFFF #define SCTPCTL_HEARTBEAT_INTERVAL_DEFAULT SCTP_HB_DEFAULT_MSEC -/* pmtu_raise_time: Default PMTU raise timer in sec */ -#define SCTPCTL_PMTU_RAISE_TIME_DESC "Default PMTU raise timer in sec" +/* pmtu_raise_time: Default PMTU raise timer in seconds */ +#define SCTPCTL_PMTU_RAISE_TIME_DESC "Default PMTU raise timer in seconds" #define SCTPCTL_PMTU_RAISE_TIME_MIN 0 #define SCTPCTL_PMTU_RAISE_TIME_MAX 0xFFFFFFFF #define SCTPCTL_PMTU_RAISE_TIME_DEFAULT SCTP_DEF_PMTU_RAISE_SEC -/* shutdown_guard_time: Default shutdown guard timer in sec */ -#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in sec" +/* shutdown_guard_time: Default shutdown guard timer in seconds */ +#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in seconds" #define SCTPCTL_SHUTDOWN_GUARD_TIME_MIN 0 #define SCTPCTL_SHUTDOWN_GUARD_TIME_MAX 0xFFFFFFFF #define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT SCTP_DEF_MAX_SHUTDOWN_SEC -/* secret_lifetime: Default secret lifetime in sec */ -#define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in sec" +/* secret_lifetime: Default secret lifetime in seconds */ +#define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in seconds" #define SCTPCTL_SECRET_LIFETIME_MIN 0 #define SCTPCTL_SECRET_LIFETIME_MAX 0xFFFFFFFF #define SCTPCTL_SECRET_LIFETIME_DEFAULT SCTP_DEFAULT_SECRET_LIFE_SEC -/* rto_max: Default maximum retransmission timeout in msec */ -#define SCTPCTL_RTO_MAX_DESC "Default maximum retransmission timeout in msec" +/* rto_max: Default maximum retransmission timeout in ms */ +#define SCTPCTL_RTO_MAX_DESC "Default maximum retransmission timeout in ms" #define SCTPCTL_RTO_MAX_MIN 0 #define SCTPCTL_RTO_MAX_MAX 0xFFFFFFFF #define SCTPCTL_RTO_MAX_DEFAULT SCTP_RTO_UPPER_BOUND -/* rto_min: Default minimum retransmission timeout in msec */ -#define SCTPCTL_RTO_MIN_DESC "Default minimum retransmission timeout in msec" +/* rto_min: Default minimum retransmission timeout in ms */ +#define SCTPCTL_RTO_MIN_DESC "Default minimum retransmission timeout in ms" #define SCTPCTL_RTO_MIN_MIN 0 #define SCTPCTL_RTO_MIN_MAX 0xFFFFFFFF #define SCTPCTL_RTO_MIN_DEFAULT SCTP_RTO_LOWER_BOUND -/* rto_initial: Default initial retransmission timeout in msec */ -#define SCTPCTL_RTO_INITIAL_DESC "Default initial retransmission timeout in msec" +/* rto_initial: Default initial retransmission timeout in ms */ +#define SCTPCTL_RTO_INITIAL_DESC "Default initial retransmission timeout in ms" #define SCTPCTL_RTO_INITIAL_MIN 0 #define SCTPCTL_RTO_INITIAL_MAX 0xFFFFFFFF #define SCTPCTL_RTO_INITIAL_DEFAULT SCTP_RTO_INITIAL -/* init_rto_max: Default maximum retransmission timeout during association setup in msec */ -#define SCTPCTL_INIT_RTO_MAX_DESC "Default maximum retransmission timeout during association setup in msec" +/* init_rto_max: Default maximum retransmission timeout during association setup in ms */ +#define SCTPCTL_INIT_RTO_MAX_DESC "Default maximum retransmission timeout during association setup in ms" #define SCTPCTL_INIT_RTO_MAX_MIN 0 #define SCTPCTL_INIT_RTO_MAX_MAX 0xFFFFFFFF #define SCTPCTL_INIT_RTO_MAX_DEFAULT SCTP_RTO_UPPER_BOUND /* valid_cookie_life: Default cookie lifetime in sec */ -#define SCTPCTL_VALID_COOKIE_LIFE_DESC "Default cookie lifetime in sec" +#define SCTPCTL_VALID_COOKIE_LIFE_DESC "Default cookie lifetime in seconds" #define SCTPCTL_VALID_COOKIE_LIFE_MIN 0 #define SCTPCTL_VALID_COOKIE_LIFE_MAX 0xFFFFFFFF #define SCTPCTL_VALID_COOKIE_LIFE_DEFAULT SCTP_DEFAULT_COOKIE_LIFE @@ -320,8 +322,8 @@ struct sctp_sysctl { #define SCTPCTL_PATH_RTX_MAX_MAX 0xFFFFFFFF #define SCTPCTL_PATH_RTX_MAX_DEFAULT SCTP_DEF_MAX_PATH_RTX -/* add_more_on_output: When space wise is it worthwhile to try to add more to a socket send buffer */ -#define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space wise is it worthwhile to try to add more to a socket send buffer" +/* add_more_on_output: When space-wise is it worthwhile to try to add more to a socket send buffer */ +#define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space-wise is it worthwhile to try to add more to a socket send buffer" #define SCTPCTL_ADD_MORE_ON_OUTPUT_MIN 0 #define SCTPCTL_ADD_MORE_ON_OUTPUT_MAX 0xFFFFFFFF #define SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT SCTP_DEFAULT_ADD_MORE @@ -519,22 +521,32 @@ struct sctp_sysctl { #define SCTPCTL_INITIAL_CWND_DEFAULT 3 /* rttvar smooth avg for bw calc */ -#define SCTPCTL_RTTVAR_BW_DESC "Shift amount for bw smothing on rtt calc" +#define SCTPCTL_RTTVAR_BW_DESC "Shift amount for bw smoothing on rtt calc" #define SCTPCTL_RTTVAR_BW_MIN 0 #define SCTPCTL_RTTVAR_BW_MAX 32 #define SCTPCTL_RTTVAR_BW_DEFAULT 4 /* rttvar smooth avg for bw calc */ -#define SCTPCTL_RTTVAR_RTT_DESC "Shift amount for rtt smothing on rtt calc" +#define SCTPCTL_RTTVAR_RTT_DESC "Shift amount for rtt smoothing on rtt calc" #define SCTPCTL_RTTVAR_RTT_MIN 0 #define SCTPCTL_RTTVAR_RTT_MAX 32 #define SCTPCTL_RTTVAR_RTT_DEFAULT 5 -#define SCTPCTL_RTTVAR_EQRET_DESC "When rtt and bw are unchanged return what" +#define SCTPCTL_RTTVAR_EQRET_DESC "What to return when rtt and bw are unchanged" #define SCTPCTL_RTTVAR_EQRET_MIN 0 #define SCTPCTL_RTTVAR_EQRET_MAX 1 #define SCTPCTL_RTTVAR_EQRET_DEFAULT 0 +#define SCTPCTL_RTTVAR_STEADYS_DESC "How many the sames it takes to try step down of cwnd" +#define SCTPCTL_RTTVAR_STEADYS_MIN 0 +#define SCTPCTL_RTTVAR_STEADYS_MAX 0xFFFF +#define SCTPCTL_RTTVAR_STEADYS_DEFAULT 20 /* 0 means disable feature */ + +#define SCTPCTL_RTTVAR_DCCCECN_DESC "Enable for RTCC CC datacenter ECN" +#define SCTPCTL_RTTVAR_DCCCECN_MIN 0 +#define SCTPCTL_RTTVAR_DCCCECN_MAX 1 +#define SCTPCTL_RTTVAR_DCCCECN_DEFAULT 1 /* 0 means disable feature */ + #if defined(SCTP_DEBUG) /* debug: Configure debug output */ #define SCTPCTL_DEBUG_DESC "Configure debug output" diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 6ff0f581404..bccf7dfc739 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -820,6 +820,12 @@ start_again: /* reset the TSN for striking and other FR stuff */ chk->rec.data.doing_fast_retransmit = 0; /* Clear any time so NO RTT is being done */ + + if (chk->do_rtt) { + if (chk->whoTo->rto_needed == 0) { + chk->whoTo->rto_needed = 1; + } + } chk->do_rtt = 0; if (alt != net) { sctp_free_remote_addr(chk->whoTo); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index a1b345031cb..ffd131ffc6c 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1370,11 +1370,10 @@ sctp_iterator_worker(void) SCTP_IPI_ITERATOR_WQ_UNLOCK(); CURVNET_SET(it->vn); sctp_iterator_work(it); - + sctp_it_ctl.cur_it = NULL; CURVNET_RESTORE(); SCTP_IPI_ITERATOR_WQ_LOCK(); if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) { - sctp_it_ctl.cur_it = NULL; break; } /* sa_ignore FREED_MEMORY */ @@ -2469,7 +2468,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_nets *net, struct timeval *told, - int safe, int local_lan_determine) + int safe, int rtt_from_sack) { /*- * given an association and the starting time of the current RTT @@ -2507,9 +2506,18 @@ sctp_calculate_rto(struct sctp_tcb *stcb, /* computer rtt in ms */ rtt = net->rtt / 1000; - - /* Do we need to determine the lan type? */ - if ((local_lan_determine == SCTP_DETERMINE_LL_OK) && + if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) { + /* + * Tell the CC module that a new update has just occurred + * from a sack + */ + (*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now); + } + /* + * Do we need to determine the lan? We do this only on sacks i.e. + * RTT being determined from data not non-data (HB/INIT->INITACK). + */ + if ((rtt_from_sack == SCTP_RTT_FROM_DATA) && (net->lan_type == SCTP_LAN_UNKNOWN)) { if (net->rtt > SCTP_LOCAL_LAN_RTT) { net->lan_type = SCTP_LAN_INTERNET;