Skip to content

Commit

Permalink
tcp: Use segment size excluding tcp options for all cwnd calculations
Browse files Browse the repository at this point in the history
Avoid sending small segments by making sure that cwnd is usually
calculated in full (data) segment sizes. Especially during loss
recovery and retransmission scenarios.

Reviewed By: tuexen, #transport
Sponsored by: NetApp, Inc.
Differential Revision: https://reviews.freebsd.org/D47474
  • Loading branch information
rscheff committed Nov 14, 2024
1 parent 8f5a2e2 commit 22dcc81
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 54 deletions.
13 changes: 7 additions & 6 deletions sys/netinet/cc/cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ void
newreno_cc_post_recovery(struct cc_var *ccv)
{
int pipe;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

if (IN_FASTRECOVERY(CCV(ccv, t_flags))) {
/*
Expand All @@ -412,8 +413,7 @@ newreno_cc_post_recovery(struct cc_var *ccv)
* Ensure that cwnd does not collapse to 1 MSS under
* adverse conditions. Implements RFC6582
*/
CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) +
CCV(ccv, t_maxseg);
CCV(ccv, snd_cwnd) = max(pipe, mss) + mss;
else
CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
}
Expand Down Expand Up @@ -521,7 +521,7 @@ u_int
newreno_cc_cwnd_in_cong_avoid(struct cc_var *ccv)
{
u_int cw = CCV(ccv, snd_cwnd);
u_int incr = CCV(ccv, t_maxseg);
u_int incr = tcp_fixed_maxseg(ccv->tp);

KASSERT(cw > CCV(ccv, snd_ssthresh),
("congestion control state not in congestion avoidance\n"));
Expand Down Expand Up @@ -561,7 +561,8 @@ u_int
newreno_cc_cwnd_in_slow_start(struct cc_var *ccv)
{
u_int cw = CCV(ccv, snd_cwnd);
u_int incr = CCV(ccv, t_maxseg);
u_int mss = tcp_fixed_maxseg(ccv->tp);
u_int incr = mss;

KASSERT(cw <= CCV(ccv, snd_ssthresh),
("congestion control state not in slow start\n"));
Expand Down Expand Up @@ -599,9 +600,9 @@ newreno_cc_cwnd_in_slow_start(struct cc_var *ccv)
abc_val = V_tcp_abc_l_var;
if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max))
incr = min(ccv->bytes_this_ack,
ccv->nsegs * abc_val * CCV(ccv, t_maxseg));
ccv->nsegs * abc_val * mss);
else
incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
incr = min(ccv->bytes_this_ack, mss);
}
/* ABC is on by default, so incr equals 0 frequently. */
if (incr > 0)
Expand Down
9 changes: 5 additions & 4 deletions sys/netinet/cc/cc_cdg.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,27 +416,28 @@ cdg_window_increase(struct cc_var *ccv, int new_measurement)
{
struct cdg *cdg_data;
int incr, s_w_incr;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

cdg_data = ccv->cc_data;
incr = s_w_incr = 0;

if (CCV(ccv, snd_cwnd) <= CCV(ccv, snd_ssthresh)) {
/* Slow start. */
incr = CCV(ccv, t_maxseg);
incr = mss;
s_w_incr = incr;
cdg_data->window_incr = cdg_data->rtt_count = 0;
} else {
/* Congestion avoidance. */
if (new_measurement) {
s_w_incr = CCV(ccv, t_maxseg);
s_w_incr = mss;
if (V_cdg_alpha_inc == 0) {
incr = CCV(ccv, t_maxseg);
incr = mss;
} else {
if (++cdg_data->rtt_count >= V_cdg_alpha_inc) {
cdg_data->window_incr++;
cdg_data->rtt_count = 0;
}
incr = CCV(ccv, t_maxseg) *
incr = mss *
cdg_data->window_incr;
}
}
Expand Down
20 changes: 11 additions & 9 deletions sys/netinet/cc/cc_chd.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,11 @@ static __inline void
chd_window_decrease(struct cc_var *ccv)
{
unsigned long win;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

win = min(CCV(ccv, snd_wnd), CCV(ccv, snd_cwnd)) / CCV(ccv, t_maxseg);
win = min(CCV(ccv, snd_wnd), CCV(ccv, snd_cwnd)) / mss;
win -= max((win / 2), 1);
CCV(ccv, snd_ssthresh) = max(win, 2) * CCV(ccv, t_maxseg);
CCV(ccv, snd_ssthresh) = max(win, 2) * mss;
}

/*
Expand Down Expand Up @@ -190,6 +191,7 @@ chd_window_increase(struct cc_var *ccv, int new_measurement)
{
struct chd *chd_data;
int incr;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

chd_data = ccv->cc_data;
incr = 0;
Expand All @@ -201,23 +203,22 @@ chd_window_increase(struct cc_var *ccv, int new_measurement)
if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max)) {
/* Not due to RTO. */
incr = min(ccv->bytes_this_ack,
V_tcp_abc_l_var * CCV(ccv, t_maxseg));
V_tcp_abc_l_var * mss);
} else {
/* Due to RTO. */
incr = min(ccv->bytes_this_ack,
CCV(ccv, t_maxseg));
incr = min(ccv->bytes_this_ack, mss);
}
} else
incr = CCV(ccv, t_maxseg);
incr = mss;

} else { /* Congestion avoidance. */
if (V_tcp_do_rfc3465) {
if (ccv->flags & CCF_ABC_SENTAWND) {
ccv->flags &= ~CCF_ABC_SENTAWND;
incr = CCV(ccv, t_maxseg);
incr = mss;
}
} else if (new_measurement)
incr = CCV(ccv, t_maxseg);
incr = mss;
}

if (chd_data->shadow_w > 0) {
Expand Down Expand Up @@ -380,8 +381,9 @@ chd_cong_signal(struct cc_var *ccv, ccsignal_t signal_type)
}

if (chd_data->shadow_w > 0) {
uint32_t mss = tcp_fixed_maxseg(ccv->tp);
chd_data->shadow_w = max(chd_data->shadow_w /
CCV(ccv, t_maxseg) / 2, 2) * CCV(ccv, t_maxseg);
mss / 2, 2) * mss;
}
ENTER_FASTRECOVERY(CCV(ccv, t_flags));
break;
Expand Down
24 changes: 12 additions & 12 deletions sys/netinet/cc/cc_cubic.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ cubic_does_slow_start(struct cc_var *ccv, struct cubic *cubicd)
* doesn't rely on tcpcb vars.
*/
u_int cw = CCV(ccv, snd_cwnd);
u_int incr = CCV(ccv, t_maxseg);
uint32_t mss = tcp_fixed_maxseg(ccv->tp);
u_int incr = mss;
uint16_t abc_val;

cubicd->flags |= CUBICFLAG_IN_SLOWSTART;
Expand Down Expand Up @@ -216,10 +217,9 @@ cubic_does_slow_start(struct cc_var *ccv, struct cubic *cubicd)
}
if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max))
incr = min(ccv->bytes_this_ack,
ccv->nsegs * abc_val *
CCV(ccv, t_maxseg));
ccv->nsegs * abc_val * mss);
else
incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
incr = min(ccv->bytes_this_ack, mss);

/* Only if Hystart is enabled will the flag get set */
if (cubicd->flags & CUBICFLAG_HYSTART_IN_CSS) {
Expand All @@ -238,6 +238,7 @@ cubic_ack_received(struct cc_var *ccv, ccsignal_t type)
struct cubic *cubic_data;
unsigned long W_est, W_cubic;
int usecs_since_epoch;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

cubic_data = ccv->cc_data;
cubic_record_rtt(ccv);
Expand Down Expand Up @@ -277,8 +278,7 @@ cubic_ack_received(struct cc_var *ccv, ccsignal_t type)
cubic_data->flags &= ~(CUBICFLAG_IN_SLOWSTART |
CUBICFLAG_IN_APPLIMIT);
cubic_data->t_epoch = ticks;
cubic_data->K = cubic_k(cubic_data->W_max /
CCV(ccv, t_maxseg));
cubic_data->K = cubic_k(cubic_data->W_max / mss);
}
usecs_since_epoch = (ticks - cubic_data->t_epoch) * tick;
if (usecs_since_epoch < 0) {
Expand All @@ -298,7 +298,7 @@ cubic_ack_received(struct cc_var *ccv, ccsignal_t type)
W_cubic = cubic_cwnd(usecs_since_epoch +
cubic_data->mean_rtt_usecs,
cubic_data->W_max,
CCV(ccv, t_maxseg),
tcp_fixed_maxseg(ccv->tp),
cubic_data->K);

if (W_cubic < W_est) {
Expand Down Expand Up @@ -329,7 +329,7 @@ cubic_ack_received(struct cc_var *ccv, ccsignal_t type)
cubic_data->W_max < CCV(ccv, snd_cwnd)) {
cubic_data->W_max = CCV(ccv, snd_cwnd);
cubic_data->K = cubic_k(cubic_data->W_max /
CCV(ccv, t_maxseg));
tcp_fixed_maxseg(ccv->tp));
}
}
} else if (type == CC_ACK && !IN_RECOVERY(CCV(ccv, t_flags)) &&
Expand All @@ -351,7 +351,7 @@ cubic_after_idle(struct cc_var *ccv)
cubic_data = ccv->cc_data;

cubic_data->W_max = ulmax(cubic_data->W_max, CCV(ccv, snd_cwnd));
cubic_data->K = cubic_k(cubic_data->W_max / CCV(ccv, t_maxseg));
cubic_data->K = cubic_k(cubic_data->W_max / tcp_fixed_maxseg(ccv->tp));
if ((cubic_data->flags & CUBICFLAG_HYSTART_ENABLED) == 0) {
/*
* Re-enable hystart if we have been idle.
Expand Down Expand Up @@ -532,6 +532,7 @@ cubic_post_recovery(struct cc_var *ccv)
{
struct cubic *cubic_data;
int pipe;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

cubic_data = ccv->cc_data;
pipe = 0;
Expand All @@ -554,13 +555,12 @@ cubic_post_recovery(struct cc_var *ccv)
* Ensure that cwnd does not collapse to 1 MSS under
* adverse conditions. Implements RFC6582
*/
CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) +
CCV(ccv, t_maxseg);
CCV(ccv, snd_cwnd) = max(pipe, mss) + mss;
else
/* Update cwnd based on beta and adjusted W_max. */
CCV(ccv, snd_cwnd) = max(((uint64_t)cubic_data->W_max *
CUBIC_BETA) >> CUBIC_SHIFT,
2 * CCV(ccv, t_maxseg));
2 * mss);
}

/* Calculate the average RTT between congestion epochs. */
Expand Down
13 changes: 7 additions & 6 deletions sys/netinet/cc/cc_dctcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ dctcp_ack_received(struct cc_var *ccv, ccsignal_t type)
{
struct dctcp *dctcp_data;
int bytes_acked = 0;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

dctcp_data = ccv->cc_data;

Expand All @@ -125,7 +126,7 @@ dctcp_ack_received(struct cc_var *ccv, ccsignal_t type)
newreno_cc_ack_received(ccv, type);

if (type == CC_DUPACK)
bytes_acked = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
bytes_acked = min(ccv->bytes_this_ack, mss);

if (type == CC_ACK)
bytes_acked = ccv->bytes_this_ack;
Expand All @@ -138,16 +139,16 @@ dctcp_ack_received(struct cc_var *ccv, ccsignal_t type)
//XXRMS: For fluid-model DCTCP, update
//cwnd here during for RTT fairness
if (!dctcp_data->ece_prev
&& bytes_acked > CCV(ccv, t_maxseg)) {
&& bytes_acked > mss) {
dctcp_data->bytes_ecn +=
(bytes_acked - CCV(ccv, t_maxseg));
(bytes_acked - mss);
} else
dctcp_data->bytes_ecn += bytes_acked;
dctcp_data->ece_prev = 1;
} else {
if (dctcp_data->ece_prev
&& bytes_acked > CCV(ccv, t_maxseg))
dctcp_data->bytes_ecn += CCV(ccv, t_maxseg);
&& bytes_acked > mss)
dctcp_data->bytes_ecn += mss;
dctcp_data->ece_prev = 0;
}
dctcp_data->ece_curr = 0;
Expand Down Expand Up @@ -305,7 +306,7 @@ dctcp_cong_signal(struct cc_var *ccv, ccsignal_t type)
}
CCV(ccv, snd_cwnd) = mss;
dctcp_update_alpha(ccv);
dctcp_data->save_sndnxt += CCV(ccv, t_maxseg);
dctcp_data->save_sndnxt += mss;
dctcp_data->num_cong_events++;
break;
default:
Expand Down
15 changes: 8 additions & 7 deletions sys/netinet/cc/cc_htcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static void
htcp_ack_received(struct cc_var *ccv, ccsignal_t type)
{
struct htcp *htcp_data;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

htcp_data = ccv->cc_data;
htcp_record_rtt(ccv);
Expand Down Expand Up @@ -220,7 +221,7 @@ htcp_ack_received(struct cc_var *ccv, ccsignal_t type)
if (V_tcp_do_rfc3465) {
/* Increment cwnd by alpha segments. */
CCV(ccv, snd_cwnd) += htcp_data->alpha *
CCV(ccv, t_maxseg);
mss;
ccv->flags &= ~CCF_ABC_SENTAWND;
} else
/*
Expand All @@ -230,8 +231,8 @@ htcp_ack_received(struct cc_var *ccv, ccsignal_t type)
*/
CCV(ccv, snd_cwnd) += (((htcp_data->alpha <<
HTCP_SHIFT) / (max(1,
CCV(ccv, snd_cwnd) / CCV(ccv, t_maxseg)))) *
CCV(ccv, t_maxseg)) >> HTCP_SHIFT;
CCV(ccv, snd_cwnd) / mss))) *
mss) >> HTCP_SHIFT;
}
}
}
Expand Down Expand Up @@ -370,6 +371,7 @@ htcp_post_recovery(struct cc_var *ccv)
{
int pipe;
struct htcp *htcp_data;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

pipe = 0;
htcp_data = ccv->cc_data;
Expand All @@ -392,12 +394,11 @@ htcp_post_recovery(struct cc_var *ccv)
* Ensure that cwnd down not collape to 1 MSS under
* adverse conditions. Implements RFC6582
*/
CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) +
CCV(ccv, t_maxseg);
CCV(ccv, snd_cwnd) = max(pipe, mss) + mss;
else
CCV(ccv, snd_cwnd) = max(1, ((htcp_data->beta *
htcp_data->prev_cwnd / CCV(ccv, t_maxseg))
>> HTCP_SHIFT)) * CCV(ccv, t_maxseg);
htcp_data->prev_cwnd / mss)
>> HTCP_SHIFT)) * mss;
}
}

Expand Down
8 changes: 4 additions & 4 deletions sys/netinet/cc/cc_newreno.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,13 @@ static void
newreno_ack_received(struct cc_var *ccv, ccsignal_t type)
{
struct newreno *nreno;
uint32_t mss = tcp_fixed_maxseg(ccv->tp);

nreno = ccv->cc_data;
if (type == CC_ACK && !IN_RECOVERY(CCV(ccv, t_flags)) &&
(ccv->flags & CCF_CWND_LIMITED)) {
u_int cw = CCV(ccv, snd_cwnd);
u_int incr = CCV(ccv, t_maxseg);
u_int incr = mss;

/*
* Regular in-order ACK, open the congestion window.
Expand Down Expand Up @@ -324,10 +325,9 @@ newreno_ack_received(struct cc_var *ccv, ccsignal_t type)
}
if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max))
incr = min(ccv->bytes_this_ack,
ccv->nsegs * abc_val *
CCV(ccv, t_maxseg));
ccv->nsegs * abc_val * mss);
else
incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
incr = min(ccv->bytes_this_ack, mss);

/* Only if Hystart is enabled will the flag get set */
if (nreno->newreno_flags & CC_NEWRENO_HYSTART_IN_CSS) {
Expand Down
Loading

0 comments on commit 22dcc81

Please sign in to comment.