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