Author: rrs Date: Tue Mar 8 11:58:25 2011 New Revision: 219397 URL: http://svn.freebsd.org/changeset/base/219397
Log: Tunes and fixes the new DC-CC to seem to hit the right mix. Still may need some tweaks but it appears to almost not give away too much to an RFC2581 flow, but can really minimize the amount of buffers used in the net. MFC after: 3 months Modified: head/sys/netinet/sctp.h head/sys/netinet/sctp_cc_functions.c head/sys/netinet/sctp_constants.h head/sys/netinet/sctp_dtrace_declare.h head/sys/netinet/sctp_dtrace_define.h head/sys/netinet/sctp_indata.c head/sys/netinet/sctp_input.c head/sys/netinet/sctp_output.c head/sys/netinet/sctp_pcb.c head/sys/netinet/sctp_structs.h head/sys/netinet/sctp_sysctl.c head/sys/netinet/sctp_sysctl.h head/sys/netinet/sctp_timer.c head/sys/netinet/sctputil.c Modified: head/sys/netinet/sctp.h ============================================================================== --- head/sys/netinet/sctp.h Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp.h Tue Mar 8 11:58:25 2011 (r219397) @@ -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 Modified: head/sys/netinet/sctp_cc_functions.c ============================================================================== --- head/sys/netinet/sctp_cc_functions.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_cc_functions.c Tue Mar 8 11:58:25 2011 (r219397) @@ -185,6 +185,328 @@ sctp_cwnd_update_after_fr(struct sctp_tc } } +/* 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, struc * 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(struc 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(s 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 sc 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 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 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_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_functio .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 } }; Modified: head/sys/netinet/sctp_constants.h ============================================================================== --- head/sys/netinet/sctp_constants.h Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_constants.h Tue Mar 8 11:58:25 2011 (r219397) @@ -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 */ Modified: head/sys/netinet/sctp_dtrace_declare.h ============================================================================== --- head/sys/netinet/sctp_dtrace_declare.h Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_dtrace_declare.h Tue Mar 8 11:58:25 2011 (r219397) @@ -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); Modified: head/sys/netinet/sctp_dtrace_define.h ============================================================================== --- head/sys/netinet/sctp_dtrace_define.h Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_dtrace_define.h Tue Mar 8 11:58:25 2011 (r219397) @@ -78,14 +78,27 @@ SDT_PROBE_DEFINE(sctp, cwnd, net, 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 */ Modified: head/sys/netinet/sctp_indata.c ============================================================================== --- head/sys/netinet/sctp_indata.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_indata.c Tue Mar 8 11:58:25 2011 (r219397) @@ -2817,7 +2817,7 @@ sctp_process_segment_range(struct sctp_t 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_t * 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 } 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_t * 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 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 /* 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 off 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 off /* 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 off */ 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)) { Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_input.c Tue Mar 8 11:58:25 2011 (r219397) @@ -485,7 +485,7 @@ sctp_process_init_ack(struct mbuf *m, in /* 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_he } /* 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 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, 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_cooki 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 * 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); Modified: head/sys/netinet/sctp_output.c ============================================================================== --- head/sys/netinet/sctp_output.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_output.c Tue Mar 8 11:58:25 2011 (r219397) @@ -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)) { Modified: head/sys/netinet/sctp_pcb.c ============================================================================== --- head/sys/netinet/sctp_pcb.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_pcb.c Tue Mar 8 11:58:25 2011 (r219397) @@ -3858,6 +3858,7 @@ sctp_add_remote_addr(struct sctp_tcb *st * 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++; Modified: head/sys/netinet/sctp_structs.h ============================================================================== --- head/sys/netinet/sctp_structs.h Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_structs.h Tue Mar 8 11:58:25 2011 (r219397) @@ -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 *); }; /* Modified: head/sys/netinet/sctp_sysctl.c ============================================================================== --- head/sys/netinet/sctp_sysctl.c Tue Mar 8 11:50:59 2011 (r219396) +++ head/sys/netinet/sctp_sysctl.c Tue Mar 8 11:58:25 2011 (r219397) @@ -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; + *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"