Adds a new Congestion Control that helps reduce

the RTT that a flow will build up in buffers in
transit. It is a slight modification to RFC2581
but is more friendly i.e. less aggressive.

MFC after:	3 months
This commit is contained in:
Randall Stewart 2011-03-01 00:37:46 +00:00
parent 7d66f0801b
commit 48b6c64938
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219120
7 changed files with 549 additions and 41 deletions

View File

@ -258,6 +258,11 @@ struct sctp_paramhdr {
#define SCTP_CC_HSTCP 0x00000001
/* HTCP Congestion Control */
#define SCTP_CC_HTCP 0x00000002
/* RTCC Congestion Control - RFC2581 plus */
#define SCTP_CC_RTCC 0x00000003
#define SCTP_CC_OPT_RTCC_SETMODE 0x00002000
#define SCTP_CC_OPT_USE_DCCC_ECN 0x00002001
/* RS - Supported stream scheduling modules for pluggable
* stream scheduling

View File

@ -185,10 +185,203 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
}
}
/* RTCC Algoritm to limit growth of cwnd, return
* true if you want to NOT allow cwnd growth
*/
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;
/*-
* Here we need to see if we want
* to limit cwnd growth due to increase
* in overall rtt but no increase in bw.
* We use the following table to figure
* out what we should do. When we return
* 0, cc update goes on as planned. If we
* return 1, then no cc update happens and cwnd
* stays where it is at.
* ----------------------------------
* BW | RTT | Action
* *********************************
* INC | INC | return 0
* ----------------------------------
* INC | SAME | return 0
* ----------------------------------
* INC | DECR | return 0
* ----------------------------------
* SAME | INC | return 1
* ----------------------------------
* SAME | SAME | return 1
* ----------------------------------
* SAME | DECR | return 0
* ----------------------------------
* DECR | INC | return 0 or 1 based on if we caused.
* ----------------------------------
* DECR | SAME | return 0
* ----------------------------------
* DECR | DECR | return 0
* ----------------------------------
*
* We are a bit fuzz on what an increase or
* decrease is. For BW it is the same if
* it did not change within 1/64th. For
* RTT it stayed the same if it did not
* change within 1/32nd
*/
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 */
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);
}
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);
}
/*
* 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);
}
static void
sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit)
int accum_moved, int reneged_all, int will_exit, int use_rtcc)
{
struct sctp_nets *net;
int old_cwnd;
@ -326,6 +519,48 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*/
goto skip_cwnd_update;
}
/*
* Did any measurements go on for this network?
*/
if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
uint64_t nbw;
/*
* At this point our bw_bytes has been updated by
* incoming sack information.
*
* But our bw may not yet be set.
*
*/
if ((net->cc_mod.rtcc.new_tot_time / 1000) > 0) {
nbw = net->cc_mod.rtcc.bw_bytes / (net->cc_mod.rtcc.new_tot_time / 1000);
} else {
nbw = net->cc_mod.rtcc.bw_bytes;
}
if (net->cc_mod.rtcc.lbw) {
if (cc_bw_limit(stcb, net, nbw)) {
/* Hold here, no update */
goto skip_cwnd_update;
}
} else {
uint64_t vtag, probepoint;
probepoint = (((uint64_t) net->cwnd) << 32);
probepoint |= ((0xa << 16) | 0);
vtag = (net->rtt << 32) |
(((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
(stcb->rport);
SDT_PROBE(sctp, cwnd, net, rttvar,
vtag,
nbw,
0,
net->rtt,
probepoint);
net->cc_mod.rtcc.lbw = nbw;
net->cc_mod.rtcc.lbw_rtt = net->rtt;
}
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
@ -481,31 +716,67 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
static void
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
int in_window, int num_pkt_lost)
sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
int in_window, int num_pkt_lost, int use_rtcc)
{
int old_cwnd = net->cwnd;
if (in_window == 0) {
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
net->ssthresh = net->cwnd / 2;
if (net->ssthresh < net->mtu) {
net->ssthresh = net->mtu;
/* here back off the timer as well, to slow us down */
net->RTO <<= 1;
if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
/* Data center Congestion Control */
if (in_window == 0) {
/*
* Go to CA with the cwnd at the point we sent the
* TSN that was marked with a CE.
*/
if (net->ecn_prev_cwnd < net->cwnd) {
/* Restore to prev cwnd */
net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
} else {
/* Just cut in 1/2 */
net->cwnd /= 2;
}
/* Drop to CA */
net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
}
} else {
/*
* Further tuning down required over the drastic
* orginal cut
*/
net->ssthresh -= (net->mtu * num_pkt_lost);
net->cwnd -= (net->mtu * num_pkt_lost);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
}
}
net->cwnd = net->ssthresh;
SDT_PROBE(sctp, cwnd, net, ecn,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
} else {
if (in_window == 0) {
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
net->ssthresh = net->cwnd / 2;
if (net->ssthresh < net->mtu) {
net->ssthresh = net->mtu;
/*
* here back off the timer as well, to slow
* us down
*/
net->RTO <<= 1;
}
net->cwnd = net->ssthresh;
SDT_PROBE(sctp, cwnd, net, ecn,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
}
}
}
}
static void
@ -636,14 +907,16 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
if (net->ssthresh < net->cwnd)
net->ssthresh = net->cwnd;
net->cwnd = (net->flight_size + (burst_limit * net->mtu));
SDT_PROBE(sctp, cwnd, net, bl,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
if (burst_limit) {
net->cwnd = (net->flight_size + (burst_limit * net->mtu));
SDT_PROBE(sctp, cwnd, net, bl,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
}
}
}
@ -673,6 +946,212 @@ sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
}
}
static void
sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit)
{
/* Passing a zero argument in last disables the rtcc algoritm */
sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
}
static void
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
int in_window, int num_pkt_lost)
{
/* Passing a zero argument in last disables the rtcc algoritm */
sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
}
/* Here starts the RTCCVAR type CC invented by RRS which
* is a slight mod to RFC2581. We reuse a common routine or
* two since these algoritms are so close and need to
* remain the same.
*/
static void
sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
int in_window, int num_pkt_lost)
{
sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
}
static
void
sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
struct sctp_tmit_chunk *tp1)
{
net->cc_mod.rtcc.bw_bytes += tp1->send_size;
}
static void
sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb,
struct sctp_nets *net)
{
if (net->cc_mod.rtcc.tls_needs_set > 0) {
/* We had a bw measurment going on */
struct timeval ltls;
SCTP_GETPTIME_TIMEVAL(&ltls);
timevalsub(&ltls, &net->cc_mod.rtcc.tls);
net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
}
}
static void
sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
struct sctp_nets *net)
{
uint64_t vtag, probepoint;
if (net->cc_mod.rtcc.lbw) {
/* Clear the old bw.. we went to 0 in-flight */
vtag = (net->rtt << 32) | (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
(stcb->rport);
probepoint = (((uint64_t) net->cwnd) << 32);
/* Probe point 8 */
probepoint |= ((8 << 16) | 0);
SDT_PROBE(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | 0),
net->cc_mod.rtcc.lbw_rtt,
0,
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_tot_time = 0;
net->cc_mod.rtcc.bw_bytes = 0;
net->cc_mod.rtcc.tls_needs_set = 0;
if (net->cc_mod.rtcc.ret_from_eq) {
/* less aggressive one - reset cwnd too */
uint32_t cwnd_in_mtu, cwnd;
cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
if (cwnd_in_mtu == 0) {
/*
* Using 0 means that the value of RFC 4960
* is used.
*/
cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
} else {
/*
* We take the minimum of the burst limit
* and the initial congestion window.
*/
if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
cwnd_in_mtu = stcb->asoc.max_burst;
cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
}
if (net->cwnd > cwnd) {
/*
* Only set if we are not a timeout (i.e.
* down to 1 mtu)
*/
net->cwnd = cwnd;
}
}
}
}
static void
sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
struct sctp_nets *net)
{
uint64_t vtag, probepoint;
sctp_set_initial_cc_param(stcb, net);
stcb->asoc.use_precise_time = 1;
probepoint = (((uint64_t) net->cwnd) << 32);
probepoint |= ((9 << 16) | 0);
vtag = (net->rtt << 32) |
(((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
(stcb->rport);
SDT_PROBE(sctp, cwnd, net, rttvar,
vtag,
0,
0,
0,
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_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);
}
static int
sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
struct sctp_cc_option *cc_opt)
{
struct sctp_nets *net;
if (setorget == 1) {
/* a set */
if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
if ((cc_opt->aid_value.assoc_value != 0) &&
(cc_opt->aid_value.assoc_value != 1)) {
return (EINVAL);
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
}
} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
if ((cc_opt->aid_value.assoc_value != 0) &&
(cc_opt->aid_value.assoc_value != 1)) {
return (EINVAL);
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
}
} else {
return (EINVAL);
}
} else {
/* a get */
if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
net = TAILQ_FIRST(&stcb->asoc.nets);
if (net == NULL) {
return (EFAULT);
}
cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
net = TAILQ_FIRST(&stcb->asoc.nets);
if (net == NULL) {
return (EFAULT);
}
cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
} else {
return (EINVAL);
}
}
return (0);
}
static void
sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb,
struct sctp_nets *net)
{
if (net->cc_mod.rtcc.tls_needs_set == 0) {
SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
net->cc_mod.rtcc.tls_needs_set = 2;
}
}
static void
sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit)
{
/* Passing a one argument at the last enables the rtcc algoritm */
sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
}
/* Here starts Sally Floyds HS-TCP */
struct sctp_hs_raise_drop {
int32_t cwnd;
int32_t increase;
@ -1710,5 +2189,20 @@ struct sctp_cc_functions sctp_cc_functions[] = {
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
.sctp_cwnd_update_after_fr_timer = sctp_htcp_cwnd_update_after_fr_timer
},
{
.sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
.sctp_cwnd_update_after_fr_timer = sctp_cwnd_update_after_fr_timer,
.sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
.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
}
};

View File

@ -965,10 +965,9 @@ __FBSDID("$FreeBSD$");
* local lan type rtt's
*/
/*
* We allow 500us for the rtt and another 500us for the cookie processing
* since we measure this on the first rtt.
* We allow 900us for the rtt.
*/
#define SCTP_LOCAL_LAN_RTT 1100
#define SCTP_LOCAL_LAN_RTT 900
#define SCTP_LAN_UNKNOWN 0
#define SCTP_LAN_LOCAL 1
#define SCTP_LAN_INTERNET 2

View File

@ -219,6 +219,21 @@ struct htcp {
uint32_t lasttime;
};
struct rtcc_cc {
struct timeval tls; /* The time we started the sending */
uint64_t lbw; /* Our last estimated bw */
uint64_t lbw_rtt; /* RTT at bw estimate */
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;
uint8_t tls_needs_set; /* Flag to indicate we need to set tls 0 or 1
* means set at send 2 not */
};
struct sctp_nets {
TAILQ_ENTRY(sctp_nets) sctp_next; /* next link */
@ -255,6 +270,7 @@ struct sctp_nets {
struct timeval last_sent_time;
union cc_control_data {
struct htcp htcp_ca; /* JRS - struct used in HTCP algorithm */
struct rtcc_cc rtcc; /* rtcc module cc stuff */
} cc_mod;
int ref_count;

View File

@ -115,11 +115,9 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_vtag_time_wait) = SCTPCTL_TIME_WAIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_buffer_splitting) = SCTPCTL_BUFFER_SPLITTING_DEFAULT;
SCTP_BASE_SYSCTL(sctp_initial_cwnd) = SCTPCTL_INITIAL_CWND_DEFAULT;
#ifdef SCTP_HAS_RTTCC
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;
#endif
#if defined(SCTP_LOCAL_TRACE_BUF)
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
#endif
@ -638,11 +636,9 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_time_wait), SCTPCTL_TIME_WAIT_MIN, SCTPCTL_TIME_WAIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_buffer_splitting), SCTPCTL_BUFFER_SPLITTING_MIN, SCTPCTL_BUFFER_SPLITTING_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_initial_cwnd), SCTPCTL_INITIAL_CWND_MIN, SCTPCTL_INITIAL_CWND_MAX);
#ifdef SCTP_HAS_RTTCC
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);
#endif
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);
@ -1110,7 +1106,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_UINT | CTLFLAG_
&SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sysctl_sctp_check, "IU",
SCTPCTL_INITIAL_CWND_DESC);
#ifdef SCTP_HAS_RTTCC
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_bw, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rttvar_bw), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTTVAR_BW_DESC);
@ -1122,7 +1117,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_rtt, CTLTYPE_UINT | CTLFLAG_RW
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_eqret, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTTVAR_EQRET_DESC);
#endif
#ifdef SCTP_DEBUG
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW,

View File

@ -104,11 +104,9 @@ struct sctp_sysctl {
uint32_t sctp_mobility_base;
uint32_t sctp_mobility_fasthandoff;
uint32_t sctp_inits_include_nat_friendly;
#ifdef SCTP_HAS_RTTCC
uint32_t sctp_rttvar_bw;
uint32_t sctp_rttvar_rtt;
uint32_t sctp_rttvar_eqret;
#endif
#if defined(SCTP_LOCAL_TRACE_BUF)
struct sctp_log sctp_log;
#endif
@ -519,7 +517,6 @@ struct sctp_sysctl {
#define SCTPCTL_INITIAL_CWND_MIN 0
#define SCTPCTL_INITIAL_CWND_MAX 0xffffffff
#define SCTPCTL_INITIAL_CWND_DEFAULT 3
#ifdef SCTP_HAS_RTTCC
/* rttvar smooth avg for bw calc */
#define SCTPCTL_RTTVAR_BW_DESC "Shift amount for bw smothing on rtt calc"
@ -537,7 +534,6 @@ struct sctp_sysctl {
#define SCTPCTL_RTTVAR_EQRET_MIN 0
#define SCTPCTL_RTTVAR_EQRET_MAX 1
#define SCTPCTL_RTTVAR_EQRET_DEFAULT 0
#endif
#if defined(SCTP_DEBUG)
/* debug: Configure debug output */

View File

@ -1777,6 +1777,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_TCB_UNLOCK(stcb);
}
}
break;
/* RS - Get socket option for pluggable stream scheduling */
case SCTP_PLUGGABLE_SS:
{
@ -2957,6 +2958,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_CC_RFC2581:
case SCTP_CC_HSTCP:
case SCTP_CC_HTCP:
case SCTP_CC_RTCC:
stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
stcb->asoc.congestion_control_module = av->assoc_value;
if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
@ -2976,6 +2978,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_CC_RFC2581:
case SCTP_CC_HSTCP:
case SCTP_CC_HTCP:
case SCTP_CC_RTCC:
SCTP_INP_WLOCK(inp);
inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
SCTP_INP_WUNLOCK(inp);
@ -2987,6 +2990,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
}
break;
case SCTP_CC_OPTION:
{
struct sctp_cc_option *cc_opt;