aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2019-07-29 09:19:48 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2019-07-29 09:19:48 +0000
commitbb63f59b229f28f5bd059740d2fa5e0ba55dad11 (patch)
tree5905131f7129eb91bbc7a4303779b2e112af4394 /sys/netinet
parent333ba164d621907e6c8794fd64f671f1ea4870d9 (diff)
downloadsrc-bb63f59b229f28f5bd059740d2fa5e0ba55dad11.tar.gz
src-bb63f59b229f28f5bd059740d2fa5e0ba55dad11.zip
When performing after_idle() or post_recovery(), don't disable the
DCTCP specific methods. Also fallthrough NewReno for non ECN capable TCP connections and improve the integer arithmetic. Obtained from: Richard Scheffenegger MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D20550
Notes
Notes: svn path=/head/; revision=350404
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/cc/cc_dctcp.c135
1 files changed, 70 insertions, 65 deletions
diff --git a/sys/netinet/cc/cc_dctcp.c b/sys/netinet/cc/cc_dctcp.c
index 2e11253fb1d2..51df6a85c9ef 100644
--- a/sys/netinet/cc/cc_dctcp.c
+++ b/sys/netinet/cc/cc_dctcp.c
@@ -123,7 +123,7 @@ dctcp_ack_received(struct cc_var *ccv, uint16_t type)
newreno_cc_algo.ack_received(ccv, type);
if (type == CC_DUPACK)
- bytes_acked = CCV(ccv, t_maxseg);
+ bytes_acked = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
if (type == CC_ACK)
bytes_acked = ccv->bytes_this_ack;
@@ -133,6 +133,8 @@ dctcp_ack_received(struct cc_var *ccv, uint16_t type)
/* Update total marked bytes. */
if (dctcp_data->ece_curr) {
+ //XXRMS: For fluid-model DCTCP, update
+ //cwnd here during for RTT fairness
if (!dctcp_data->ece_prev
&& bytes_acked > CCV(ccv, t_maxseg)) {
dctcp_data->bytes_ecn +=
@@ -166,18 +168,20 @@ dctcp_after_idle(struct cc_var *ccv)
{
struct dctcp *dctcp_data;
- dctcp_data = ccv->cc_data;
+ if (CCV(ccv, t_flags) & TF_ECN_PERMIT) {
+ dctcp_data = ccv->cc_data;
- /* Initialize internal parameters after idle time */
- dctcp_data->bytes_ecn = 0;
- dctcp_data->bytes_total = 0;
- dctcp_data->save_sndnxt = CCV(ccv, snd_nxt);
- dctcp_data->alpha = V_dctcp_alpha;
- dctcp_data->ece_curr = 0;
- dctcp_data->ece_prev = 0;
- dctcp_data->num_cong_events = 0;
+ /* Initialize internal parameters after idle time */
+ dctcp_data->bytes_ecn = 0;
+ dctcp_data->bytes_total = 0;
+ dctcp_data->save_sndnxt = CCV(ccv, snd_nxt);
+ dctcp_data->alpha = V_dctcp_alpha;
+ dctcp_data->ece_curr = 0;
+ dctcp_data->ece_prev = 0;
+ dctcp_data->num_cong_events = 0;
+ }
- dctcp_cc_algo.after_idle = newreno_cc_algo.after_idle;
+ newreno_cc_algo.after_idle(ccv);
}
static void
@@ -228,63 +232,66 @@ static void
dctcp_cong_signal(struct cc_var *ccv, uint32_t type)
{
struct dctcp *dctcp_data;
- u_int win, mss;
+ u_int cwin, mss;
- dctcp_data = ccv->cc_data;
- win = CCV(ccv, snd_cwnd);
- mss = CCV(ccv, t_maxseg);
-
- switch (type) {
- case CC_NDUPACK:
- if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+ if (CCV(ccv, t_flags) & TF_ECN_PERMIT) {
+ dctcp_data = ccv->cc_data;
+ cwin = CCV(ccv, snd_cwnd);
+ mss = CCV(ccv, t_maxseg);
+
+ switch (type) {
+ case CC_NDUPACK:
+ if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+ if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
+ CCV(ccv, snd_ssthresh) =
+ max(cwin / 2, 2 * mss);
+ dctcp_data->num_cong_events++;
+ } else {
+ /* cwnd has already updated as congestion
+ * recovery. Reverse cwnd value using
+ * snd_cwnd_prev and recalculate snd_ssthresh
+ */
+ cwin = CCV(ccv, snd_cwnd_prev);
+ CCV(ccv, snd_ssthresh) =
+ max(cwin / 2, 2 * mss);
+ }
+ ENTER_RECOVERY(CCV(ccv, t_flags));
+ }
+ break;
+ case CC_ECN:
+ /*
+ * Save current snd_cwnd when the host encounters both
+ * congestion recovery and fast recovery.
+ */
+ CCV(ccv, snd_cwnd_prev) = cwin;
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
- CCV(ccv, snd_ssthresh) = mss *
- max(win / 2 / mss, 2);
- dctcp_data->num_cong_events++;
- } else {
- /* cwnd has already updated as congestion
- * recovery. Reverse cwnd value using
- * snd_cwnd_prev and recalculate snd_ssthresh
- */
- win = CCV(ccv, snd_cwnd_prev);
- CCV(ccv, snd_ssthresh) =
- max(win / 2 / mss, 2) * mss;
+ if (V_dctcp_slowstart &&
+ dctcp_data->num_cong_events++ == 0) {
+ CCV(ccv, snd_ssthresh) =
+ max(cwin / 2, 2 * mss);
+ dctcp_data->alpha = MAX_ALPHA_VALUE;
+ dctcp_data->bytes_ecn = 0;
+ dctcp_data->bytes_total = 0;
+ dctcp_data->save_sndnxt = CCV(ccv, snd_nxt);
+ } else
+ CCV(ccv, snd_ssthresh) =
+ max((cwin - (((uint64_t)cwin *
+ dctcp_data->alpha) >> (DCTCP_SHIFT+1))),
+ 2 * mss);
+ CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
+ ENTER_CONGRECOVERY(CCV(ccv, t_flags));
}
- ENTER_RECOVERY(CCV(ccv, t_flags));
- }
- break;
- case CC_ECN:
- /*
- * Save current snd_cwnd when the host encounters both
- * congestion recovery and fast recovery.
- */
- CCV(ccv, snd_cwnd_prev) = win;
- if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
- if (V_dctcp_slowstart &&
- dctcp_data->num_cong_events++ == 0) {
- CCV(ccv, snd_ssthresh) =
- mss * max(win / 2 / mss, 2);
- dctcp_data->alpha = MAX_ALPHA_VALUE;
- dctcp_data->bytes_ecn = 0;
- dctcp_data->bytes_total = 0;
- dctcp_data->save_sndnxt = CCV(ccv, snd_nxt);
- } else
- CCV(ccv, snd_ssthresh) = max((win - ((win *
- dctcp_data->alpha) >> 11)) / mss, 2) * mss;
- CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
- ENTER_CONGRECOVERY(CCV(ccv, t_flags));
- }
- dctcp_data->ece_curr = 1;
- break;
- case CC_RTO:
- if (CCV(ccv, t_flags) & TF_ECN_PERMIT) {
+ dctcp_data->ece_curr = 1;
+ break;
+ case CC_RTO:
CCV(ccv, t_flags) |= TF_ECN_SND_CWR;
dctcp_update_alpha(ccv);
dctcp_data->save_sndnxt += CCV(ccv, t_maxseg);
dctcp_data->num_cong_events++;
+ break;
}
- break;
- }
+ } else
+ newreno_cc_algo.cong_signal(ccv, type);
}
static void
@@ -304,7 +311,7 @@ dctcp_conn_init(struct cc_var *ccv)
static void
dctcp_post_recovery(struct cc_var *ccv)
{
- dctcp_cc_algo.post_recovery = newreno_cc_algo.post_recovery;
+ newreno_cc_algo.post_recovery(ccv);
if (CCV(ccv, t_flags) & TF_ECN_PERMIT)
dctcp_update_alpha(ccv);
@@ -330,8 +337,8 @@ dctcp_ecnpkt_handler(struct cc_var *ccv)
delay_ack = 1;
/*
- * DCTCP responses an ACK immediately when the CE state
- * in between this segment and the last segment is not same.
+ * DCTCP responds with an ACK immediately when the CE state
+ * in between this segment and the last segment has changed.
*/
if (ccflag & CCF_IPHDR_CE) {
if (!dctcp_data->ce_prev && (ccflag & CCF_DELACK))
@@ -351,8 +358,6 @@ dctcp_ecnpkt_handler(struct cc_var *ccv)
if (delay_ack == 0)
ccv->flags |= CCF_ACKNOW;
- else
- ccv->flags &= ~CCF_ACKNOW;
}
/*