| 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 */ |
| 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> |
| 15 |
| 16 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win
dow.h" |
| 14 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_
filter.h" | 17 #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" |
| 15 | 19 |
| 16 namespace webrtc { | 20 namespace webrtc { |
| 17 namespace testing { | 21 namespace testing { |
| 18 namespace bwe { | 22 namespace bwe { |
| 19 namespace { | 23 namespace { |
| 20 const int kFeedbackIntervalsMs = 100; | 24 const int kFeedbackIntervalsMs = 3; |
| 21 // BBR uses this value to double sending rate each round trip. Design document | 25 // BBR uses this value to double sending rate each round trip. Design document |
| 22 // suggests using this value. | 26 // suggests using this value. |
| 23 const float kHighGain = 2.885f; | 27 const float kHighGain = 2.885f; |
| 24 // BBR uses this value to drain queues created during STARTUP in one round trip | 28 // BBR uses this value to drain queues created during STARTUP in one round trip |
| 25 // time. | 29 // time. |
| 26 const float kDrainGain = 1 / kHighGain; | 30 const float kDrainGain = 1 / kHighGain; |
| 27 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from | 31 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from |
| 28 // experiments, according to the design document. | 32 // experiments, according to the design document. |
| 29 const float kStartupGrowthTarget = 1.25f; | 33 const float kStartupGrowthTarget = 1.25f; |
| 30 const int kMaxRoundsWithoutGrowth = 3; | 34 const int kMaxRoundsWithoutGrowth = 3; |
| 35 // Pacing gain values for Probe Bandwidth mode. |
| 36 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; |
| 37 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); |
| 38 // The least amount of rounds PROBE_RTT mode should last. |
| 39 const int kProbeRttDurationRounds = 1; |
| 40 // The least amount of milliseconds PROBE_RTT mode should last. |
| 41 const int kProbeRttDurationMs = 200; |
| 42 // Gain value for congestion window for assuming that network has no queues. |
| 43 const float kTargetCongestionWindowGain = 1; |
| 44 // Gain value for congestion window in PROBE_BW mode. In theory it should be |
| 45 // equal to 1, but in practice because of delayed acks and the way networks |
| 46 // work, it is nice to have some extra room in congestion window for full link |
| 47 // utilization. Value chosen by observations on different tests. |
| 48 const float kCruisingCongestionWindowGain = 1.5f; |
| 49 // Expiration time for min_rtt sample, which is set to 10 seconds according to |
| 50 // BBR design doc. |
| 51 const int64_t kMinRttFilterSizeMs = 10000; |
| 31 } // namespace | 52 } // namespace |
| 32 | 53 |
| 33 BbrBweSender::BbrBweSender(Clock* clock) | 54 BbrBweSender::BbrBweSender(Clock* clock) |
| 34 : BweSender(0), | 55 : BweSender(0), |
| 35 clock_(clock), | 56 clock_(clock), |
| 36 mode_(STARTUP), | 57 mode_(STARTUP), |
| 37 max_bandwidth_filter_(new MaxBandwidthFilter()), | 58 max_bandwidth_filter_(new MaxBandwidthFilter()), |
| 59 min_rtt_filter_(new MinRttFilter()), |
| 60 congestion_window_(new CongestionWindow()), |
| 61 rand_(new Random(time(NULL))), |
| 38 round_count_(0), | 62 round_count_(0), |
| 39 last_packet_sent_(0), | 63 last_packet_sent_(0), |
| 40 round_trip_end_(0), | 64 round_trip_end_(0), |
| 41 full_bandwidth_reached_(false) { | 65 full_bandwidth_reached_(false), |
| 66 cycle_start_time_ms_(0), |
| 67 cycle_index_(0), |
| 68 prior_in_flight_(0), |
| 69 probe_rtt_start_time_ms_(0), |
| 70 minimum_congestion_window_start_time_ms_(), |
| 71 minimum_congestion_window_start_round_(0) { |
| 42 // Initially enter Startup mode. | 72 // Initially enter Startup mode. |
| 43 EnterStartup(); | 73 EnterStartup(); |
| 44 } | 74 } |
| 45 | 75 |
| 46 BbrBweSender::~BbrBweSender() {} | 76 BbrBweSender::~BbrBweSender() {} |
| 47 | 77 |
| 48 int BbrBweSender::GetFeedbackIntervalMs() const { | 78 int BbrBweSender::GetFeedbackIntervalMs() const { |
| 49 return kFeedbackIntervalsMs; | 79 return kFeedbackIntervalsMs; |
| 50 } | 80 } |
| 51 | 81 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 74 case STARTUP: | 104 case STARTUP: |
| 75 TryExitingStartup(); | 105 TryExitingStartup(); |
| 76 break; | 106 break; |
| 77 case DRAIN: | 107 case DRAIN: |
| 78 TryExitingDrain(now_ms); | 108 TryExitingDrain(now_ms); |
| 79 break; | 109 break; |
| 80 case PROBE_BW: | 110 case PROBE_BW: |
| 81 TryUpdatingCyclePhase(now_ms); | 111 TryUpdatingCyclePhase(now_ms); |
| 82 break; | 112 break; |
| 83 case PROBE_RTT: | 113 case PROBE_RTT: |
| 84 TryExitingProbeRtt(now_ms); | 114 TryExitingProbeRtt(now_ms, 0); |
| 85 break; | 115 break; |
| 86 } | 116 } |
| 87 TryEnteringProbeRtt(now_ms); | 117 TryEnteringProbeRtt(now_ms); |
| 88 // TODO(gnish): implement functions updating congestion window and pacing rate | 118 // TODO(gnish): implement functions updating congestion window and pacing rate |
| 89 // controllers. | 119 // controllers. |
| 90 } | 120 } |
| 91 | 121 |
| 122 size_t BbrBweSender::TargetCongestionWindow(float gain) { |
| 123 size_t target_congestion_window = |
| 124 congestion_window_->GetTargetCongestionWindow( |
| 125 max_bandwidth_filter_->max_bandwidth_estimate_bps(), |
| 126 min_rtt_filter_->min_rtt_ms(), gain); |
| 127 return target_congestion_window; |
| 128 } |
| 129 |
| 92 bool BbrBweSender::UpdateBandwidthAndMinRtt() { | 130 bool BbrBweSender::UpdateBandwidthAndMinRtt() { |
| 93 return false; | 131 return false; |
| 94 } | 132 } |
| 95 | 133 |
| 96 void BbrBweSender::EnterStartup() { | 134 void BbrBweSender::EnterStartup() { |
| 97 mode_ = STARTUP; | 135 mode_ = STARTUP; |
| 98 pacing_gain_ = kHighGain; | 136 pacing_gain_ = kHighGain; |
| 99 congestion_window_gain_ = kHighGain; | 137 congestion_window_gain_ = kHighGain; |
| 100 } | 138 } |
| 101 | 139 |
| 102 void BbrBweSender::TryExitingStartup() { | 140 void BbrBweSender::TryExitingStartup() { |
| 103 if (full_bandwidth_reached_) { | 141 if (full_bandwidth_reached_) { |
| 104 mode_ = DRAIN; | 142 mode_ = DRAIN; |
| 105 pacing_gain_ = kDrainGain; | 143 pacing_gain_ = kDrainGain; |
| 106 congestion_window_gain_ = kHighGain; | 144 congestion_window_gain_ = kHighGain; |
| 107 } | 145 } |
| 108 } | 146 } |
| 109 | 147 |
| 110 void BbrBweSender::TryExitingDrain(int64_t now_ms) {} | 148 void BbrBweSender::TryExitingDrain(int64_t now_ms) { |
| 149 if (congestion_window_->data_inflight() <= |
| 150 TargetCongestionWindow(kTargetCongestionWindowGain)) |
| 151 EnterProbeBw(now_ms); |
| 152 } |
| 111 | 153 |
| 112 void BbrBweSender::EnterProbeBw(int64_t now_ms) {} | 154 // Start probing with a random gain value, which is different form 0.75, |
| 155 // starting with 0.75 doesn't offer any benefits as there are no queues to be |
| 156 // drained. |
| 157 void BbrBweSender::EnterProbeBw(int64_t now_ms) { |
| 158 mode_ = PROBE_BW; |
| 159 congestion_window_gain_ = kCruisingCongestionWindowGain; |
| 160 int index = rand_->Rand(kGainCycleLength - 2); |
| 161 if (index == 1) |
| 162 index = kGainCycleLength - 1; |
| 163 pacing_gain_ = kPacingGain[index]; |
| 164 cycle_start_time_ms_ = now_ms; |
| 165 cycle_index_ = index; |
| 166 } |
| 113 | 167 |
| 114 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {} | 168 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { |
| 169 // Each phase should last rougly min_rtt ms time. |
| 170 bool advance_cycle_phase = false; |
| 171 if (min_rtt_filter_->min_rtt_ms()) |
| 172 advance_cycle_phase = |
| 173 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); |
| 174 // If BBR was probing and it couldn't increase data inflight sufficiently in |
| 175 // one min_rtt time, continue probing. BBR design doc isn't clear about this, |
| 176 // but condition helps in quicker ramp-up and performs better. |
| 177 if (pacing_gain_ > 1.0 && |
| 178 prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) |
| 179 advance_cycle_phase = false; |
| 180 // If BBR has already drained queues there is no point in continuing draining |
| 181 // phase. |
| 182 if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) |
| 183 advance_cycle_phase = true; |
| 184 if (advance_cycle_phase) { |
| 185 cycle_index_++; |
| 186 cycle_index_ %= kGainCycleLength; |
| 187 pacing_gain_ = kPacingGain[cycle_index_]; |
| 188 cycle_start_time_ms_ = now_ms; |
| 189 } |
| 190 } |
| 115 | 191 |
| 116 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {} | 192 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { |
| 117 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms) {} | 193 if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && |
| 194 mode_ != PROBE_RTT) { |
| 195 mode_ = PROBE_RTT; |
| 196 pacing_gain_ = 1; |
| 197 probe_rtt_start_time_ms_ = now_ms; |
| 198 minimum_congestion_window_start_time_ms_.reset(); |
| 199 } |
| 200 } |
| 201 |
| 202 // minimum_congestion_window_start_time_'s value is set to the first moment when |
| 203 // data inflight was less then kMinimumCongestionWindowBytes, we should make |
| 204 // 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) { |
| 206 if (!minimum_congestion_window_start_time_ms_) { |
| 207 if (congestion_window_->data_inflight() <= |
| 208 CongestionWindow::kMinimumCongestionWindowBytes) { |
| 209 *minimum_congestion_window_start_time_ms_ = now_ms; |
| 210 minimum_congestion_window_start_round_ = round; |
| 211 } |
| 212 } else { |
| 213 if (now_ms - *minimum_congestion_window_start_time_ms_ >= |
| 214 kProbeRttDurationMs && |
| 215 round - minimum_congestion_window_start_round_ >= |
| 216 kProbeRttDurationRounds) |
| 217 EnterProbeBw(now_ms); |
| 218 } |
| 219 } |
| 118 | 220 |
| 119 int64_t BbrBweSender::TimeUntilNextProcess() { | 221 int64_t BbrBweSender::TimeUntilNextProcess() { |
| 120 return 100; | 222 return 100; |
| 121 } | 223 } |
| 122 | 224 |
| 123 void BbrBweSender::OnPacketsSent(const Packets& packets) { | 225 void BbrBweSender::OnPacketsSent(const Packets& packets) { |
| 124 last_packet_sent_ = | 226 last_packet_sent_ = |
| 125 static_cast<const MediaPacket*>(packets.back())->sequence_number(); | 227 static_cast<const MediaPacket*>(packets.back())->sequence_number(); |
| 126 } | 228 } |
| 127 | 229 |
| 128 void BbrBweSender::Process() {} | 230 void BbrBweSender::Process() {} |
| 129 | 231 |
| 130 BbrBweReceiver::BbrBweReceiver(int flow_id) | 232 BbrBweReceiver::BbrBweReceiver(int flow_id) |
| 131 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} | 233 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} |
| 132 | 234 |
| 133 BbrBweReceiver::~BbrBweReceiver() {} | 235 BbrBweReceiver::~BbrBweReceiver() {} |
| 134 | 236 |
| 135 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, | 237 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, |
| 136 const MediaPacket& media_packet) {} | 238 const MediaPacket& media_packet) {} |
| 137 | 239 |
| 138 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { | 240 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { |
| 139 return nullptr; | 241 return nullptr; |
| 140 } | 242 } |
| 141 } // namespace bwe | 243 } // namespace bwe |
| 142 } // namespace testing | 244 } // namespace testing |
| 143 } // namespace webrtc | 245 } // namespace webrtc |
| OLD | NEW |