Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc

Issue 2990163002: Almost full implementation of BBR's core. (Closed)
Patch Set: Fixed a small bug. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 * 9 *
10 */ 10 */
11 11
12 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" 12 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h"
13 13
14 #include <stdlib.h> 14 #include <stdlib.h>
15 #include <algorithm>
15 16
16 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win dow.h" 17 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win dow.h"
17 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_ filter.h" 18 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_ filter.h"
18 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter .h" 19 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter .h"
19 20
20 namespace webrtc { 21 namespace webrtc {
21 namespace testing { 22 namespace testing {
22 namespace bwe { 23 namespace bwe {
23 namespace { 24 namespace {
24 const int kFeedbackIntervalsMs = 3; 25 const int kFeedbackIntervalsMs = 5;
25 // BBR uses this value to double sending rate each round trip. Design document 26 // BBR uses this value to double sending rate each round trip. Design document
26 // suggests using this value. 27 // suggests using this value.
27 const float kHighGain = 2.885f; 28 const float kHighGain = 2.885f;
28 // BBR uses this value to drain queues created during STARTUP in one round trip 29 // BBR uses this value to drain queues created during STARTUP in one round trip
29 // time. 30 // time.
30 const float kDrainGain = 1 / kHighGain; 31 const float kDrainGain = 1 / kHighGain;
31 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from 32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from
32 // experiments, according to the design document. 33 // experiments, according to the design document.
33 const float kStartupGrowthTarget = 1.25f; 34 const float kStartupGrowthTarget = 1.25f;
34 const int kMaxRoundsWithoutGrowth = 3; 35 const int kMaxRoundsWithoutGrowth = 3;
35 // Pacing gain values for Probe Bandwidth mode. 36 // Pacing gain values for Probe Bandwidth mode.
36 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; 37 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1};
37 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); 38 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]);
38 // The least amount of rounds PROBE_RTT mode should last. 39 // Least amount number of rounds PROBE_RTT should last.
terelius 2017/08/08 17:32:40 nit: Remove "amount"?
gnish1 2017/08/09 10:05:53 Done.
39 const int kProbeRttDurationRounds = 1; 40 const int kProbeRttDurationRounds = 1;
40 // The least amount of milliseconds PROBE_RTT mode should last. 41 // The least amount of milliseconds PROBE_RTT mode should last.
41 const int kProbeRttDurationMs = 200; 42 const int kProbeRttDurationMs = 200;
42 // Gain value for congestion window for assuming that network has no queues. 43 // Gain value for congestion window for assuming that network has no queues.
43 const float kTargetCongestionWindowGain = 1; 44 const float kTargetCongestionWindowGain = 1;
44 // Gain value for congestion window in PROBE_BW mode. In theory it should be 45 // Gain value for congestion window in PROBE_BW mode. In theory it should be
45 // equal to 1, but in practice because of delayed acks and the way networks 46 // equal to 1, but in practice because of delayed acks and the way networks
46 // work, it is nice to have some extra room in congestion window for full link 47 // work, it is nice to have some extra room in congestion window for full link
47 // utilization. Value chosen by observations on different tests. 48 // utilization. Value chosen by observations on different tests.
48 const float kCruisingCongestionWindowGain = 1.5f; 49 const float kCruisingCongestionWindowGain = 1.5f;
49 // Expiration time for min_rtt sample, which is set to 10 seconds according to 50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation
50 // BBR design doc. 51 // tool.
51 const int64_t kMinRttFilterSizeMs = 10000; 52 const float kRecoveryPacingGain = 0.5f;
53 // Congestion window gain specific for Recovery mode. Chosen by experiments in
54 // simulation tool.
55 const float kRecoveryCongestionWindowGain = 1.5f;
56 // Number of rounds over which average rtt is stored for Recovery mode.
57 const size_t kPastRttsFilterSize = 1;
58 // Threshold to assume average rtt has increased for a round. Chosen by
terelius 2017/08/08 17:32:40 rtt -> RTT. Same below.
gnish1 2017/08/09 10:05:53 Done.
59 // experiments in simulation tool.
60 const float kRttIncreaseThreshold = 3;
61 // Threshold to assume average rtt has decreased for a round. Chosen by
62 // experiments in simulation tool.
63 const float kRttDecreaseThreshold = 1.5f;
terelius 2017/08/08 17:32:40 I wouldn't call it a "decrease" if the RTT is 1.5
gnish1 2017/08/09 10:05:53 Yes, but I didn't want to create another mode simi
52 } // namespace 64 } // namespace
53 65
54 BbrBweSender::BbrBweSender(Clock* clock) 66 BbrBweSender::BbrBweSender(Clock* clock)
55 : BweSender(0), 67 : BweSender(0),
56 clock_(clock), 68 clock_(clock),
57 mode_(STARTUP), 69 mode_(STARTUP),
58 max_bandwidth_filter_(new MaxBandwidthFilter()), 70 max_bandwidth_filter_(new MaxBandwidthFilter()),
59 min_rtt_filter_(new MinRttFilter()), 71 min_rtt_filter_(new MinRttFilter()),
60 congestion_window_(new CongestionWindow()), 72 congestion_window_(new CongestionWindow()),
61 rand_(new Random(time(NULL))), 73 rand_(new Random(time(NULL))),
62 round_count_(0), 74 round_count_(0),
63 last_packet_sent_(0),
64 round_trip_end_(0), 75 round_trip_end_(0),
65 full_bandwidth_reached_(false), 76 full_bandwidth_reached_(false),
66 cycle_start_time_ms_(0), 77 cycle_start_time_ms_(0),
67 cycle_index_(0), 78 cycle_index_(0),
68 prior_in_flight_(0), 79 bytes_acked_(0),
69 probe_rtt_start_time_ms_(0), 80 probe_rtt_start_time_ms_(0),
70 minimum_congestion_window_start_time_ms_(), 81 minimum_congestion_window_start_time_ms_(0),
71 minimum_congestion_window_start_round_(0) { 82 minimum_congestion_window_start_round_(0),
83 bytes_sent_(0),
84 last_packet_sent_sequence_number_(0),
85 last_packet_acked_sequence_number_(0),
86 last_packet_ack_time_(0),
87 last_packet_send_time_(0),
88 pacing_rate_bps_(0),
89 last_packet_send_time_during_high_gain_ms_(-1),
90 data_sent_before_high_gain_started_bytes_(-1),
91 data_sent_before_high_gain_ended_bytes_(-1),
92 first_packet_ack_time_during_high_gain_ms_(-1),
93 last_packet_ack_time_during_high_gain_ms_(-1),
94 data_acked_before_high_gain_started_bytes_(-1),
95 data_acked_before_high_gain_ended_bytes_(-1),
96 first_packet_seq_num_during_high_gain_(-1),
97 last_packet_seq_num_during_high_gain_(-1),
98 high_gain_over_(false),
99 packet_stats_(),
100 past_rtts_() {
72 // Initially enter Startup mode. 101 // Initially enter Startup mode.
73 EnterStartup(); 102 EnterStartup();
74 } 103 }
75 104
76 BbrBweSender::~BbrBweSender() {} 105 BbrBweSender::~BbrBweSender() {}
77 106
78 int BbrBweSender::GetFeedbackIntervalMs() const { 107 int BbrBweSender::GetFeedbackIntervalMs() const {
79 return kFeedbackIntervalsMs; 108 return kFeedbackIntervalsMs;
80 } 109 }
81 110
111 void BbrBweSender::CalculatePacingRate() {
112 pacing_rate_bps_ =
113 max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_;
114 }
115
116 void BbrBweSender::HandleLoss(uint64_t last_acked_packet,
117 uint64_t recently_acked_packet) {
118 // Logic specific to wrapping sequence numbers.
119 if (!last_acked_packet)
120 return;
121 for (uint16_t i = last_acked_packet + 1;
122 AheadOrAt<uint64_t>(recently_acked_packet - 1, i); i++)
terelius 2017/08/08 17:32:40 I'd prefer curly braces around the loop body becau
terelius 2017/08/08 17:32:40 Is it safe to subtract one here, or could the subt
gnish1 2017/08/09 10:05:53 It will underflow, but it is safe, the loop will w
gnish1 2017/08/09 10:05:53 Done.
123 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes);
124 }
125
126 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) {
127 uint64_t last_round = 0;
128 if (!past_rtts_.empty())
129 last_round = past_rtts_.back().round;
130
131 // Try to add the sample to the last round.
132 if (last_round == round_count_ && !past_rtts_.empty()) {
133 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms;
134 past_rtts_.back().num_samples++;
135 } else {
136 // If the sample belongs to a new round, keep number of rounds in the window
137 // equal to |kPastRttsFilterSize|.
138 if (past_rtts_.size() == kPastRttsFilterSize)
139 past_rtts_.pop_front();
140 past_rtts_.push_back(
141 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_));
142 }
143 }
144
82 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { 145 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {
146 int64_t now_ms = clock_->TimeInMilliseconds();
147 last_packet_ack_time_ = now_ms;
83 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); 148 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback);
84 // feedback_vector holds values of acknowledged packets' sequence numbers. 149 // feedback_vector holds values of acknowledged packets' sequence numbers.
85 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); 150 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector();
86 // Check if new round started for the connection. Round is the period of time 151 // Go through all the packets acked, update variables/containers accordingly.
87 // from sending packet to its acknowledgement. 152 for (uint64_t f : feedback_vector) {
terelius 2017/08/08 17:32:40 Better name than f?
gnish1 2017/08/09 10:05:53 Done.
153 // Completing packet information with a recently received ack.
154 PacketStats* packet = &packet_stats_[f];
155 bytes_acked_ += packet->payload_size_bytes;
156 packet->data_sent_bytes = bytes_sent_;
157 packet->last_sent_packet_send_time_ms = last_packet_send_time_;
158 packet->data_acked_bytes = bytes_acked_;
159 packet->ack_time_ms = now_ms;
160 // Logic specific to applying "bucket" to high gain, in order to have
161 // quicker ramp-up. We check if we started receiving acks for the packets
162 // sent during high gain phase.
163 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) {
164 first_packet_ack_time_during_high_gain_ms_ = now_ms;
165 data_acked_before_high_gain_started_bytes_ = bytes_acked_;
166 }
167 // If the last packet of high gain phase has been acked, high gain phase is
168 // over.
169 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) {
170 last_packet_ack_time_during_high_gain_ms_ = now_ms;
171 data_acked_before_high_gain_ended_bytes_ = bytes_acked_;
172 high_gain_over_ = true;
173 }
174 // Notify pacer that an ack was received, to adjust data inflight.
175 // TODO(gnish): Add implementation for BitrateObserver class, to notify
176 // pacer about incoming acks.
177 congestion_window_->AckReceived(packet->payload_size_bytes);
178 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number);
179 last_packet_acked_sequence_number_ = packet->sequence_number;
180 // Logic for wrapping sequence numbers. If round started with packet number
181 // x, it can never end on y, if x > y. That could happen when sequence
182 // numbers are wrapped after some point.
183 if (packet->sequence_number == 0)
184 round_trip_end_ = 0;
185 }
186 // Check if new round started for the connection.
88 bool new_round_started = false; 187 bool new_round_started = false;
89 if (!feedback_vector.empty()) { 188 if (!feedback_vector.empty()) {
90 uint64_t last_acked_packet = *feedback_vector.rbegin(); 189 if (last_packet_acked_sequence_number_ > round_trip_end_) {
91 if (last_acked_packet > round_trip_end_) {
92 new_round_started = true; 190 new_round_started = true;
93 round_count_++; 191 round_count_++;
94 round_trip_end_ = last_packet_sent_; 192 round_trip_end_ = last_packet_sent_sequence_number_;
95 } 193 }
96 } 194 }
195 bool min_rtt_expired = false;
196 min_rtt_expired =
197 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_);
97 if (new_round_started && !full_bandwidth_reached_) { 198 if (new_round_started && !full_bandwidth_reached_) {
98 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( 199 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached(
99 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); 200 kStartupGrowthTarget, kMaxRoundsWithoutGrowth);
100 } 201 }
101 int now_ms = clock_->TimeInMilliseconds();
102 switch (mode_) { 202 switch (mode_) {
103 break; 203 break;
104 case STARTUP: 204 case STARTUP:
105 TryExitingStartup(); 205 TryExitingStartup();
106 break; 206 break;
107 case DRAIN: 207 case DRAIN:
108 TryExitingDrain(now_ms); 208 TryExitingDrain(now_ms);
109 break; 209 break;
110 case PROBE_BW: 210 case PROBE_BW:
111 TryUpdatingCyclePhase(now_ms); 211 TryUpdatingCyclePhase(now_ms);
112 break; 212 break;
113 case PROBE_RTT: 213 case PROBE_RTT:
114 TryExitingProbeRtt(now_ms, 0); 214 TryExitingProbeRtt(now_ms, round_count_);
215 break;
216 case RECOVERY:
217 TryExitingRecovery(new_round_started);
115 break; 218 break;
116 } 219 }
117 TryEnteringProbeRtt(now_ms); 220 TryEnteringProbeRtt(now_ms);
118 // TODO(gnish): implement functions updating congestion window and pacing rate 221 TryEnteringRecovery(new_round_started); // Comment this line to disable
119 // controllers. 222 // entering Recovery mode.
223 for (uint64_t f : feedback_vector)
224 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms);
225 CalculatePacingRate();
226 // Make sure we don't get stuck when pacing_rate is 0, because of simulation
227 // tool specifics.
228 if (!pacing_rate_bps_)
229 pacing_rate_bps_ = 100;
230 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000);
231 // TODO(gnish): Add implementation for BitrateObserver class to update pacing
232 // rate for the pacer and the encoder.
120 } 233 }
121 234
122 size_t BbrBweSender::TargetCongestionWindow(float gain) { 235 size_t BbrBweSender::TargetCongestionWindow(float gain) {
123 size_t target_congestion_window = 236 size_t target_congestion_window =
124 congestion_window_->GetTargetCongestionWindow( 237 congestion_window_->GetTargetCongestionWindow(
125 max_bandwidth_filter_->max_bandwidth_estimate_bps(), 238 max_bandwidth_filter_->max_bandwidth_estimate_bps(),
126 min_rtt_filter_->min_rtt_ms(), gain); 239 min_rtt_filter_->min_rtt_ms(), gain);
127 return target_congestion_window; 240 return target_congestion_window;
128 } 241 }
129 242
130 bool BbrBweSender::UpdateBandwidthAndMinRtt() { 243 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample(
131 return false; 244 size_t data_sent_bytes,
245 int64_t send_time_delta_ms,
246 size_t data_acked_bytes,
247 int64_t ack_time_delta_ms) {
248 rtc::Optional<int64_t> bandwidth_sample;
249 if (send_time_delta_ms > 0)
250 *bandwidth_sample = data_sent_bytes * 8000 / send_time_delta_ms;
251 rtc::Optional<int64_t> ack_rate;
252 if (ack_time_delta_ms > 0)
253 *ack_rate = data_acked_bytes * 8000 / ack_time_delta_ms;
254 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to
255 // ack_rate.
256 if (!bandwidth_sample)
257 bandwidth_sample = ack_rate;
258 if (bandwidth_sample && ack_rate)
259 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate);
260 return bandwidth_sample;
261 }
262
263 void BbrBweSender::AddSampleForHighGain() {
264 if (!high_gain_over_)
265 return;
266 high_gain_over_ = false;
267 // Calculate data sent/acked and time elapsed only for packets sent during
268 // high gain phase.
269 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ -
270 data_sent_before_high_gain_started_bytes_;
271 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ -
terelius 2017/08/08 17:32:40 Won't this overestimate the bandwidth? If we are s
gnish1 2017/08/09 10:05:53 It could overestimate bw, as normal bw calculation
terelius 2017/08/11 09:27:52 What I am saying is that the calculation seems to
gnish1 2017/08/12 11:57:31 Done.
272 *first_packet_send_time_during_high_gain_ms_;
273 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ -
274 data_acked_before_high_gain_started_bytes_;
275 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ -
276 first_packet_ack_time_during_high_gain_ms_;
277 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
278 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms);
279 if (bandwidth_sample)
280 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_);
281 first_packet_send_time_during_high_gain_ms_.reset();
282 }
283
284 bool BbrBweSender::UpdateBandwidthAndMinRtt(
285 int64_t now_ms,
286 const std::vector<uint64_t>& feedback_vector,
287 int64_t bytes_acked) {
288 rtc::Optional<int64_t> min_rtt_sample_ms;
289 for (uint64_t f : feedback_vector) {
290 PacketStats packet = packet_stats_[f];
291 size_t data_sent_bytes =
292 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes;
293 int64_t send_time_delta_ms =
294 packet.last_sent_packet_send_time_ms - packet.send_time_ms;
295 size_t data_acked_bytes = packet.data_acked_bytes -
296 packet.data_acked_before_last_acked_packet_bytes;
297 int64_t ack_time_delta_ms =
298 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms;
299 rtc::Optional<int64_t> bandwidth_sample =
300 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms,
301 data_acked_bytes, ack_time_delta_ms);
302 if (bandwidth_sample)
303 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample,
304 round_count_);
305 AddSampleForHighGain(); // Comment to disable bucket for high gain.
306 if (!min_rtt_sample_ms)
307 *min_rtt_sample_ms = packet.ack_time_ms - packet.send_time_ms;
308 else
309 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms,
310 packet.ack_time_ms - packet.send_time_ms);
311 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms,
312 packet.ack_time_ms - packet.send_time_ms);
313 }
314 if (!min_rtt_sample_ms)
315 return false;
316 bool min_rtt_expired = min_rtt_filter_->MinRttExpired(now_ms);
317 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms);
318 return min_rtt_expired;
132 } 319 }
133 320
134 void BbrBweSender::EnterStartup() { 321 void BbrBweSender::EnterStartup() {
135 mode_ = STARTUP; 322 mode_ = STARTUP;
136 pacing_gain_ = kHighGain; 323 pacing_gain_ = kHighGain;
137 congestion_window_gain_ = kHighGain; 324 congestion_window_gain_ = kHighGain;
138 } 325 }
139 326
140 void BbrBweSender::TryExitingStartup() { 327 void BbrBweSender::TryExitingStartup() {
141 if (full_bandwidth_reached_) { 328 if (full_bandwidth_reached_) {
(...skipping 25 matching lines...) Expand all
167 354
168 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { 355 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {
169 // Each phase should last rougly min_rtt ms time. 356 // Each phase should last rougly min_rtt ms time.
170 bool advance_cycle_phase = false; 357 bool advance_cycle_phase = false;
171 if (min_rtt_filter_->min_rtt_ms()) 358 if (min_rtt_filter_->min_rtt_ms())
172 advance_cycle_phase = 359 advance_cycle_phase =
173 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); 360 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms();
174 // If BBR was probing and it couldn't increase data inflight sufficiently in 361 // If BBR was probing and it couldn't increase data inflight sufficiently in
175 // one min_rtt time, continue probing. BBR design doc isn't clear about this, 362 // one min_rtt time, continue probing. BBR design doc isn't clear about this,
176 // but condition helps in quicker ramp-up and performs better. 363 // but condition helps in quicker ramp-up and performs better.
177 if (pacing_gain_ > 1.0 && 364 if (pacing_gain_ > 1.0 && congestion_window_->data_inflight() <
178 prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) 365 TargetCongestionWindow(pacing_gain_))
179 advance_cycle_phase = false; 366 advance_cycle_phase = false;
180 // If BBR has already drained queues there is no point in continuing draining 367 // If BBR has already drained queues there is no point in continuing draining
181 // phase. 368 // phase.
182 if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) 369 if (pacing_gain_ < 1.0 &&
370 congestion_window_->data_inflight() <= TargetCongestionWindow(1))
183 advance_cycle_phase = true; 371 advance_cycle_phase = true;
184 if (advance_cycle_phase) { 372 if (advance_cycle_phase) {
185 cycle_index_++; 373 cycle_index_++;
186 cycle_index_ %= kGainCycleLength; 374 cycle_index_ %= kGainCycleLength;
187 pacing_gain_ = kPacingGain[cycle_index_]; 375 pacing_gain_ = kPacingGain[cycle_index_];
188 cycle_start_time_ms_ = now_ms; 376 cycle_start_time_ms_ = now_ms;
189 } 377 }
190 } 378 }
191 379
192 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { 380 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {
193 if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && 381 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) {
194 mode_ != PROBE_RTT) {
195 mode_ = PROBE_RTT; 382 mode_ = PROBE_RTT;
196 pacing_gain_ = 1; 383 pacing_gain_ = 1;
197 probe_rtt_start_time_ms_ = now_ms; 384 probe_rtt_start_time_ms_ = now_ms;
198 minimum_congestion_window_start_time_ms_.reset(); 385 minimum_congestion_window_start_time_ms_.reset();
199 } 386 }
200 } 387 }
201 388
202 // minimum_congestion_window_start_time_'s value is set to the first moment when 389 // |minimum_congestion_window_start_time_|'s value is set to the first moment
203 // data inflight was less then kMinimumCongestionWindowBytes, we should make 390 // when data inflight was less then
204 // sure that BBR has been in PROBE_RTT mode for at least one round or 200ms. 391 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that
392 // BBR has been in PROBE_RTT mode for at least one round or 200ms.
205 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { 393 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) {
206 if (!minimum_congestion_window_start_time_ms_) { 394 if (!minimum_congestion_window_start_time_ms_) {
207 if (congestion_window_->data_inflight() <= 395 if (congestion_window_->data_inflight() <=
208 CongestionWindow::kMinimumCongestionWindowBytes) { 396 CongestionWindow::kMinimumCongestionWindowBytes) {
209 *minimum_congestion_window_start_time_ms_ = now_ms; 397 *minimum_congestion_window_start_time_ms_ = now_ms;
210 minimum_congestion_window_start_round_ = round; 398 minimum_congestion_window_start_round_ = round;
211 } 399 }
212 } else { 400 } else {
213 if (now_ms - *minimum_congestion_window_start_time_ms_ >= 401 if (now_ms - *minimum_congestion_window_start_time_ms_ >=
214 kProbeRttDurationMs && 402 kProbeRttDurationMs &&
215 round - minimum_congestion_window_start_round_ >= 403 round - minimum_congestion_window_start_round_ >=
216 kProbeRttDurationRounds) 404 kProbeRttDurationRounds)
217 EnterProbeBw(now_ms); 405 EnterProbeBw(now_ms);
218 } 406 }
219 } 407 }
220 408
409 void BbrBweSender::TryEnteringRecovery(bool new_round_started) {
410 // If we are already in Recovery don't try to enter.
411 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_)
412 return;
413 uint64_t increased_rtt_round_counter = 0;
414 // If average rtt for past |kPastRttsFilterSize| rounds has been more than
415 // some multiplier of min_rtt_ms enter Recovery.
416 for (BbrBweSender::AverageRtt i : past_rtts_) {
417 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >=
418 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold)
419 increased_rtt_round_counter++;
420 }
421 if (increased_rtt_round_counter < kPastRttsFilterSize)
422 return;
423 mode_ = RECOVERY;
424 pacing_gain_ = kRecoveryPacingGain;
425 congestion_window_gain_ = kRecoveryCongestionWindowGain;
426 }
427
428 void BbrBweSender::TryExitingRecovery(bool new_round_started) {
429 if (mode_ != RECOVERY || !new_round_started || !full_bandwidth_reached_)
430 return;
431 // If average rtt for the past round has decreased sufficiently exit Recovery.
432 if (!past_rtts_.empty()) {
433 BbrBweSender::AverageRtt last_round_sample = past_rtts_.back();
434 if (last_round_sample.sum_of_rtts_ms / last_round_sample.num_samples <=
435 *min_rtt_filter_->min_rtt_ms() * kRttDecreaseThreshold) {
436 EnterProbeBw(clock_->TimeInMilliseconds());
437 }
438 }
439 }
440
221 int64_t BbrBweSender::TimeUntilNextProcess() { 441 int64_t BbrBweSender::TimeUntilNextProcess() {
222 return 100; 442 return 50;
223 } 443 }
224 444
225 void BbrBweSender::OnPacketsSent(const Packets& packets) { 445 void BbrBweSender::OnPacketsSent(const Packets& packets) {
226 last_packet_sent_ = 446 for (Packet* packet : packets) {
227 static_cast<const MediaPacket*>(packets.back())->sequence_number(); 447 if (packet->GetPacketType() == Packet::kMedia) {
448 MediaPacket* media_packet = static_cast<MediaPacket*>(packet);
449 bytes_sent_ += media_packet->payload_size();
450 PacketStats packet_stats = PacketStats(
451 media_packet->sequence_number(), 0,
452 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_,
453 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_);
454 packet_stats_[media_packet->sequence_number()] = packet_stats;
455 last_packet_send_time_ = media_packet->sender_timestamp_ms();
456 last_packet_sent_sequence_number_ = media_packet->sequence_number();
457 // If this is the first packet sent for high gain phase, save data for it.
458 if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) {
459 *first_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
460 data_sent_before_high_gain_started_bytes_ = bytes_sent_;
461 first_packet_seq_num_during_high_gain_ =
462 media_packet->sequence_number();
463 }
464 // This condition ensures that |last_packet_seq_num_during_high_gain_|
465 // will contain a sequence number of the last packet sent during high gain
466 // phase.
467 if (pacing_gain_ > 1) {
468 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
469 data_sent_before_high_gain_ended_bytes_ = bytes_sent_;
470 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number();
471 }
472 congestion_window_->PacketSent(media_packet->payload_size());
473 }
474 }
228 } 475 }
229 476
230 void BbrBweSender::Process() {} 477 void BbrBweSender::Process() {}
231 478
232 BbrBweReceiver::BbrBweReceiver(int flow_id) 479 BbrBweReceiver::BbrBweReceiver(int flow_id)
233 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} 480 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {}
234 481
235 BbrBweReceiver::~BbrBweReceiver() {} 482 BbrBweReceiver::~BbrBweReceiver() {}
236 483
237 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, 484 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms,
238 const MediaPacket& media_packet) {} 485 const MediaPacket& media_packet) {}
239 486
240 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { 487 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) {
241 return nullptr; 488 return nullptr;
242 } 489 }
243 } // namespace bwe 490 } // namespace bwe
244 } // namespace testing 491 } // namespace testing
245 } // namespace webrtc 492 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698