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