Commit 12a7f869 authored by David S. Miller's avatar David S. Miller

Merge branch 'tcp_bbr-PROBE_RTT-minor-bug-fixes'

Kevin Yang says:

====================
tcp_bbr: PROBE_RTT minor bug fixes

This series includes two minor bug fixes for the TCP BBR PROBE_RTT
mechanism, and one preparatory patch:

(1) A preparatory patch to reorganize the PROBE_RTT logic by refactoring
    (into its own function) the code to exit PROBE_RTT, since the next
    patch will be using that code in a new context.

(2) Fix: When BBR restarts from idle and if BBR is in PROBE_RTT mode,
    BBR should check if it's time to exit PROBE_RTT. If yes, then BBR
    should exit PROBE_RTT mode and restore the cwnd to its full value.

(3) Fix: Apply the PROBE_RTT cwnd cap even if the count of fully-ACKed
    packets is 0.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 431280ee 8e995bf1
...@@ -95,11 +95,10 @@ struct bbr { ...@@ -95,11 +95,10 @@ struct bbr {
u32 mode:3, /* current bbr_mode in state machine */ u32 mode:3, /* current bbr_mode in state machine */
prev_ca_state:3, /* CA state on previous ACK */ prev_ca_state:3, /* CA state on previous ACK */
packet_conservation:1, /* use packet conservation? */ packet_conservation:1, /* use packet conservation? */
restore_cwnd:1, /* decided to revert cwnd to old value */
round_start:1, /* start of packet-timed tx->ack round? */ round_start:1, /* start of packet-timed tx->ack round? */
idle_restart:1, /* restarting after idle? */ idle_restart:1, /* restarting after idle? */
probe_rtt_round_done:1, /* a BBR_PROBE_RTT round at 4 pkts? */ probe_rtt_round_done:1, /* a BBR_PROBE_RTT round at 4 pkts? */
unused:12, unused:13,
lt_is_sampling:1, /* taking long-term ("LT") samples now? */ lt_is_sampling:1, /* taking long-term ("LT") samples now? */
lt_rtt_cnt:7, /* round trips in long-term interval */ lt_rtt_cnt:7, /* round trips in long-term interval */
lt_use_bw:1; /* use lt_bw as our bw estimate? */ lt_use_bw:1; /* use lt_bw as our bw estimate? */
...@@ -175,6 +174,8 @@ static const u32 bbr_lt_bw_diff = 4000 / 8; ...@@ -175,6 +174,8 @@ static const u32 bbr_lt_bw_diff = 4000 / 8;
/* If we estimate we're policed, use lt_bw for this many round trips: */ /* If we estimate we're policed, use lt_bw for this many round trips: */
static const u32 bbr_lt_bw_max_rtts = 48; static const u32 bbr_lt_bw_max_rtts = 48;
static void bbr_check_probe_rtt_done(struct sock *sk);
/* Do we estimate that STARTUP filled the pipe? */ /* Do we estimate that STARTUP filled the pipe? */
static bool bbr_full_bw_reached(const struct sock *sk) static bool bbr_full_bw_reached(const struct sock *sk)
{ {
...@@ -309,6 +310,8 @@ static void bbr_cwnd_event(struct sock *sk, enum tcp_ca_event event) ...@@ -309,6 +310,8 @@ static void bbr_cwnd_event(struct sock *sk, enum tcp_ca_event event)
*/ */
if (bbr->mode == BBR_PROBE_BW) if (bbr->mode == BBR_PROBE_BW)
bbr_set_pacing_rate(sk, bbr_bw(sk), BBR_UNIT); bbr_set_pacing_rate(sk, bbr_bw(sk), BBR_UNIT);
else if (bbr->mode == BBR_PROBE_RTT)
bbr_check_probe_rtt_done(sk);
} }
} }
...@@ -396,17 +399,11 @@ static bool bbr_set_cwnd_to_recover_or_restore( ...@@ -396,17 +399,11 @@ static bool bbr_set_cwnd_to_recover_or_restore(
cwnd = tcp_packets_in_flight(tp) + acked; cwnd = tcp_packets_in_flight(tp) + acked;
} else if (prev_state >= TCP_CA_Recovery && state < TCP_CA_Recovery) { } else if (prev_state >= TCP_CA_Recovery && state < TCP_CA_Recovery) {
/* Exiting loss recovery; restore cwnd saved before recovery. */ /* Exiting loss recovery; restore cwnd saved before recovery. */
bbr->restore_cwnd = 1; cwnd = max(cwnd, bbr->prior_cwnd);
bbr->packet_conservation = 0; bbr->packet_conservation = 0;
} }
bbr->prev_ca_state = state; bbr->prev_ca_state = state;
if (bbr->restore_cwnd) {
/* Restore cwnd after exiting loss recovery or PROBE_RTT. */
cwnd = max(cwnd, bbr->prior_cwnd);
bbr->restore_cwnd = 0;
}
if (bbr->packet_conservation) { if (bbr->packet_conservation) {
*new_cwnd = max(cwnd, tcp_packets_in_flight(tp) + acked); *new_cwnd = max(cwnd, tcp_packets_in_flight(tp) + acked);
return true; /* yes, using packet conservation */ return true; /* yes, using packet conservation */
...@@ -423,10 +420,10 @@ static void bbr_set_cwnd(struct sock *sk, const struct rate_sample *rs, ...@@ -423,10 +420,10 @@ static void bbr_set_cwnd(struct sock *sk, const struct rate_sample *rs,
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
struct bbr *bbr = inet_csk_ca(sk); struct bbr *bbr = inet_csk_ca(sk);
u32 cwnd = 0, target_cwnd = 0; u32 cwnd = tp->snd_cwnd, target_cwnd = 0;
if (!acked) if (!acked)
return; goto done; /* no packet fully ACKed; just apply caps */
if (bbr_set_cwnd_to_recover_or_restore(sk, rs, acked, &cwnd)) if (bbr_set_cwnd_to_recover_or_restore(sk, rs, acked, &cwnd))
goto done; goto done;
...@@ -748,6 +745,20 @@ static void bbr_check_drain(struct sock *sk, const struct rate_sample *rs) ...@@ -748,6 +745,20 @@ static void bbr_check_drain(struct sock *sk, const struct rate_sample *rs)
bbr_reset_probe_bw_mode(sk); /* we estimate queue is drained */ bbr_reset_probe_bw_mode(sk); /* we estimate queue is drained */
} }
static void bbr_check_probe_rtt_done(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
struct bbr *bbr = inet_csk_ca(sk);
if (!(bbr->probe_rtt_done_stamp &&
after(tcp_jiffies32, bbr->probe_rtt_done_stamp)))
return;
bbr->min_rtt_stamp = tcp_jiffies32; /* wait a while until PROBE_RTT */
tp->snd_cwnd = max(tp->snd_cwnd, bbr->prior_cwnd);
bbr_reset_mode(sk);
}
/* The goal of PROBE_RTT mode is to have BBR flows cooperatively and /* The goal of PROBE_RTT mode is to have BBR flows cooperatively and
* periodically drain the bottleneck queue, to converge to measure the true * periodically drain the bottleneck queue, to converge to measure the true
* min_rtt (unloaded propagation delay). This allows the flows to keep queues * min_rtt (unloaded propagation delay). This allows the flows to keep queues
...@@ -806,12 +817,8 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs) ...@@ -806,12 +817,8 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs)
} else if (bbr->probe_rtt_done_stamp) { } else if (bbr->probe_rtt_done_stamp) {
if (bbr->round_start) if (bbr->round_start)
bbr->probe_rtt_round_done = 1; bbr->probe_rtt_round_done = 1;
if (bbr->probe_rtt_round_done && if (bbr->probe_rtt_round_done)
after(tcp_jiffies32, bbr->probe_rtt_done_stamp)) { bbr_check_probe_rtt_done(sk);
bbr->min_rtt_stamp = tcp_jiffies32;
bbr->restore_cwnd = 1; /* snap to prior_cwnd */
bbr_reset_mode(sk);
}
} }
} }
/* Restart after idle ends only once we process a new S/ACK for data */ /* Restart after idle ends only once we process a new S/ACK for data */
...@@ -862,7 +869,6 @@ static void bbr_init(struct sock *sk) ...@@ -862,7 +869,6 @@ static void bbr_init(struct sock *sk)
bbr->has_seen_rtt = 0; bbr->has_seen_rtt = 0;
bbr_init_pacing_rate_from_rtt(sk); bbr_init_pacing_rate_from_rtt(sk);
bbr->restore_cwnd = 0;
bbr->round_start = 0; bbr->round_start = 0;
bbr->idle_restart = 0; bbr->idle_restart = 0;
bbr->full_bw_reached = 0; bbr->full_bw_reached = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment