Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/cc/cc_cubic.c
Show First 20 Lines • Show All 280 Lines • ▼ Show 20 Lines | cubic_cong_signal(struct cc_var *ccv, uint32_t type) | ||||
cubic_data = ccv->cc_data; | cubic_data = ccv->cc_data; | ||||
switch (type) { | switch (type) { | ||||
case CC_NDUPACK: | case CC_NDUPACK: | ||||
if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { | if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { | ||||
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | ||||
cubic_ssthresh_update(ccv); | cubic_ssthresh_update(ccv); | ||||
cubic_data->flags |= CUBICFLAG_CONG_EVENT; | cubic_data->flags |= CUBICFLAG_CONG_EVENT; | ||||
cubic_data->prev_max_cwnd = cubic_data->max_cwnd; | cubic_data->t_last_cong = ticks; | ||||
cubic_data->max_cwnd = CCV(ccv, snd_cwnd); | |||||
cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); | cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); | ||||
} | } | ||||
ENTER_RECOVERY(CCV(ccv, t_flags)); | ENTER_RECOVERY(CCV(ccv, t_flags)); | ||||
} | } | ||||
break; | break; | ||||
case CC_ECN: | case CC_ECN: | ||||
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | ||||
cubic_ssthresh_update(ccv); | cubic_ssthresh_update(ccv); | ||||
cubic_data->flags |= CUBICFLAG_CONG_EVENT; | cubic_data->flags |= CUBICFLAG_CONG_EVENT; | ||||
cubic_data->prev_max_cwnd = cubic_data->max_cwnd; | |||||
cubic_data->max_cwnd = CCV(ccv, snd_cwnd); | |||||
cubic_data->t_last_cong = ticks; | cubic_data->t_last_cong = ticks; | ||||
cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); | cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); | ||||
CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh); | CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh); | ||||
ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ||||
} | } | ||||
break; | break; | ||||
case CC_RTO: | case CC_RTO: | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
cubic_post_recovery(struct cc_var *ccv) | cubic_post_recovery(struct cc_var *ccv) | ||||
{ | { | ||||
struct cubic *cubic_data; | struct cubic *cubic_data; | ||||
int pipe; | int pipe; | ||||
cubic_data = ccv->cc_data; | cubic_data = ccv->cc_data; | ||||
pipe = 0; | pipe = 0; | ||||
/* Fast convergence heuristic. */ | |||||
if (cubic_data->max_cwnd < cubic_data->prev_max_cwnd) | |||||
cubic_data->max_cwnd = (cubic_data->max_cwnd * CUBIC_FC_FACTOR) | |||||
>> CUBIC_SHIFT; | |||||
if (IN_FASTRECOVERY(CCV(ccv, t_flags))) { | if (IN_FASTRECOVERY(CCV(ccv, t_flags))) { | ||||
/* | /* | ||||
* If inflight data is less than ssthresh, set cwnd | * If inflight data is less than ssthresh, set cwnd | ||||
* conservatively to avoid a burst of data, as suggested in | * conservatively to avoid a burst of data, as suggested in | ||||
* the NewReno RFC. Otherwise, use the CUBIC method. | * the NewReno RFC. Otherwise, use the CUBIC method. | ||||
* | * | ||||
* XXXLAS: Find a way to do this without needing curack | * XXXLAS: Find a way to do this without needing curack | ||||
*/ | */ | ||||
Show All 10 Lines | if (pipe < CCV(ccv, snd_ssthresh)) | ||||
CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) + | CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) + | ||||
CCV(ccv, t_maxseg); | CCV(ccv, t_maxseg); | ||||
else | else | ||||
/* Update cwnd based on beta and adjusted max_cwnd. */ | /* Update cwnd based on beta and adjusted max_cwnd. */ | ||||
CCV(ccv, snd_cwnd) = max(((uint64_t)cubic_data->max_cwnd * | CCV(ccv, snd_cwnd) = max(((uint64_t)cubic_data->max_cwnd * | ||||
CUBIC_BETA) >> CUBIC_SHIFT, | CUBIC_BETA) >> CUBIC_SHIFT, | ||||
2 * CCV(ccv, t_maxseg)); | 2 * CCV(ccv, t_maxseg)); | ||||
} | } | ||||
cubic_data->t_last_cong = ticks; | |||||
/* Calculate the average RTT between congestion epochs. */ | /* Calculate the average RTT between congestion epochs. */ | ||||
if (cubic_data->epoch_ack_count > 0 && | if (cubic_data->epoch_ack_count > 0 && | ||||
cubic_data->sum_rtt_ticks >= cubic_data->epoch_ack_count) { | cubic_data->sum_rtt_ticks >= cubic_data->epoch_ack_count) { | ||||
cubic_data->mean_rtt_ticks = (int)(cubic_data->sum_rtt_ticks / | cubic_data->mean_rtt_ticks = (int)(cubic_data->sum_rtt_ticks / | ||||
cubic_data->epoch_ack_count); | cubic_data->epoch_ack_count); | ||||
} | } | ||||
cubic_data->epoch_ack_count = 0; | cubic_data->epoch_ack_count = 0; | ||||
cubic_data->sum_rtt_ticks = 0; | cubic_data->sum_rtt_ticks = 0; | ||||
cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); | |||||
} | } | ||||
/* | /* | ||||
* Record the min RTT and sum samples for the epoch average RTT calculation. | * Record the min RTT and sum samples for the epoch average RTT calculation. | ||||
*/ | */ | ||||
static void | static void | ||||
cubic_record_rtt(struct cc_var *ccv) | cubic_record_rtt(struct cc_var *ccv) | ||||
{ | { | ||||
Show All 37 Lines | |||||
/* | /* | ||||
* Update the ssthresh in the event of congestion. | * Update the ssthresh in the event of congestion. | ||||
*/ | */ | ||||
static void | static void | ||||
cubic_ssthresh_update(struct cc_var *ccv) | cubic_ssthresh_update(struct cc_var *ccv) | ||||
{ | { | ||||
struct cubic *cubic_data; | struct cubic *cubic_data; | ||||
uint32_t ssthresh; | uint32_t ssthresh; | ||||
uint32_t cwnd; | |||||
cubic_data = ccv->cc_data; | cubic_data = ccv->cc_data; | ||||
cwnd = CCV(ccv, snd_cwnd); | |||||
/* Fast convergence heuristic. */ | |||||
if (cwnd < cubic_data->max_cwnd) { | |||||
cwnd = ((uint64_t)cwnd * CUBIC_FC_FACTOR) >> CUBIC_SHIFT; | |||||
} | |||||
cubic_data->prev_max_cwnd = cubic_data->max_cwnd; | |||||
cubic_data->max_cwnd = cwnd; | |||||
/* | /* | ||||
* On the first congestion event, set ssthresh to cwnd * 0.5, on | * On the first congestion event, set ssthresh to cwnd * 0.5 | ||||
* subsequent congestion events, set it to cwnd * beta. | * and reduce max_cwnd to cwnd * beta. This aligns the cubic concave | ||||
* region appropriately. On subsequent congestion events, set | |||||
* ssthresh to cwnd * beta. | |||||
*/ | */ | ||||
if ((cubic_data->flags & CUBICFLAG_CONG_EVENT) == 0) | if ((cubic_data->flags & CUBICFLAG_CONG_EVENT) == 0) { | ||||
ssthresh = CCV(ccv, snd_cwnd) >> 1; | ssthresh = cwnd >> 1; | ||||
else | cubic_data->max_cwnd = ((uint64_t)cwnd * | ||||
ssthresh = ((uint64_t)CCV(ccv, snd_cwnd) * | |||||
CUBIC_BETA) >> CUBIC_SHIFT; | CUBIC_BETA) >> CUBIC_SHIFT; | ||||
} else { | |||||
ssthresh = ((uint64_t)cwnd * | |||||
CUBIC_BETA) >> CUBIC_SHIFT; | |||||
} | |||||
CCV(ccv, snd_ssthresh) = max(ssthresh, 2 * CCV(ccv, t_maxseg)); | CCV(ccv, snd_ssthresh) = max(ssthresh, 2 * CCV(ccv, t_maxseg)); | ||||
} | } | ||||
DECLARE_CC_MODULE(cubic, &cubic_cc_algo); | DECLARE_CC_MODULE(cubic, &cubic_cc_algo); | ||||
MODULE_VERSION(cubic, 1); | MODULE_VERSION(cubic, 1); |