OLD | NEW |
---|---|
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 */ |
(...skipping 16 matching lines...) Expand all Loading... | |
27 // suggests using this value. | 27 // suggests using this value. |
28 const float kHighGain = 2.885f; | 28 const float kHighGain = 2.885f; |
29 // 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 |
30 // time. | 30 // time. |
31 const float kDrainGain = 1 / kHighGain; | 31 const float kDrainGain = 1 / kHighGain; |
32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from | 32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from |
33 // experiments, according to the design document. | 33 // experiments, according to the design document. |
34 const float kStartupGrowthTarget = 1.25f; | 34 const float kStartupGrowthTarget = 1.25f; |
35 const int kMaxRoundsWithoutGrowth = 3; | 35 const int kMaxRoundsWithoutGrowth = 3; |
36 // Pacing gain values for Probe Bandwidth mode. | 36 // Pacing gain values for Probe Bandwidth mode. |
37 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; | 37 const float kPacingGain[] = {1.1, 0.9, 1, 1, 1, 1, 1, 1}; |
38 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); | 38 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); |
39 // Least number of rounds PROBE_RTT should last. | 39 // Least number of rounds PROBE_RTT should last. |
40 const int kProbeRttDurationRounds = 1; | 40 const int kProbeRttDurationRounds = 1; |
41 // The least amount of milliseconds PROBE_RTT mode should last. | 41 // The least amount of milliseconds PROBE_RTT mode should last. |
42 const int kProbeRttDurationMs = 200; | 42 const int kProbeRttDurationMs = 200; |
43 // 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. |
44 const float kTargetCongestionWindowGain = 1; | 44 const float kTargetCongestionWindowGain = 1; |
45 // 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 |
46 // 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 |
47 // 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 |
48 // utilization. Value chosen by observations on different tests. | 48 // utilization. Value chosen by observations on different tests. |
49 const float kCruisingCongestionWindowGain = 1.5f; | 49 const float kCruisingCongestionWindowGain = 2; |
50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation | 50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation |
51 // tool. | 51 // tool. |
52 const float kRecoveryPacingGain = 0.5f; | 52 const float kRecoveryPacingGain = 0.5f; |
53 // Congestion window gain specific for Recovery mode. Chosen by experiments in | 53 // Congestion window gain specific for Recovery mode. Chosen by experiments in |
54 // simulation tool. | 54 // simulation tool. |
55 const float kRecoveryCongestionWindowGain = 1.5f; | 55 const float kRecoveryCongestionWindowGain = 1.5f; |
56 // Number of rounds over which average RTT is stored for Recovery mode. | 56 // Number of rounds over which average RTT is stored for Recovery mode. |
57 const size_t kPastRttsFilterSize = 1; | 57 const size_t kPastRttsFilterSize = 1; |
58 // Threshold to assume average RTT has increased for a round. Chosen by | 58 // Threshold to assume average RTT has increased for a round. Chosen by |
59 // experiments in simulation tool. | 59 // experiments in simulation tool. |
60 const float kRttIncreaseThreshold = 3; | 60 const float kRttIncreaseThreshold = 3; |
61 // Threshold to assume average RTT has decreased for a round. Chosen by | 61 // Threshold to assume average RTT has decreased for a round. Chosen by |
62 // experiments in simulation tool. | 62 // experiments in simulation tool. |
63 const float kRttDecreaseThreshold = 1.5f; | 63 const float kRttDecreaseThreshold = 1.5f; |
64 // If |kCongestionWindowThreshold| of the congestion window is filled up, tell | |
65 // encoder to stop, to avoid building sender side queues. | |
66 const float kCongestionWindowThreshold = 0.69f; | |
67 // Duration we send at |kDefaultRatebps| in order to ensure BBR has data to work | |
68 // with. | |
69 const int64_t kTimeForDefaultSendMs = 200; | |
philipel
2017/08/18 11:22:15
kDuration...
gnish1
2017/08/18 11:48:42
Done.
| |
70 const int64_t kDefaultRatebps = 300000; | |
71 // Congestion window gain for PROBE_RTT mode. | |
72 const float kProbeRttCongestionWindowGain = 0.65f; | |
73 // We need to be sure that data inflight has increased by at least | |
74 // |kTargetCongestionWindowGainForHighGain| compared to the congestion window in | |
75 // PROBE_BW's high gain phase, to make ramp-up quicker. As high gain value has | |
76 // been decreased from 1.25 to 1.1 we need to make | |
77 // |kTargetCongestionWindowGainForHighGain| slightly higher than the actual high | |
78 // gain value. | |
79 const float kTargetCongestionWindowGainForHighGain = 1.15f; | |
80 // Encoder rate gain value for PROBE_RTT mode. | |
81 const float kEncoderRateGainForProbeRtt = 0.1f; | |
64 } // namespace | 82 } // namespace |
65 | 83 |
66 BbrBweSender::BbrBweSender(Clock* clock) | 84 BbrBweSender::BbrBweSender(BitrateObserver* observer, Clock* clock) |
67 : BweSender(0), | 85 : BweSender(0), |
86 observer_(observer), | |
68 clock_(clock), | 87 clock_(clock), |
69 mode_(STARTUP), | 88 mode_(STARTUP), |
70 max_bandwidth_filter_(new MaxBandwidthFilter()), | 89 max_bandwidth_filter_(new MaxBandwidthFilter()), |
71 min_rtt_filter_(new MinRttFilter()), | 90 min_rtt_filter_(new MinRttFilter()), |
72 congestion_window_(new CongestionWindow()), | 91 congestion_window_(new CongestionWindow()), |
73 rand_(new Random(time(NULL))), | 92 rand_(new Random(time(NULL))), |
74 round_count_(0), | 93 round_count_(0), |
75 round_trip_end_(0), | 94 round_trip_end_(0), |
76 full_bandwidth_reached_(false), | 95 full_bandwidth_reached_(false), |
77 cycle_start_time_ms_(0), | 96 cycle_start_time_ms_(0), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 } | 133 } |
115 | 134 |
116 void BbrBweSender::HandleLoss(uint64_t last_acked_packet, | 135 void BbrBweSender::HandleLoss(uint64_t last_acked_packet, |
117 uint64_t recently_acked_packet) { | 136 uint64_t recently_acked_packet) { |
118 // Logic specific to wrapping sequence numbers. | 137 // Logic specific to wrapping sequence numbers. |
119 if (!last_acked_packet) | 138 if (!last_acked_packet) |
120 return; | 139 return; |
121 for (uint16_t i = last_acked_packet + 1; | 140 for (uint16_t i = last_acked_packet + 1; |
122 AheadOrAt<uint16_t>(recently_acked_packet - 1, i); i++) { | 141 AheadOrAt<uint16_t>(recently_acked_packet - 1, i); i++) { |
123 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes); | 142 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes); |
143 observer_->OnBytesAcked(packet_stats_[i].payload_size_bytes); | |
124 } | 144 } |
125 } | 145 } |
126 | 146 |
127 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) { | 147 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) { |
128 uint64_t last_round = 0; | 148 uint64_t last_round = 0; |
129 if (!past_rtts_.empty()) | 149 if (!past_rtts_.empty()) |
130 last_round = past_rtts_.back().round; | 150 last_round = past_rtts_.back().round; |
131 | 151 |
132 // Try to add the sample to the last round. | 152 // Try to add the sample to the last round. |
133 if (last_round == round_count_ && !past_rtts_.empty()) { | 153 if (last_round == round_count_ && !past_rtts_.empty()) { |
134 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms; | 154 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms; |
135 past_rtts_.back().num_samples++; | 155 past_rtts_.back().num_samples++; |
136 } else { | 156 } else { |
137 // If the sample belongs to a new round, keep number of rounds in the window | 157 // If the sample belongs to a new round, keep number of rounds in the window |
138 // equal to |kPastRttsFilterSize|. | 158 // equal to |kPastRttsFilterSize|. |
139 if (past_rtts_.size() == kPastRttsFilterSize) | 159 if (past_rtts_.size() == kPastRttsFilterSize) |
140 past_rtts_.pop_front(); | 160 past_rtts_.pop_front(); |
141 past_rtts_.push_back( | 161 past_rtts_.push_back( |
142 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_)); | 162 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_)); |
143 } | 163 } |
144 } | 164 } |
145 | 165 |
146 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { | 166 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { |
147 int64_t now_ms = clock_->TimeInMilliseconds(); | 167 int64_t now_ms = clock_->TimeInMilliseconds(); |
148 last_packet_ack_time_ = now_ms; | 168 last_packet_ack_time_ = now_ms; |
149 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); | 169 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); |
150 // feedback_vector holds values of acknowledged packets' sequence numbers. | 170 // feedback_vector holds values of acknowledged packets' sequence numbers. |
151 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); | 171 const std::vector<uint16_t>& feedback_vector = fb.packet_feedback_vector(); |
152 // Go through all the packets acked, update variables/containers accordingly. | 172 // Go through all the packets acked, update variables/containers accordingly. |
153 for (uint16_t sequence_number : feedback_vector) { | 173 for (uint16_t sequence_number : feedback_vector) { |
154 // Completing packet information with a recently received ack. | 174 // Completing packet information with a recently received ack. |
155 PacketStats* packet = &packet_stats_[sequence_number]; | 175 PacketStats* packet = &packet_stats_[sequence_number]; |
156 bytes_acked_ += packet->payload_size_bytes; | 176 bytes_acked_ += packet->payload_size_bytes; |
157 packet->data_sent_bytes = bytes_sent_; | 177 packet->data_sent_bytes = bytes_sent_; |
158 packet->last_sent_packet_send_time_ms = last_packet_send_time_; | 178 packet->last_sent_packet_send_time_ms = last_packet_send_time_; |
159 packet->data_acked_bytes = bytes_acked_; | 179 packet->data_acked_bytes = bytes_acked_; |
160 packet->ack_time_ms = now_ms; | 180 packet->ack_time_ms = now_ms; |
161 // Logic specific to applying "bucket" to high gain, in order to have | 181 // 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 | 182 // quicker ramp-up. We check if we started receiving acks for the packets |
163 // sent during high gain phase. | 183 // sent during high gain phase. |
164 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) { | 184 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) { |
165 first_packet_ack_time_during_high_gain_ms_ = now_ms; | 185 first_packet_ack_time_during_high_gain_ms_ = now_ms; |
166 // Substracting half of the packet's size to avoid overestimation. | 186 // Substracting half of the packet's size to avoid overestimation. |
167 data_acked_before_high_gain_started_bytes_ = | 187 data_acked_before_high_gain_started_bytes_ = |
168 bytes_acked_ - packet->payload_size_bytes / 2; | 188 bytes_acked_ - packet->payload_size_bytes / 2; |
169 } | 189 } |
170 // If the last packet of high gain phase has been acked, high gain phase is | 190 // If the last packet of high gain phase has been acked, high gain phase is |
171 // over. | 191 // over. |
172 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) { | 192 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) { |
173 last_packet_ack_time_during_high_gain_ms_ = now_ms; | 193 last_packet_ack_time_during_high_gain_ms_ = now_ms; |
174 data_acked_before_high_gain_ended_bytes_ = | 194 data_acked_before_high_gain_ended_bytes_ = |
175 bytes_acked_ - packet->payload_size_bytes / 2; | 195 bytes_acked_ - packet->payload_size_bytes / 2; |
176 high_gain_over_ = true; | 196 high_gain_over_ = true; |
177 } | 197 } |
178 // Notify pacer that an ack was received, to adjust data inflight. | 198 observer_->OnBytesAcked(packet->payload_size_bytes); |
179 // TODO(gnish): Add implementation for BitrateObserver class, to notify | |
180 // pacer about incoming acks. | |
181 congestion_window_->AckReceived(packet->payload_size_bytes); | 199 congestion_window_->AckReceived(packet->payload_size_bytes); |
182 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number); | 200 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number); |
183 last_packet_acked_sequence_number_ = packet->sequence_number; | 201 last_packet_acked_sequence_number_ = packet->sequence_number; |
184 // Logic for wrapping sequence numbers. If round started with packet number | 202 // 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 | 203 // x, it can never end on y, if x > y. That could happen when sequence |
186 // numbers are wrapped after some point. | 204 // numbers are wrapped after some point. |
187 if (packet->sequence_number == 0) | 205 if (packet->sequence_number == 0) |
188 round_trip_end_ = 0; | 206 round_trip_end_ = 0; |
189 } | 207 } |
190 // Check if new round started for the connection. | 208 // Check if new round started for the connection. |
191 bool new_round_started = false; | 209 bool new_round_started = false; |
192 if (!feedback_vector.empty()) { | 210 if (!feedback_vector.empty()) { |
193 if (last_packet_acked_sequence_number_ > round_trip_end_) { | 211 if (last_packet_acked_sequence_number_ > round_trip_end_) { |
194 new_round_started = true; | 212 new_round_started = true; |
195 round_count_++; | 213 round_count_++; |
196 round_trip_end_ = last_packet_sent_sequence_number_; | 214 round_trip_end_ = last_packet_sent_sequence_number_; |
197 } | 215 } |
198 } | 216 } |
199 bool min_rtt_expired = false; | 217 TryEnteringProbeRtt(now_ms); |
200 min_rtt_expired = | 218 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_); |
201 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_); | |
202 if (new_round_started && !full_bandwidth_reached_) { | 219 if (new_round_started && !full_bandwidth_reached_) { |
203 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( | 220 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( |
204 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); | 221 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); |
205 } | 222 } |
206 switch (mode_) { | 223 switch (mode_) { |
207 break; | 224 break; |
208 case STARTUP: | 225 case STARTUP: |
209 TryExitingStartup(); | 226 TryExitingStartup(); |
210 break; | 227 break; |
211 case DRAIN: | 228 case DRAIN: |
212 TryExitingDrain(now_ms); | 229 TryExitingDrain(now_ms); |
213 break; | 230 break; |
214 case PROBE_BW: | 231 case PROBE_BW: |
215 TryUpdatingCyclePhase(now_ms); | 232 TryUpdatingCyclePhase(now_ms); |
216 break; | 233 break; |
217 case PROBE_RTT: | 234 case PROBE_RTT: |
218 TryExitingProbeRtt(now_ms, round_count_); | 235 TryExitingProbeRtt(now_ms, round_count_); |
219 break; | 236 break; |
220 case RECOVERY: | 237 case RECOVERY: |
221 TryExitingRecovery(new_round_started); | 238 TryExitingRecovery(new_round_started); |
222 break; | 239 break; |
223 } | 240 } |
224 TryEnteringProbeRtt(now_ms); | |
225 TryEnteringRecovery(new_round_started); // Comment this line to disable | 241 TryEnteringRecovery(new_round_started); // Comment this line to disable |
226 // entering Recovery mode. | 242 // entering Recovery mode. |
227 for (uint64_t f : feedback_vector) | 243 for (uint16_t f : feedback_vector) |
228 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms); | 244 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms); |
229 CalculatePacingRate(); | 245 CalculatePacingRate(); |
246 size_t cwnd = congestion_window_->GetCongestionWindow( | |
247 mode_, max_bandwidth_filter_->max_bandwidth_estimate_bps(), | |
248 min_rtt_filter_->min_rtt_ms(), congestion_window_gain_); | |
230 // Make sure we don't get stuck when pacing_rate is 0, because of simulation | 249 // Make sure we don't get stuck when pacing_rate is 0, because of simulation |
231 // tool specifics. | 250 // tool specifics. |
232 if (!pacing_rate_bps_) | 251 if (!pacing_rate_bps_) |
233 pacing_rate_bps_ = 100; | 252 pacing_rate_bps_ = 100; |
234 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000); | 253 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000); |
235 // TODO(gnish): Add implementation for BitrateObserver class to update pacing | 254 int64_t rate_for_pacer_bps = pacing_rate_bps_; |
236 // rate for the pacer and the encoder. | 255 // Encoder producing slightly more due to rounding errors, so we ask for 2% |
256 // less. | |
257 int64_t rate_for_encoder_bps = pacing_rate_bps_; | |
258 if (congestion_window_->data_inflight() >= cwnd * kCongestionWindowThreshold) | |
259 rate_for_encoder_bps = 0; | |
260 // We dont completely stop sending during PROBE_RTT, so we need encoder to | |
261 // produce something, another way of doing this would be telling encoder to | |
262 // stop and send padding instead of actual data. | |
263 if (mode_ == PROBE_RTT) | |
264 rate_for_encoder_bps = rate_for_pacer_bps * kEncoderRateGainForProbeRtt; | |
265 // Send for 300 kbps for first 200 ms, so that BBR has data to work with. | |
266 if (now_ms <= kTimeForDefaultSendMs) | |
267 observer_->OnNetworkChanged( | |
268 kDefaultRatebps, kDefaultRatebps, false, | |
269 clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd); | |
270 else | |
271 observer_->OnNetworkChanged( | |
272 rate_for_encoder_bps, rate_for_pacer_bps, mode_ == PROBE_RTT, | |
273 clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd); | |
237 } | 274 } |
238 | 275 |
239 size_t BbrBweSender::TargetCongestionWindow(float gain) { | 276 size_t BbrBweSender::TargetCongestionWindow(float gain) { |
240 size_t target_congestion_window = | 277 size_t target_congestion_window = |
241 congestion_window_->GetTargetCongestionWindow( | 278 congestion_window_->GetTargetCongestionWindow( |
242 max_bandwidth_filter_->max_bandwidth_estimate_bps(), | 279 max_bandwidth_filter_->max_bandwidth_estimate_bps(), |
243 min_rtt_filter_->min_rtt_ms(), gain); | 280 min_rtt_filter_->min_rtt_ms(), gain); |
244 return target_congestion_window; | 281 return target_congestion_window; |
245 } | 282 } |
246 | 283 |
247 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample( | 284 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample( |
248 size_t data_sent_bytes, | 285 size_t data_sent_bytes, |
249 int64_t send_time_delta_ms, | 286 int64_t send_time_delta_ms, |
250 size_t data_acked_bytes, | 287 size_t data_acked_bytes, |
251 int64_t ack_time_delta_ms) { | 288 int64_t ack_time_delta_ms) { |
252 rtc::Optional<int64_t> bandwidth_sample; | 289 rtc::Optional<int64_t> bandwidth_sample; |
253 if (send_time_delta_ms > 0) | 290 if (send_time_delta_ms > 0) |
254 *bandwidth_sample = data_sent_bytes * 8000 / send_time_delta_ms; | 291 bandwidth_sample.emplace(data_sent_bytes * 8000 / send_time_delta_ms); |
255 rtc::Optional<int64_t> ack_rate; | 292 rtc::Optional<int64_t> ack_rate; |
256 if (ack_time_delta_ms > 0) | 293 if (ack_time_delta_ms > 0) |
257 *ack_rate = data_acked_bytes * 8000 / ack_time_delta_ms; | 294 ack_rate.emplace(data_acked_bytes * 8000 / ack_time_delta_ms); |
258 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to | 295 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to |
259 // ack_rate. | 296 // ack_rate. |
260 if (!bandwidth_sample) | 297 if (!bandwidth_sample) |
261 bandwidth_sample = ack_rate; | 298 bandwidth_sample = ack_rate; |
262 if (bandwidth_sample && ack_rate) | 299 if (bandwidth_sample && ack_rate) |
263 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate); | 300 bandwidth_sample.emplace(std::min(*bandwidth_sample, *ack_rate)); |
264 return bandwidth_sample; | 301 return bandwidth_sample; |
265 } | 302 } |
266 | 303 |
267 void BbrBweSender::AddSampleForHighGain() { | 304 void BbrBweSender::AddSampleForHighGain() { |
268 if (!high_gain_over_) | 305 if (!high_gain_over_) |
269 return; | 306 return; |
270 high_gain_over_ = false; | 307 high_gain_over_ = false; |
271 // Calculate data sent/acked and time elapsed only for packets sent during | 308 // Calculate data sent/acked and time elapsed only for packets sent during |
272 // high gain phase. | 309 // high gain phase. |
273 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ - | 310 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ - |
274 data_sent_before_high_gain_started_bytes_; | 311 data_sent_before_high_gain_started_bytes_; |
275 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ - | 312 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ - |
276 *first_packet_send_time_during_high_gain_ms_; | 313 *first_packet_send_time_during_high_gain_ms_; |
277 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ - | 314 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ - |
278 data_acked_before_high_gain_started_bytes_; | 315 data_acked_before_high_gain_started_bytes_; |
279 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ - | 316 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ - |
280 first_packet_ack_time_during_high_gain_ms_; | 317 first_packet_ack_time_during_high_gain_ms_; |
281 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample( | 318 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample( |
282 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms); | 319 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms); |
283 if (bandwidth_sample) | 320 if (bandwidth_sample) |
284 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_); | 321 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_); |
285 first_packet_send_time_during_high_gain_ms_.reset(); | 322 first_packet_send_time_during_high_gain_ms_.reset(); |
286 } | 323 } |
287 | 324 |
288 bool BbrBweSender::UpdateBandwidthAndMinRtt( | 325 void BbrBweSender::UpdateBandwidthAndMinRtt( |
289 int64_t now_ms, | 326 int64_t now_ms, |
290 const std::vector<uint64_t>& feedback_vector, | 327 const std::vector<uint16_t>& feedback_vector, |
291 int64_t bytes_acked) { | 328 int64_t bytes_acked) { |
292 rtc::Optional<int64_t> min_rtt_sample_ms; | 329 rtc::Optional<int64_t> min_rtt_sample_ms; |
293 for (uint64_t f : feedback_vector) { | 330 for (uint16_t f : feedback_vector) { |
294 PacketStats packet = packet_stats_[f]; | 331 PacketStats packet = packet_stats_[f]; |
295 size_t data_sent_bytes = | 332 size_t data_sent_bytes = |
296 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes; | 333 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes; |
297 int64_t send_time_delta_ms = | 334 int64_t send_time_delta_ms = |
298 packet.last_sent_packet_send_time_ms - packet.send_time_ms; | 335 packet.last_sent_packet_send_time_ms - packet.send_time_ms; |
299 size_t data_acked_bytes = packet.data_acked_bytes - | 336 size_t data_acked_bytes = packet.data_acked_bytes - |
300 packet.data_acked_before_last_acked_packet_bytes; | 337 packet.data_acked_before_last_acked_packet_bytes; |
301 int64_t ack_time_delta_ms = | 338 int64_t ack_time_delta_ms = |
302 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms; | 339 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms; |
303 rtc::Optional<int64_t> bandwidth_sample = | 340 rtc::Optional<int64_t> bandwidth_sample = |
304 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms, | 341 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms, |
305 data_acked_bytes, ack_time_delta_ms); | 342 data_acked_bytes, ack_time_delta_ms); |
306 if (bandwidth_sample) | 343 if (bandwidth_sample) |
307 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, | 344 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, |
308 round_count_); | 345 round_count_); |
309 AddSampleForHighGain(); // Comment to disable bucket for high gain. | 346 // AddSampleForHighGain(); // Comment to disable bucket for high gain. |
310 if (!min_rtt_sample_ms) | 347 if (!min_rtt_sample_ms) |
311 *min_rtt_sample_ms = packet.ack_time_ms - packet.send_time_ms; | 348 min_rtt_sample_ms.emplace(packet.ack_time_ms - packet.send_time_ms); |
312 else | 349 else |
313 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms, | 350 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms, |
314 packet.ack_time_ms - packet.send_time_ms); | 351 packet.ack_time_ms - packet.send_time_ms); |
315 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms, | 352 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms, |
316 packet.ack_time_ms - packet.send_time_ms); | 353 packet.ack_time_ms - packet.send_time_ms); |
317 } | 354 } |
318 if (!min_rtt_sample_ms) | 355 // We only feed RTT samples into the min_rtt filter which were not produced |
319 return false; | 356 // during 1.1 gain phase, to ensure they contain no queueing delay. But if the |
320 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms); | 357 // rtt sample from 1.1 gain phase improves the current estimate then we should |
321 bool min_rtt_expired = min_rtt_filter_->MinRttExpired(now_ms); | 358 // make it as a new best estimate. |
322 return min_rtt_expired; | 359 if (pacing_gain_ <= 1.0f || !min_rtt_filter_->min_rtt_ms() || |
360 *min_rtt_filter_->min_rtt_ms() >= *min_rtt_sample_ms) | |
361 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms); | |
323 } | 362 } |
324 | 363 |
325 void BbrBweSender::EnterStartup() { | 364 void BbrBweSender::EnterStartup() { |
326 mode_ = STARTUP; | 365 mode_ = STARTUP; |
327 pacing_gain_ = kHighGain; | 366 pacing_gain_ = kHighGain; |
328 congestion_window_gain_ = kHighGain; | 367 congestion_window_gain_ = kHighGain; |
329 } | 368 } |
330 | 369 |
331 void BbrBweSender::TryExitingStartup() { | 370 void BbrBweSender::TryExitingStartup() { |
332 if (full_bandwidth_reached_) { | 371 if (full_bandwidth_reached_) { |
(...skipping 25 matching lines...) Expand all Loading... | |
358 | 397 |
359 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { | 398 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { |
360 // Each phase should last rougly min_rtt ms time. | 399 // Each phase should last rougly min_rtt ms time. |
361 bool advance_cycle_phase = false; | 400 bool advance_cycle_phase = false; |
362 if (min_rtt_filter_->min_rtt_ms()) | 401 if (min_rtt_filter_->min_rtt_ms()) |
363 advance_cycle_phase = | 402 advance_cycle_phase = |
364 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); | 403 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); |
365 // If BBR was probing and it couldn't increase data inflight sufficiently in | 404 // If BBR was probing and it couldn't increase data inflight sufficiently in |
366 // one min_rtt time, continue probing. BBR design doc isn't clear about this, | 405 // one min_rtt time, continue probing. BBR design doc isn't clear about this, |
367 // but condition helps in quicker ramp-up and performs better. | 406 // but condition helps in quicker ramp-up and performs better. |
368 if (pacing_gain_ > 1.0 && congestion_window_->data_inflight() < | 407 if (pacing_gain_ > 1.0 && |
369 TargetCongestionWindow(pacing_gain_)) | 408 congestion_window_->data_inflight() < |
409 TargetCongestionWindow(kTargetCongestionWindowGainForHighGain)) | |
370 advance_cycle_phase = false; | 410 advance_cycle_phase = false; |
371 // If BBR has already drained queues there is no point in continuing draining | 411 // If BBR has already drained queues there is no point in continuing draining |
372 // phase. | 412 // phase. |
373 if (pacing_gain_ < 1.0 && | 413 if (pacing_gain_ < 1.0 && |
374 congestion_window_->data_inflight() <= TargetCongestionWindow(1)) | 414 congestion_window_->data_inflight() <= TargetCongestionWindow(1)) |
375 advance_cycle_phase = true; | 415 advance_cycle_phase = true; |
376 if (advance_cycle_phase) { | 416 if (advance_cycle_phase) { |
377 cycle_index_++; | 417 cycle_index_++; |
378 cycle_index_ %= kGainCycleLength; | 418 cycle_index_ %= kGainCycleLength; |
379 pacing_gain_ = kPacingGain[cycle_index_]; | 419 pacing_gain_ = kPacingGain[cycle_index_]; |
380 cycle_start_time_ms_ = now_ms; | 420 cycle_start_time_ms_ = now_ms; |
381 } | 421 } |
382 } | 422 } |
383 | 423 |
384 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { | 424 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { |
385 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) { | 425 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) { |
386 mode_ = PROBE_RTT; | 426 mode_ = PROBE_RTT; |
387 pacing_gain_ = 1; | 427 pacing_gain_ = 1; |
428 congestion_window_gain_ = kProbeRttCongestionWindowGain; | |
388 probe_rtt_start_time_ms_ = now_ms; | 429 probe_rtt_start_time_ms_ = now_ms; |
389 minimum_congestion_window_start_time_ms_.reset(); | 430 minimum_congestion_window_start_time_ms_.reset(); |
390 } | 431 } |
391 } | 432 } |
392 | 433 |
393 // |minimum_congestion_window_start_time_|'s value is set to the first moment | 434 // |minimum_congestion_window_start_time_|'s value is set to the first moment |
394 // when data inflight was less then | 435 // when data inflight was less then |
395 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that | 436 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that |
396 // BBR has been in PROBE_RTT mode for at least one round or 200ms. | 437 // BBR has been in PROBE_RTT mode for at least one round or 200ms. |
397 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { | 438 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { |
398 if (!minimum_congestion_window_start_time_ms_) { | 439 if (!minimum_congestion_window_start_time_ms_) { |
399 if (congestion_window_->data_inflight() <= | 440 if (congestion_window_->data_inflight() <= |
400 CongestionWindow::kMinimumCongestionWindowBytes) { | 441 TargetCongestionWindow(kProbeRttCongestionWindowGain)) { |
401 *minimum_congestion_window_start_time_ms_ = now_ms; | 442 minimum_congestion_window_start_time_ms_.emplace(now_ms); |
402 minimum_congestion_window_start_round_ = round; | 443 minimum_congestion_window_start_round_ = round; |
403 } | 444 } |
404 } else { | 445 } else { |
405 if (now_ms - *minimum_congestion_window_start_time_ms_ >= | 446 if (now_ms - *minimum_congestion_window_start_time_ms_ >= |
406 kProbeRttDurationMs && | 447 kProbeRttDurationMs && |
407 round - minimum_congestion_window_start_round_ >= | 448 round - minimum_congestion_window_start_round_ >= |
408 kProbeRttDurationRounds) | 449 kProbeRttDurationRounds) { |
409 EnterProbeBw(now_ms); | 450 EnterProbeBw(now_ms); |
451 } | |
410 } | 452 } |
411 } | 453 } |
412 | 454 |
413 void BbrBweSender::TryEnteringRecovery(bool new_round_started) { | 455 void BbrBweSender::TryEnteringRecovery(bool new_round_started) { |
414 // If we are already in Recovery don't try to enter. | 456 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_ || |
415 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_) | 457 !min_rtt_filter_->min_rtt_ms()) |
416 return; | 458 return; |
417 uint64_t increased_rtt_round_counter = 0; | 459 uint64_t increased_rtt_round_counter = 0; |
418 // If average RTT for past |kPastRttsFilterSize| rounds has been more than | 460 // If average RTT for past |kPastRttsFilterSize| rounds has been more than |
419 // some multiplier of min_rtt_ms enter Recovery. | 461 // some multiplier of min_rtt_ms enter Recovery. |
420 for (BbrBweSender::AverageRtt i : past_rtts_) { | 462 for (BbrBweSender::AverageRtt i : past_rtts_) { |
421 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >= | 463 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >= |
422 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold) | 464 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold) |
423 increased_rtt_round_counter++; | 465 increased_rtt_round_counter++; |
424 } | 466 } |
425 if (increased_rtt_round_counter < kPastRttsFilterSize) | 467 if (increased_rtt_round_counter < kPastRttsFilterSize) |
(...skipping 27 matching lines...) Expand all Loading... | |
453 bytes_sent_ += media_packet->payload_size(); | 495 bytes_sent_ += media_packet->payload_size(); |
454 PacketStats packet_stats = PacketStats( | 496 PacketStats packet_stats = PacketStats( |
455 media_packet->sequence_number(), 0, | 497 media_packet->sequence_number(), 0, |
456 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_, | 498 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_, |
457 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_); | 499 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_); |
458 packet_stats_[media_packet->sequence_number()] = packet_stats; | 500 packet_stats_[media_packet->sequence_number()] = packet_stats; |
459 last_packet_send_time_ = media_packet->sender_timestamp_ms(); | 501 last_packet_send_time_ = media_packet->sender_timestamp_ms(); |
460 last_packet_sent_sequence_number_ = media_packet->sequence_number(); | 502 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. | 503 // 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) { | 504 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_; | 505 first_packet_send_time_during_high_gain_ms_.emplace( |
506 last_packet_send_time_); | |
464 data_sent_before_high_gain_started_bytes_ = | 507 data_sent_before_high_gain_started_bytes_ = |
465 bytes_sent_ - media_packet->payload_size() / 2; | 508 bytes_sent_ - media_packet->payload_size() / 2; |
466 first_packet_seq_num_during_high_gain_ = | 509 first_packet_seq_num_during_high_gain_ = |
467 media_packet->sequence_number(); | 510 media_packet->sequence_number(); |
468 } | 511 } |
469 // This condition ensures that |last_packet_seq_num_during_high_gain_| | 512 // 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 | 513 // will contain a sequence number of the last packet sent during high gain |
471 // phase. | 514 // phase. |
472 if (pacing_gain_ > 1) { | 515 if (pacing_gain_ > 1) { |
473 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; | 516 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; |
474 data_sent_before_high_gain_ended_bytes_ = | 517 data_sent_before_high_gain_ended_bytes_ = |
475 bytes_sent_ - media_packet->payload_size() / 2; | 518 bytes_sent_ - media_packet->payload_size() / 2; |
476 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number(); | 519 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number(); |
477 } | 520 } |
478 congestion_window_->PacketSent(media_packet->payload_size()); | 521 congestion_window_->PacketSent(media_packet->payload_size()); |
479 } | 522 } |
480 } | 523 } |
481 } | 524 } |
482 | 525 |
483 void BbrBweSender::Process() {} | 526 void BbrBweSender::Process() {} |
484 | 527 |
485 BbrBweReceiver::BbrBweReceiver(int flow_id) | 528 BbrBweReceiver::BbrBweReceiver(int flow_id) |
486 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} | 529 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), |
530 clock_(0), | |
531 packet_feedbacks_(), | |
532 last_feedback_ms_(0) {} | |
487 | 533 |
488 BbrBweReceiver::~BbrBweReceiver() {} | 534 BbrBweReceiver::~BbrBweReceiver() {} |
489 | 535 |
490 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, | 536 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, |
491 const MediaPacket& media_packet) {} | 537 const MediaPacket& media_packet) { |
538 packet_feedbacks_.push_back(media_packet.sequence_number()); | |
539 BweReceiver::ReceivePacket(arrival_time_ms, media_packet); | |
540 } | |
492 | 541 |
493 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { | 542 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { |
494 return nullptr; | 543 last_feedback_ms_ = now_ms; |
544 int64_t corrected_send_time_ms = 0L; | |
545 if (!received_packets_.empty()) { | |
546 PacketIdentifierNode* latest = *(received_packets_.begin()); | |
547 // |latest->send_time_ms| and |latest->arrival_time_ms| could be different | |
548 // because of sender and receiver having different clocks, so we convert the | |
549 // time at which packets' were sent to match receiver's clock. | |
550 corrected_send_time_ms = | |
philipel
2017/08/18 11:22:15
Remove this code and add a comment about why it ex
gnish1
2017/08/18 11:48:42
Done.
| |
551 latest->send_time_ms + now_ms - latest->arrival_time_ms; | |
552 } | |
553 FeedbackPacket* fb = new BbrBweFeedback( | |
554 flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedbacks_); | |
555 packet_feedbacks_.clear(); | |
556 return fb; | |
495 } | 557 } |
496 } // namespace bwe | 558 } // namespace bwe |
497 } // namespace testing | 559 } // namespace testing |
498 } // namespace webrtc | 560 } // namespace webrtc |
OLD | NEW |