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
This commit is contained in:
Randall Stewart 2011-03-08 11:58:25 +00:00
parent fd7032e1b3
commit f79aab1866
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219397
14 changed files with 583 additions and 205 deletions

View File

@ -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

View File

@ -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
}
};

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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)) {

View File

@ -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);

View File

@ -8254,7 +8254,10 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
} 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)) {

View File

@ -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++;

View File

@ -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 *);
};
/*

View File

@ -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",

View File

@ -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"

View File

@ -820,6 +820,12 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
/* 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);

View File

@ -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;