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

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: 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 // Number of rounds for bandwidth estimate to expire.
40 const size_t kBandwidthWindowFilterSize = kGainCycleLength + 2;
41 const int kMinimumCongestionWindow = 4000;
philipel 2017/08/04 12:08:06 kMinimumCongestionWindow should not be defined in
gnish1 2017/08/07 10:34:28 Done.
42 // Least amount number of rounds PROBE_RTT should last.
39 const int kProbeRttDurationRounds = 1; 43 const int kProbeRttDurationRounds = 1;
40 // The least amount of milliseconds PROBE_RTT mode should last. 44 // The least amount of milliseconds PROBE_RTT mode should last.
41 const int kProbeRttDurationMs = 200; 45 const int kProbeRttDurationMs = 200;
42 // Gain value for congestion window for assuming that network has no queues. 46 // Gain value for congestion window for assuming that network has no queues.
43 const float kTargetCongestionWindowGain = 1; 47 const float kTargetCongestionWindowGain = 1;
44 // Gain value for congestion window in PROBE_BW mode. In theory it should be 48 // 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 49 // 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 50 // work, it is nice to have some extra room in congestion window for full link
47 // utilization. Value chosen by observations on different tests. 51 // utilization. Value chosen by observations on different tests.
48 const float kCruisingCongestionWindowGain = 1.5f; 52 const float kCruisingCongestionWindowGain = 1.5f;
49 // Expiration time for min_rtt sample, which is set to 10 seconds according to 53 // Expiration time for min_rtt sample, which is set to 10 seconds according to
50 // BBR design doc. 54 // BBR design doc.
51 const int64_t kMinRttFilterSizeMs = 10000; 55 const int64_t kMinRttFilterSizeMs = 10000;
56 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation
57 // tool.
58 const float kRecoveryPacingGain = 0.5f;
59 // Congestion window gain specific for Recovery mode. Chosen by experiments in
60 // simulation tool.
61 const float kRecoveryCongestionWindowGain = 1.5f;
62 // Number of rounds over which average rtt is stored for Recovery mode.
63 const size_t kPastRttsFilterSize = 1;
64 // Threshold to assume average rtt has increased for a round. Chosen by
65 // experiments in simulation tool.
66 const float kRttIncreaseThreshold = 3;
67 // Threshold to assume average rtt has decreased for a round. Chosen by
68 // experiments in simulation tool.
69 const float kRttDecreaseThreshold = 1.5f;
52 } // namespace 70 } // namespace
53 71
54 BbrBweSender::BbrBweSender(Clock* clock) 72 BbrBweSender::BbrBweSender(Clock* clock)
55 : BweSender(0), 73 : BweSender(0),
56 clock_(clock), 74 clock_(clock),
57 mode_(STARTUP), 75 mode_(STARTUP),
58 max_bandwidth_filter_(new MaxBandwidthFilter()), 76 max_bandwidth_filter_(new MaxBandwidthFilter()),
59 min_rtt_filter_(new MinRttFilter()), 77 min_rtt_filter_(new MinRttFilter()),
60 congestion_window_(new CongestionWindow()), 78 congestion_window_(new CongestionWindow()),
61 rand_(new Random(time(NULL))), 79 rand_(new Random(time(NULL))),
62 round_count_(0), 80 round_count_(0),
63 last_packet_sent_(0),
64 round_trip_end_(0), 81 round_trip_end_(0),
65 full_bandwidth_reached_(false), 82 full_bandwidth_reached_(false),
66 cycle_start_time_ms_(0), 83 cycle_start_time_ms_(0),
67 cycle_index_(0), 84 cycle_index_(0),
85 bytes_acked_(0),
68 prior_in_flight_(0), 86 prior_in_flight_(0),
69 probe_rtt_start_time_ms_(0), 87 probe_rtt_start_time_ms_(0),
70 minimum_congestion_window_start_time_ms_(), 88 minimum_congestion_window_start_time_ms_(0),
71 minimum_congestion_window_start_round_(0) { 89 minimum_congestion_window_start_round_(0),
90 bytes_sent_(0),
91 last_packet_sent_sequence_number_(0),
92 last_packet_acked_sequence_number_(0),
93 last_packet_ack_time_(0),
94 last_packet_send_time_(0),
95 pacing_rate_(0),
96 last_high_gain_send_time_(-1),
97 first_high_gain_sent_before_(-1),
98 last_high_gain_sent_before_(-1),
99 first_high_gain_ack_time_(-1),
100 last_high_gain_ack_time_(-1),
101 first_high_gain_acked_before_(-1),
102 last_high_gain_acked_before_(-1),
103 first_high_gain_seq_num_(-1),
104 last_high_gain_seq_num_(-1),
105 high_gain_over_(false),
106 packet_stats_(),
107 past_rtts_() {
72 // Initially enter Startup mode. 108 // Initially enter Startup mode.
73 EnterStartup(); 109 EnterStartup();
74 } 110 }
75 111
76 BbrBweSender::~BbrBweSender() {} 112 BbrBweSender::~BbrBweSender() {}
77 113
78 int BbrBweSender::GetFeedbackIntervalMs() const { 114 int BbrBweSender::GetFeedbackIntervalMs() const {
79 return kFeedbackIntervalsMs; 115 return kFeedbackIntervalsMs;
80 } 116 }
81 117
118 void BbrBweSender::CalculatePacingRate() {
119 pacing_rate_ =
120 max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_;
121 }
122
123 void BbrBweSender::HandleLoss(uint64_t last_acked_packet,
philipel 2017/08/04 12:08:07 So, in the case of loss we immediately mark the lo
gnish1 2017/08/07 10:34:28 Done.
124 uint64_t recently_acked_packet) {
125 // Logic specific to wrapping sequence numbers.
126 if (!last_acked_packet)
127 return;
128 for (uint64_t i = last_acked_packet + 1; i < recently_acked_packet; i++)
philipel 2017/08/04 12:08:06 Are |last_acked_packet| and |recently_acked_packet
gnish1 2017/08/07 10:34:28 Done.
129 congestion_window_->AckReceived(packet_stats_[i].payload_size);
130 }
131
132 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) {
133 uint64_t last_round = 0;
134 if (!past_rtts_.empty())
135 last_round = past_rtts_.rbegin()->round;
philipel 2017/08/04 12:08:06 ... = past_rtts_.back().round;
gnish1 2017/08/07 10:34:27 Done.
136
137 // Try to add the sample to the last round.
138 if (last_round == round_count_ && !past_rtts_.empty()) {
139 BbrBweSender::AverageRtt& last_round_sample = *(past_rtts_.rbegin());
philipel 2017/08/04 12:08:06 BbrBweSender::AverageRtt* = &past_rtts_.back(); W
gnish1 2017/08/07 10:34:28 Done.
140 last_round_sample.sum_of_rtts += rtt_sample_ms;
141 last_round_sample.quantity++;
142 } else {
143 // If the sample belongs to a new round, keep number of rounds in the window
144 // equal to |kPastRttsFilterSize|.
145 if (past_rtts_.size() == kPastRttsFilterSize)
146 past_rtts_.pop_front();
147 past_rtts_.push_back(
148 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_));
149 }
150 }
151
82 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { 152 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {
153 int64_t now = clock_->TimeInMilliseconds();
154 last_packet_ack_time_ = now;
155 prior_in_flight_ = bytes_acked_;
83 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); 156 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback);
84 // feedback_vector holds values of acknowledged packets' sequence numbers. 157 // feedback_vector holds values of acknowledged packets' sequence numbers.
85 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); 158 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 159 // Go through all the packets acked, update variables/containers accordingly.
87 // from sending packet to its acknowledgement. 160 for (const auto& f : feedback_vector) {
philipel 2017/08/04 12:08:06 We use auto for situations where it is both obviou
gnish1 2017/08/07 10:34:28 Done.
161 // Completing packet information with a recently received ack.
162 PacketStats& packet = packet_stats_[f];
philipel 2017/08/04 12:08:06 PacketStats*
gnish1 2017/08/07 10:34:28 Done.
163 bytes_acked_ += packet.payload_size;
164 packet.data_sent = bytes_sent_;
165 packet.send_time = last_packet_send_time_;
166 packet.data_acked = bytes_acked_;
167 packet.ack_time = now;
168 // Logic specific to applying "bucket" to high gain, in order to have
169 // quicker ramp-up. We check if we started receiving acks for the packets
170 // sent during high gain phase.
171 if (packet.sequence_number == first_high_gain_seq_num_) {
172 first_high_gain_ack_time_ = now;
173 first_high_gain_acked_before_ = bytes_acked_;
174 }
175 // If the last packet of high gain phase has been acked, high gain phase is
176 // over.
177 if (packet.sequence_number == last_high_gain_seq_num_) {
178 last_high_gain_ack_time_ = now;
179 last_high_gain_acked_before_ = bytes_acked_;
180 high_gain_over_ = true;
181 }
182 // Notify pacer that an ack was received, to adjust data inflight.
183 // TODO(gnish): Add implementation for BitrateObserver class, to notify
184 // pacer about incoming acks.
185 congestion_window_->AckReceived(packet.payload_size);
186 HandleLoss(last_packet_acked_sequence_number_, packet.sequence_number);
187 last_packet_acked_sequence_number_ = packet.sequence_number;
188 // Logic for wrapping sequence numbers. If round started with packet number
189 // x, it can never end on y, if x > y. That could happen when sequence
190 // numbers are wrapped after some point.
191 if (packet.sequence_number == 0)
192 round_trip_end_ = 0;
193 }
194 // Check if new round started for the connection.
88 bool new_round_started = false; 195 bool new_round_started = false;
89 if (!feedback_vector.empty()) { 196 if (!feedback_vector.empty()) {
90 uint64_t last_acked_packet = *feedback_vector.rbegin(); 197 if (last_packet_acked_sequence_number_ > round_trip_end_) {
91 if (last_acked_packet > round_trip_end_) {
92 new_round_started = true; 198 new_round_started = true;
93 round_count_++; 199 round_count_++;
94 round_trip_end_ = last_packet_sent_; 200 round_trip_end_ = last_packet_sent_sequence_number_;
95 } 201 }
96 } 202 }
203 // Try to enter and exit recovery only after a round has ended.
204 if (new_round_started && full_bandwidth_reached_) {
205 TryEnteringRecovery(); // Comment this line to disable entering Recovery
206 // mode.
207 TryExitingRecovery();
philipel 2017/08/04 12:08:06 I think having |new_round_started| and |full_bandw
gnish1 2017/08/07 10:34:28 Done.
208 }
209 bool min_rtt_expired = false;
210 min_rtt_expired =
211 UpdateBandwidthAndMinRtt(now, feedback_vector, bytes_acked_);
97 if (new_round_started && !full_bandwidth_reached_) { 212 if (new_round_started && !full_bandwidth_reached_) {
98 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( 213 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached(
99 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); 214 kStartupGrowthTarget, kMaxRoundsWithoutGrowth);
100 } 215 }
101 int now_ms = clock_->TimeInMilliseconds();
102 switch (mode_) { 216 switch (mode_) {
103 break; 217 break;
104 case STARTUP: 218 case STARTUP:
105 TryExitingStartup(); 219 TryExitingStartup();
106 break; 220 break;
107 case DRAIN: 221 case DRAIN:
108 TryExitingDrain(now_ms); 222 TryExitingDrain(now);
109 break; 223 break;
110 case PROBE_BW: 224 case PROBE_BW:
111 TryUpdatingCyclePhase(now_ms); 225 TryUpdatingCyclePhase(now);
112 break; 226 break;
113 case PROBE_RTT: 227 case PROBE_RTT:
114 TryExitingProbeRtt(now_ms, 0); 228 TryExitingProbeRtt(now, round_count_, min_rtt_expired);
229 break;
230 case RECOVERY:
115 break; 231 break;
116 } 232 }
117 TryEnteringProbeRtt(now_ms); 233 TryEnteringProbeRtt(now, min_rtt_expired);
118 // TODO(gnish): implement functions updating congestion window and pacing rate 234 CalculatePacingRate();
119 // controllers. 235 // Make sure we don't get stuck when pacing_rate is 0, because of simulation
236 // tool specifics.
237 if (!pacing_rate_)
238 pacing_rate_ = 100;
239 BWE_TEST_LOGGING_PLOT(1, "SendRate", now, pacing_rate_ / 1000);
240 // TODO(gnish): Add implementation for BitrateObserver class to update pacing
241 // rate for the pacer and the encoder.
120 } 242 }
121 243
122 size_t BbrBweSender::TargetCongestionWindow(float gain) { 244 size_t BbrBweSender::TargetCongestionWindow(float gain) {
123 size_t target_congestion_window = 245 size_t target_congestion_window =
124 congestion_window_->GetTargetCongestionWindow( 246 congestion_window_->GetTargetCongestionWindow(
125 max_bandwidth_filter_->max_bandwidth_estimate_bps(), 247 max_bandwidth_filter_->max_bandwidth_estimate_bps(),
126 min_rtt_filter_->min_rtt_ms(), gain); 248 min_rtt_filter_->min_rtt_ms(), gain);
127 return target_congestion_window; 249 return target_congestion_window;
128 } 250 }
129 251
130 bool BbrBweSender::UpdateBandwidthAndMinRtt() { 252 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample(
131 return false; 253 size_t data_sent,
254 int64_t time_elapsed_1,
255 size_t data_acked,
256 int64_t time_elapsed_2) {
257 rtc::Optional<int64_t> bandwidth_sample;
258 if (time_elapsed_1 > 0)
259 *bandwidth_sample = data_sent * 8000 / time_elapsed_1;
260 rtc::Optional<int64_t> ack_rate;
261 if (time_elapsed_2 > 0)
262 *ack_rate = data_acked * 8000 / time_elapsed_2;
263 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to
264 // ack_rate.
265 if (!bandwidth_sample)
266 bandwidth_sample = ack_rate;
267 if (bandwidth_sample && ack_rate)
268 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate);
269 return bandwidth_sample;
270 }
271
272 void BbrBweSender::AddSampleForHighGain() {
273 if (!high_gain_over_)
274 return;
275 high_gain_over_ = false;
276 // Calculate data sent/acked and time elapsed only for packets sent during
277 // high gain phase.
278 size_t data_sent = last_high_gain_sent_before_ - first_high_gain_sent_before_;
279 int64_t time_elapsed_1 =
280 last_high_gain_send_time_ - *first_high_gain_send_time_;
281 size_t data_acked =
282 last_high_gain_acked_before_ - first_high_gain_acked_before_;
283 int64_t time_elapsed_2 = last_high_gain_ack_time_ - first_high_gain_ack_time_;
284 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
285 data_sent, time_elapsed_1, data_acked, time_elapsed_2);
286 if (bandwidth_sample)
287 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_,
288 kBandwidthWindowFilterSize);
289 first_high_gain_send_time_.reset();
290 }
291
292 bool BbrBweSender::UpdateBandwidthAndMinRtt(
293 int64_t now,
philipel 2017/08/04 12:08:06 now_ms
gnish1 2017/08/07 10:34:28 Done.
294 const std::vector<uint64_t>& feedback_vector,
295 int64_t bytes_acked) {
296 rtc::Optional<int64_t> min_rtt_sample_ms;
297 for (const auto& f : feedback_vector) {
philipel 2017/08/04 12:08:06 for (uint64_t f: feedback_vector)
gnish1 2017/08/07 10:34:28 Done.
298 PacketStats packet = packet_stats_[f];
299 size_t data_sent = packet.data_sent - packet.data_sent_before;
300 int64_t time_elapsed_1 = packet.send_time - packet.send_time_before;
301 size_t data_acked = packet.data_acked - packet.data_acked_before;
302 int64_t time_elapsed_2 = packet.ack_time - packet.ack_time_before;
303 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
304 data_sent, time_elapsed_1, data_acked, time_elapsed_2);
305 if (bandwidth_sample)
306 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_,
307 kBandwidthWindowFilterSize);
308 AddSampleForHighGain(); // Comment to disable bucket for high gain.
309 if (!min_rtt_sample_ms)
310 *min_rtt_sample_ms = packet.ack_time - packet.send_time_before;
311 else
312 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms,
313 packet.ack_time - packet.send_time_before);
314 AddToPastRtts(packet.ack_time - packet.send_time_before);
315 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now,
316 packet.ack_time - packet.send_time_before);
317 }
318 if (!min_rtt_sample_ms)
319 return false;
320 bool min_rtt_expired =
321 min_rtt_filter_->min_rtt_expired(now, kMinRttFilterSizeMs);
322 min_rtt_filter_->add_rtt_sample(*min_rtt_sample_ms, now, min_rtt_expired);
323 return min_rtt_expired;
132 } 324 }
133 325
134 void BbrBweSender::EnterStartup() { 326 void BbrBweSender::EnterStartup() {
135 mode_ = STARTUP; 327 mode_ = STARTUP;
136 pacing_gain_ = kHighGain; 328 pacing_gain_ = kHighGain;
137 congestion_window_gain_ = kHighGain; 329 congestion_window_gain_ = kHighGain;
138 } 330 }
139 331
140 void BbrBweSender::TryExitingStartup() { 332 void BbrBweSender::TryExitingStartup() {
141 if (full_bandwidth_reached_) { 333 if (full_bandwidth_reached_) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) 374 if (pacing_gain_ < 1.0 && prior_in_flight_ <= 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, bool min_rtt_expired) {
philipel 2017/08/04 12:08:06 This looks like a revert of the changes you made i
gnish1 2017/08/07 10:34:28 Done.
193 if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && 385 if (min_rtt_expired && 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 |kMinimumCongestionWindow|, we should make
204 // sure that BBR has been in PROBE_RTT mode for at least one round or 200ms. 395 // sure that 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) { 396 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms,
397 int64_t round,
398 bool min_rtt_expired) {
philipel 2017/08/04 12:08:06 Undo this change.
gnish1 2017/08/07 10:34:28 Done.
206 if (!minimum_congestion_window_start_time_ms_) { 399 if (!minimum_congestion_window_start_time_ms_) {
207 if (congestion_window_->data_inflight() <= 400 if (congestion_window_->data_inflight() <= kMinimumCongestionWindow) {
philipel 2017/08/04 12:08:06 Undo.
gnish1 2017/08/07 10:34:28 Done.
208 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() {
414 // If we are already in Recovery don't try to enter.
415 if (mode_ == RECOVERY)
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 (const auto i : past_rtts_) {
philipel 2017/08/04 12:08:06 Don't use auto.
gnish1 2017/08/07 10:34:28 Done.
421 if (i.sum_of_rtts / (int64_t)i.quantity >=
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() {
433 if (mode_ != RECOVERY)
434 return;
435 // If average rtt for the past round has decreased sufficiently exit Recovery.
436 if (!past_rtts_.empty()) {
437 auto last_round_sample = past_rtts_.rbegin();
438 if (last_round_sample->sum_of_rtts / last_round_sample->quantity <=
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_high_gain_send_time_ && pacing_gain_ > 1) {
463 *first_high_gain_send_time_ = last_packet_send_time_;
464 first_high_gain_sent_before_ = bytes_sent_;
465 first_high_gain_seq_num_ = media_packet->sequence_number();
466 }
467 // This condition ensures that |last_high_gain_seq_num_| will contain a
468 // sequence number of the last packet sent during high gain phase.
469 if (pacing_gain_ > 1) {
470 last_high_gain_send_time_ = last_packet_send_time_;
471 last_high_gain_sent_before_ = bytes_sent_;
472 last_high_gain_seq_num_ = media_packet->sequence_number();
473 }
474 congestion_window_->PacketSent(media_packet->payload_size());
475 }
476 }
228 } 477 }
229 478
230 void BbrBweSender::Process() {} 479 void BbrBweSender::Process() {}
231 480
232 BbrBweReceiver::BbrBweReceiver(int flow_id) 481 BbrBweReceiver::BbrBweReceiver(int flow_id)
233 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} 482 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {}
234 483
235 BbrBweReceiver::~BbrBweReceiver() {} 484 BbrBweReceiver::~BbrBweReceiver() {}
236 485
237 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, 486 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms,
238 const MediaPacket& media_packet) {} 487 const MediaPacket& media_packet) {}
239 488
240 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { 489 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) {
241 return nullptr; 490 return nullptr;
242 } 491 }
243 } // namespace bwe 492 } // namespace bwe
244 } // namespace testing 493 } // namespace testing
245 } // namespace webrtc 494 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698