Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/cc/cc_dctcp.c
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | struct dctcp { | ||||
int alpha; /* the fraction of marked bytes */ | int alpha; /* the fraction of marked bytes */ | ||||
int ce_prev; /* CE state of the last segment */ | int ce_prev; /* CE state of the last segment */ | ||||
tcp_seq save_sndnxt; /* end sequence number of the current window */ | tcp_seq save_sndnxt; /* end sequence number of the current window */ | ||||
int ece_curr; /* ECE flag in this segment */ | int ece_curr; /* ECE flag in this segment */ | ||||
int ece_prev; /* ECE flag in the last segment */ | int ece_prev; /* ECE flag in the last segment */ | ||||
uint32_t num_cong_events; /* # of congestion events */ | uint32_t num_cong_events; /* # of congestion events */ | ||||
}; | }; | ||||
static MALLOC_DEFINE(M_dctcp, "dctcp data", | |||||
"Per connection data required for the dctcp algorithm"); | |||||
static void dctcp_ack_received(struct cc_var *ccv, uint16_t type); | static void dctcp_ack_received(struct cc_var *ccv, uint16_t type); | ||||
static void dctcp_after_idle(struct cc_var *ccv); | static void dctcp_after_idle(struct cc_var *ccv); | ||||
static void dctcp_cb_destroy(struct cc_var *ccv); | static void dctcp_cb_destroy(struct cc_var *ccv); | ||||
static int dctcp_cb_init(struct cc_var *ccv); | static int dctcp_cb_init(struct cc_var *ccv, void *ptr); | ||||
static void dctcp_cong_signal(struct cc_var *ccv, uint32_t type); | static void dctcp_cong_signal(struct cc_var *ccv, uint32_t type); | ||||
static void dctcp_conn_init(struct cc_var *ccv); | static void dctcp_conn_init(struct cc_var *ccv); | ||||
static void dctcp_post_recovery(struct cc_var *ccv); | static void dctcp_post_recovery(struct cc_var *ccv); | ||||
static void dctcp_ecnpkt_handler(struct cc_var *ccv); | static void dctcp_ecnpkt_handler(struct cc_var *ccv); | ||||
static void dctcp_update_alpha(struct cc_var *ccv); | static void dctcp_update_alpha(struct cc_var *ccv); | ||||
static size_t dctcp_data_sz(void); | |||||
struct cc_algo dctcp_cc_algo = { | struct cc_algo dctcp_cc_algo = { | ||||
.name = "dctcp", | .name = "dctcp", | ||||
.ack_received = dctcp_ack_received, | .ack_received = dctcp_ack_received, | ||||
.cb_destroy = dctcp_cb_destroy, | .cb_destroy = dctcp_cb_destroy, | ||||
.cb_init = dctcp_cb_init, | .cb_init = dctcp_cb_init, | ||||
.cong_signal = dctcp_cong_signal, | .cong_signal = dctcp_cong_signal, | ||||
.conn_init = dctcp_conn_init, | .conn_init = dctcp_conn_init, | ||||
.post_recovery = dctcp_post_recovery, | .post_recovery = dctcp_post_recovery, | ||||
.ecnpkt_handler = dctcp_ecnpkt_handler, | .ecnpkt_handler = dctcp_ecnpkt_handler, | ||||
.after_idle = dctcp_after_idle, | .after_idle = dctcp_after_idle, | ||||
.cc_data_sz = dctcp_data_sz, | |||||
}; | }; | ||||
static void | static void | ||||
dctcp_ack_received(struct cc_var *ccv, uint16_t type) | dctcp_ack_received(struct cc_var *ccv, uint16_t type) | ||||
{ | { | ||||
struct dctcp *dctcp_data; | struct dctcp *dctcp_data; | ||||
int bytes_acked = 0; | int bytes_acked = 0; | ||||
dctcp_data = ccv->cc_data; | dctcp_data = ccv->cc_data; | ||||
if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { | if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { | ||||
/* | /* | ||||
* DCTCP doesn't treat receipt of ECN marked packet as a | * DCTCP doesn't treat receipt of ECN marked packet as a | ||||
* congestion event. Thus, DCTCP always executes the ACK | * congestion event. Thus, DCTCP always executes the ACK | ||||
* processing out of congestion recovery. | * processing out of congestion recovery. | ||||
*/ | */ | ||||
if (IN_CONGRECOVERY(CCV(ccv, t_flags))) { | if (IN_CONGRECOVERY(CCV(ccv, t_flags))) { | ||||
EXIT_CONGRECOVERY(CCV(ccv, t_flags)); | EXIT_CONGRECOVERY(CCV(ccv, t_flags)); | ||||
newreno_cc_algo.ack_received(ccv, type); | common_cc_ack_received(ccv, type); | ||||
ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ||||
} else | } else | ||||
newreno_cc_algo.ack_received(ccv, type); | common_cc_ack_received(ccv, type); | ||||
if (type == CC_DUPACK) | if (type == CC_DUPACK) | ||||
bytes_acked = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg)); | bytes_acked = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg)); | ||||
if (type == CC_ACK) | if (type == CC_ACK) | ||||
bytes_acked = ccv->bytes_this_ack; | bytes_acked = ccv->bytes_this_ack; | ||||
/* Update total bytes. */ | /* Update total bytes. */ | ||||
Show All 21 Lines | if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { | ||||
/* | /* | ||||
* Update the fraction of marked bytes at the end of | * Update the fraction of marked bytes at the end of | ||||
* current window size. | * current window size. | ||||
*/ | */ | ||||
if (!IN_FASTRECOVERY(CCV(ccv, t_flags)) && | if (!IN_FASTRECOVERY(CCV(ccv, t_flags)) && | ||||
SEQ_GT(ccv->curack, dctcp_data->save_sndnxt)) | SEQ_GT(ccv->curack, dctcp_data->save_sndnxt)) | ||||
dctcp_update_alpha(ccv); | dctcp_update_alpha(ccv); | ||||
} else | } else | ||||
newreno_cc_algo.ack_received(ccv, type); | common_cc_ack_received(ccv, type); | ||||
} | } | ||||
static size_t | |||||
dctcp_data_sz(void) | |||||
{ | |||||
return (sizeof(struct dctcp)); | |||||
} | |||||
static void | static void | ||||
dctcp_after_idle(struct cc_var *ccv) | dctcp_after_idle(struct cc_var *ccv) | ||||
{ | { | ||||
struct dctcp *dctcp_data; | struct dctcp *dctcp_data; | ||||
if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { | if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { | ||||
dctcp_data = ccv->cc_data; | dctcp_data = ccv->cc_data; | ||||
/* Initialize internal parameters after idle time */ | /* Initialize internal parameters after idle time */ | ||||
dctcp_data->bytes_ecn = 0; | dctcp_data->bytes_ecn = 0; | ||||
dctcp_data->bytes_total = 0; | dctcp_data->bytes_total = 0; | ||||
dctcp_data->save_sndnxt = CCV(ccv, snd_nxt); | dctcp_data->save_sndnxt = CCV(ccv, snd_nxt); | ||||
dctcp_data->alpha = V_dctcp_alpha; | dctcp_data->alpha = V_dctcp_alpha; | ||||
dctcp_data->ece_curr = 0; | dctcp_data->ece_curr = 0; | ||||
dctcp_data->ece_prev = 0; | dctcp_data->ece_prev = 0; | ||||
dctcp_data->num_cong_events = 0; | dctcp_data->num_cong_events = 0; | ||||
} | } | ||||
newreno_cc_algo.after_idle(ccv); | common_cc_after_idle(ccv); | ||||
} | } | ||||
static void | static void | ||||
dctcp_cb_destroy(struct cc_var *ccv) | dctcp_cb_destroy(struct cc_var *ccv) | ||||
{ | { | ||||
free(ccv->cc_data, M_dctcp); | free(ccv->cc_data, M_CC_MEM); | ||||
} | } | ||||
static int | static int | ||||
dctcp_cb_init(struct cc_var *ccv) | dctcp_cb_init(struct cc_var *ccv, void *ptr) | ||||
{ | { | ||||
struct dctcp *dctcp_data; | struct dctcp *dctcp_data; | ||||
dctcp_data = malloc(sizeof(struct dctcp), M_dctcp, M_NOWAIT|M_ZERO); | if (ptr == NULL) { | ||||
dctcp_data = malloc(sizeof(struct dctcp), M_CC_MEM, M_NOWAIT|M_ZERO); | |||||
if (dctcp_data == NULL) | if (dctcp_data == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} else | |||||
dctcp_data = ptr; | |||||
/* Initialize some key variables with sensible defaults. */ | /* Initialize some key variables with sensible defaults. */ | ||||
dctcp_data->bytes_ecn = 0; | dctcp_data->bytes_ecn = 0; | ||||
dctcp_data->bytes_total = 0; | dctcp_data->bytes_total = 0; | ||||
/* | /* | ||||
* When alpha is set to 0 in the beginning, DCTCP sender transfers as | * When alpha is set to 0 in the beginning, DCTCP sender transfers as | ||||
* much data as possible until the value converges which may expand the | * much data as possible until the value converges which may expand the | ||||
* queueing delay at the switch. When alpha is set to 1, queueing delay | * queueing delay at the switch. When alpha is set to 1, queueing delay | ||||
* is kept small. | * is kept small. | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | case CC_RTO: | ||||
2) * mss; | 2) * mss; | ||||
CCV(ccv, snd_cwnd) = mss; | CCV(ccv, snd_cwnd) = mss; | ||||
dctcp_update_alpha(ccv); | dctcp_update_alpha(ccv); | ||||
dctcp_data->save_sndnxt += CCV(ccv, t_maxseg); | dctcp_data->save_sndnxt += CCV(ccv, t_maxseg); | ||||
dctcp_data->num_cong_events++; | dctcp_data->num_cong_events++; | ||||
break; | break; | ||||
} | } | ||||
} else | } else | ||||
newreno_cc_algo.cong_signal(ccv, type); | common_cc_cong_signal(ccv, type); | ||||
} | } | ||||
static void | static void | ||||
dctcp_conn_init(struct cc_var *ccv) | dctcp_conn_init(struct cc_var *ccv) | ||||
{ | { | ||||
struct dctcp *dctcp_data; | struct dctcp *dctcp_data; | ||||
dctcp_data = ccv->cc_data; | dctcp_data = ccv->cc_data; | ||||
if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) | if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) | ||||
dctcp_data->save_sndnxt = CCV(ccv, snd_nxt); | dctcp_data->save_sndnxt = CCV(ccv, snd_nxt); | ||||
} | } | ||||
/* | /* | ||||
* Perform any necessary tasks before we exit congestion recovery. | * Perform any necessary tasks before we exit congestion recovery. | ||||
*/ | */ | ||||
static void | static void | ||||
dctcp_post_recovery(struct cc_var *ccv) | dctcp_post_recovery(struct cc_var *ccv) | ||||
{ | { | ||||
newreno_cc_algo.post_recovery(ccv); | common_cc_post_recovery(ccv); | ||||
if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) | if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) | ||||
dctcp_update_alpha(ccv); | dctcp_update_alpha(ccv); | ||||
} | } | ||||
/* | /* | ||||
* Execute an additional ECN processing using ECN field in IP header | * Execute an additional ECN processing using ECN field in IP header | ||||
* and the CWR bit in TCP header. | * and the CWR bit in TCP header. | ||||
▲ Show 20 Lines • Show All 148 Lines • Show Last 20 Lines |