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

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 patch failure 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 number of rounds PROBE_RTT should last.
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
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;
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<uint16_t>(recently_acked_packet - 1, i); i++) {
123 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes);
124 }
125 }
126
127 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) {
128 uint64_t last_round = 0;
129 if (!past_rtts_.empty())
130 last_round = past_rtts_.back().round;
131
132 // Try to add the sample to the last round.
133 if (last_round == round_count_ && !past_rtts_.empty()) {
134 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms;
135 past_rtts_.back().num_samples++;
136 } else {
137 // If the sample belongs to a new round, keep number of rounds in the window
138 // equal to |kPastRttsFilterSize|.
139 if (past_rtts_.size() == kPastRttsFilterSize)
140 past_rtts_.pop_front();
141 past_rtts_.push_back(
142 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_));
143 }
144 }
145
82 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { 146 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {
147 int64_t now_ms = clock_->TimeInMilliseconds();
148 last_packet_ack_time_ = now_ms;
83 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); 149 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback);
84 // feedback_vector holds values of acknowledged packets' sequence numbers. 150 // feedback_vector holds values of acknowledged packets' sequence numbers.
85 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); 151 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 152 // Go through all the packets acked, update variables/containers accordingly.
87 // from sending packet to its acknowledgement. 153 for (uint16_t sequence_number : feedback_vector) {
154 // Completing packet information with a recently received ack.
155 PacketStats* packet = &packet_stats_[sequence_number];
156 bytes_acked_ += packet->payload_size_bytes;
157 packet->data_sent_bytes = bytes_sent_;
158 packet->last_sent_packet_send_time_ms = last_packet_send_time_;
159 packet->data_acked_bytes = bytes_acked_;
160 packet->ack_time_ms = now_ms;
161 // Logic specific to applying "bucket" to high gain, in order to have
162 // quicker ramp-up. We check if we started receiving acks for the packets
163 // sent during high gain phase.
164 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) {
165 first_packet_ack_time_during_high_gain_ms_ = now_ms;
166 // Substracting half of the packet's size to avoid overestimation.
167 data_acked_before_high_gain_started_bytes_ =
168 bytes_acked_ - packet->payload_size_bytes / 2;
169 }
170 // If the last packet of high gain phase has been acked, high gain phase is
171 // over.
172 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) {
173 last_packet_ack_time_during_high_gain_ms_ = now_ms;
174 data_acked_before_high_gain_ended_bytes_ =
175 bytes_acked_ - packet->payload_size_bytes / 2;
176 high_gain_over_ = true;
177 }
178 // Notify pacer that an ack was received, to adjust data inflight.
179 // TODO(gnish): Add implementation for BitrateObserver class, to notify
180 // pacer about incoming acks.
181 congestion_window_->AckReceived(packet->payload_size_bytes);
182 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number);
183 last_packet_acked_sequence_number_ = packet->sequence_number;
184 // Logic for wrapping sequence numbers. If round started with packet number
185 // x, it can never end on y, if x > y. That could happen when sequence
186 // numbers are wrapped after some point.
187 if (packet->sequence_number == 0)
188 round_trip_end_ = 0;
189 }
190 // Check if new round started for the connection.
88 bool new_round_started = false; 191 bool new_round_started = false;
89 if (!feedback_vector.empty()) { 192 if (!feedback_vector.empty()) {
90 uint64_t last_acked_packet = *feedback_vector.rbegin(); 193 if (last_packet_acked_sequence_number_ > round_trip_end_) {
91 if (last_acked_packet > round_trip_end_) {
92 new_round_started = true; 194 new_round_started = true;
93 round_count_++; 195 round_count_++;
94 round_trip_end_ = last_packet_sent_; 196 round_trip_end_ = last_packet_sent_sequence_number_;
95 } 197 }
96 } 198 }
199 bool min_rtt_expired = false;
200 min_rtt_expired =
201 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_);
97 if (new_round_started && !full_bandwidth_reached_) { 202 if (new_round_started && !full_bandwidth_reached_) {
98 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( 203 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached(
99 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); 204 kStartupGrowthTarget, kMaxRoundsWithoutGrowth);
100 } 205 }
101 int now_ms = clock_->TimeInMilliseconds();
102 switch (mode_) { 206 switch (mode_) {
103 break; 207 break;
104 case STARTUP: 208 case STARTUP:
105 TryExitingStartup(); 209 TryExitingStartup();
106 break; 210 break;
107 case DRAIN: 211 case DRAIN:
108 TryExitingDrain(now_ms); 212 TryExitingDrain(now_ms);
109 break; 213 break;
110 case PROBE_BW: 214 case PROBE_BW:
111 TryUpdatingCyclePhase(now_ms); 215 TryUpdatingCyclePhase(now_ms);
112 break; 216 break;
113 case PROBE_RTT: 217 case PROBE_RTT:
114 TryExitingProbeRtt(now_ms, 0); 218 TryExitingProbeRtt(now_ms, round_count_);
219 break;
220 case RECOVERY:
221 TryExitingRecovery(new_round_started);
115 break; 222 break;
116 } 223 }
117 TryEnteringProbeRtt(now_ms); 224 TryEnteringProbeRtt(now_ms);
118 // TODO(gnish): implement functions updating congestion window and pacing rate 225 TryEnteringRecovery(new_round_started); // Comment this line to disable
119 // controllers. 226 // entering Recovery mode.
227 for (uint64_t f : feedback_vector)
228 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms);
229 CalculatePacingRate();
230 // Make sure we don't get stuck when pacing_rate is 0, because of simulation
231 // tool specifics.
232 if (!pacing_rate_bps_)
233 pacing_rate_bps_ = 100;
234 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000);
235 // TODO(gnish): Add implementation for BitrateObserver class to update pacing
236 // rate for the pacer and the encoder.
120 } 237 }
121 238
122 size_t BbrBweSender::TargetCongestionWindow(float gain) { 239 size_t BbrBweSender::TargetCongestionWindow(float gain) {
123 size_t target_congestion_window = 240 size_t target_congestion_window =
124 congestion_window_->GetTargetCongestionWindow( 241 congestion_window_->GetTargetCongestionWindow(
125 max_bandwidth_filter_->max_bandwidth_estimate_bps(), 242 max_bandwidth_filter_->max_bandwidth_estimate_bps(),
126 min_rtt_filter_->min_rtt_ms(), gain); 243 min_rtt_filter_->min_rtt_ms(), gain);
127 return target_congestion_window; 244 return target_congestion_window;
128 } 245 }
129 246
130 bool BbrBweSender::UpdateBandwidthAndMinRtt() { 247 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample(
131 return false; 248 size_t data_sent_bytes,
249 int64_t send_time_delta_ms,
250 size_t data_acked_bytes,
251 int64_t ack_time_delta_ms) {
252 rtc::Optional<int64_t> bandwidth_sample;
253 if (send_time_delta_ms > 0)
254 *bandwidth_sample = data_sent_bytes * 8000 / send_time_delta_ms;
255 rtc::Optional<int64_t> ack_rate;
256 if (ack_time_delta_ms > 0)
257 *ack_rate = data_acked_bytes * 8000 / ack_time_delta_ms;
258 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to
259 // ack_rate.
260 if (!bandwidth_sample)
261 bandwidth_sample = ack_rate;
262 if (bandwidth_sample && ack_rate)
263 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate);
264 return bandwidth_sample;
265 }
266
267 void BbrBweSender::AddSampleForHighGain() {
268 if (!high_gain_over_)
269 return;
270 high_gain_over_ = false;
271 // Calculate data sent/acked and time elapsed only for packets sent during
272 // high gain phase.
273 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ -
274 data_sent_before_high_gain_started_bytes_;
275 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ -
276 *first_packet_send_time_during_high_gain_ms_;
277 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ -
278 data_acked_before_high_gain_started_bytes_;
279 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ -
280 first_packet_ack_time_during_high_gain_ms_;
281 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
282 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms);
283 if (bandwidth_sample)
284 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_);
285 first_packet_send_time_during_high_gain_ms_.reset();
286 }
287
288 bool BbrBweSender::UpdateBandwidthAndMinRtt(
289 int64_t now_ms,
290 const std::vector<uint64_t>& feedback_vector,
291 int64_t bytes_acked) {
292 rtc::Optional<int64_t> min_rtt_sample_ms;
293 for (uint64_t f : feedback_vector) {
294 PacketStats packet = packet_stats_[f];
295 size_t data_sent_bytes =
296 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes;
297 int64_t send_time_delta_ms =
298 packet.last_sent_packet_send_time_ms - packet.send_time_ms;
299 size_t data_acked_bytes = packet.data_acked_bytes -
300 packet.data_acked_before_last_acked_packet_bytes;
301 int64_t ack_time_delta_ms =
302 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms;
303 rtc::Optional<int64_t> bandwidth_sample =
304 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms,
305 data_acked_bytes, ack_time_delta_ms);
306 if (bandwidth_sample)
307 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample,
308 round_count_);
309 AddSampleForHighGain(); // Comment to disable bucket for high gain.
310 if (!min_rtt_sample_ms)
311 *min_rtt_sample_ms = packet.ack_time_ms - packet.send_time_ms;
312 else
313 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms,
314 packet.ack_time_ms - packet.send_time_ms);
315 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms,
316 packet.ack_time_ms - packet.send_time_ms);
317 }
318 if (!min_rtt_sample_ms)
319 return false;
320 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms);
321 bool min_rtt_expired = min_rtt_filter_->MinRttExpired(now_ms);
322 return min_rtt_expired;
132 } 323 }
133 324
134 void BbrBweSender::EnterStartup() { 325 void BbrBweSender::EnterStartup() {
135 mode_ = STARTUP; 326 mode_ = STARTUP;
136 pacing_gain_ = kHighGain; 327 pacing_gain_ = kHighGain;
137 congestion_window_gain_ = kHighGain; 328 congestion_window_gain_ = kHighGain;
138 } 329 }
139 330
140 void BbrBweSender::TryExitingStartup() { 331 void BbrBweSender::TryExitingStartup() {
141 if (full_bandwidth_reached_) { 332 if (full_bandwidth_reached_) {
(...skipping 25 matching lines...) Expand all
167 358
168 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { 359 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {
169 // Each phase should last rougly min_rtt ms time. 360 // Each phase should last rougly min_rtt ms time.
170 bool advance_cycle_phase = false; 361 bool advance_cycle_phase = false;
171 if (min_rtt_filter_->min_rtt_ms()) 362 if (min_rtt_filter_->min_rtt_ms())
172 advance_cycle_phase = 363 advance_cycle_phase =
173 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); 364 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 365 // 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, 366 // 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. 367 // but condition helps in quicker ramp-up and performs better.
177 if (pacing_gain_ > 1.0 && 368 if (pacing_gain_ > 1.0 && congestion_window_->data_inflight() <
178 prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) 369 TargetCongestionWindow(pacing_gain_))
179 advance_cycle_phase = false; 370 advance_cycle_phase = false;
180 // If BBR has already drained queues there is no point in continuing draining 371 // If BBR has already drained queues there is no point in continuing draining
181 // phase. 372 // phase.
182 if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) 373 if (pacing_gain_ < 1.0 &&
374 congestion_window_->data_inflight() <= TargetCongestionWindow(1))
183 advance_cycle_phase = true; 375 advance_cycle_phase = true;
184 if (advance_cycle_phase) { 376 if (advance_cycle_phase) {
185 cycle_index_++; 377 cycle_index_++;
186 cycle_index_ %= kGainCycleLength; 378 cycle_index_ %= kGainCycleLength;
187 pacing_gain_ = kPacingGain[cycle_index_]; 379 pacing_gain_ = kPacingGain[cycle_index_];
188 cycle_start_time_ms_ = now_ms; 380 cycle_start_time_ms_ = now_ms;
189 } 381 }
190 } 382 }
191 383
192 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { 384 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {
193 if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && 385 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) {
194 mode_ != PROBE_RTT) {
195 mode_ = PROBE_RTT; 386 mode_ = PROBE_RTT;
196 pacing_gain_ = 1; 387 pacing_gain_ = 1;
197 probe_rtt_start_time_ms_ = now_ms; 388 probe_rtt_start_time_ms_ = now_ms;
198 minimum_congestion_window_start_time_ms_.reset(); 389 minimum_congestion_window_start_time_ms_.reset();
199 } 390 }
200 } 391 }
201 392
202 // minimum_congestion_window_start_time_'s value is set to the first moment when 393 // |minimum_congestion_window_start_time_|'s value is set to the first moment
203 // data inflight was less then kMinimumCongestionWindowBytes, we should make 394 // when data inflight was less then
204 // sure that BBR has been in PROBE_RTT mode for at least one round or 200ms. 395 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that
396 // 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) { 397 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) {
206 if (!minimum_congestion_window_start_time_ms_) { 398 if (!minimum_congestion_window_start_time_ms_) {
207 if (congestion_window_->data_inflight() <= 399 if (congestion_window_->data_inflight() <=
208 CongestionWindow::kMinimumCongestionWindowBytes) { 400 CongestionWindow::kMinimumCongestionWindowBytes) {
209 *minimum_congestion_window_start_time_ms_ = now_ms; 401 *minimum_congestion_window_start_time_ms_ = now_ms;
210 minimum_congestion_window_start_round_ = round; 402 minimum_congestion_window_start_round_ = round;
211 } 403 }
212 } else { 404 } else {
213 if (now_ms - *minimum_congestion_window_start_time_ms_ >= 405 if (now_ms - *minimum_congestion_window_start_time_ms_ >=
214 kProbeRttDurationMs && 406 kProbeRttDurationMs &&
215 round - minimum_congestion_window_start_round_ >= 407 round - minimum_congestion_window_start_round_ >=
216 kProbeRttDurationRounds) 408 kProbeRttDurationRounds)
217 EnterProbeBw(now_ms); 409 EnterProbeBw(now_ms);
218 } 410 }
219 } 411 }
220 412
413 void BbrBweSender::TryEnteringRecovery(bool new_round_started) {
414 // If we are already in Recovery don't try to enter.
415 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_)
416 return;
417 uint64_t increased_rtt_round_counter = 0;
418 // If average RTT for past |kPastRttsFilterSize| rounds has been more than
419 // some multiplier of min_rtt_ms enter Recovery.
420 for (BbrBweSender::AverageRtt i : past_rtts_) {
421 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >=
422 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold)
423 increased_rtt_round_counter++;
424 }
425 if (increased_rtt_round_counter < kPastRttsFilterSize)
426 return;
427 mode_ = RECOVERY;
428 pacing_gain_ = kRecoveryPacingGain;
429 congestion_window_gain_ = kRecoveryCongestionWindowGain;
430 }
431
432 void BbrBweSender::TryExitingRecovery(bool new_round_started) {
433 if (mode_ != RECOVERY || !new_round_started || !full_bandwidth_reached_)
434 return;
435 // If average RTT for the past round has decreased sufficiently exit Recovery.
436 if (!past_rtts_.empty()) {
437 BbrBweSender::AverageRtt last_round_sample = past_rtts_.back();
438 if (last_round_sample.sum_of_rtts_ms / last_round_sample.num_samples <=
439 *min_rtt_filter_->min_rtt_ms() * kRttDecreaseThreshold) {
440 EnterProbeBw(clock_->TimeInMilliseconds());
441 }
442 }
443 }
444
221 int64_t BbrBweSender::TimeUntilNextProcess() { 445 int64_t BbrBweSender::TimeUntilNextProcess() {
222 return 100; 446 return 50;
223 } 447 }
224 448
225 void BbrBweSender::OnPacketsSent(const Packets& packets) { 449 void BbrBweSender::OnPacketsSent(const Packets& packets) {
226 last_packet_sent_ = 450 for (Packet* packet : packets) {
227 static_cast<const MediaPacket*>(packets.back())->sequence_number(); 451 if (packet->GetPacketType() == Packet::kMedia) {
452 MediaPacket* media_packet = static_cast<MediaPacket*>(packet);
453 bytes_sent_ += media_packet->payload_size();
454 PacketStats packet_stats = PacketStats(
455 media_packet->sequence_number(), 0,
456 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_,
457 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_);
458 packet_stats_[media_packet->sequence_number()] = packet_stats;
459 last_packet_send_time_ = media_packet->sender_timestamp_ms();
460 last_packet_sent_sequence_number_ = media_packet->sequence_number();
461 // If this is the first packet sent for high gain phase, save data for it.
462 if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) {
463 *first_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
464 data_sent_before_high_gain_started_bytes_ =
465 bytes_sent_ - media_packet->payload_size() / 2;
466 first_packet_seq_num_during_high_gain_ =
467 media_packet->sequence_number();
468 }
469 // This condition ensures that |last_packet_seq_num_during_high_gain_|
470 // will contain a sequence number of the last packet sent during high gain
471 // phase.
472 if (pacing_gain_ > 1) {
473 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
474 data_sent_before_high_gain_ended_bytes_ =
475 bytes_sent_ - media_packet->payload_size() / 2;
476 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number();
477 }
478 congestion_window_->PacketSent(media_packet->payload_size());
479 }
480 }
228 } 481 }
229 482
230 void BbrBweSender::Process() {} 483 void BbrBweSender::Process() {}
231 484
232 BbrBweReceiver::BbrBweReceiver(int flow_id) 485 BbrBweReceiver::BbrBweReceiver(int flow_id)
233 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} 486 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {}
234 487
235 BbrBweReceiver::~BbrBweReceiver() {} 488 BbrBweReceiver::~BbrBweReceiver() {}
236 489
237 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, 490 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms,
238 const MediaPacket& media_packet) {} 491 const MediaPacket& media_packet) {}
239 492
240 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { 493 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) {
241 return nullptr; 494 return nullptr;
242 } 495 }
243 } // namespace bwe 496 } // namespace bwe
244 } // namespace testing 497 } // namespace testing
245 } // namespace webrtc 498 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698