| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/core/congestion_control/cubic_bytes.h" | 5 #include "net/quic/core/congestion_control/cubic_bytes.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <cmath> | 9 #include <cmath> |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 // curve. This additional backoff factor is expected to give up bandwidth to | 36 // curve. This additional backoff factor is expected to give up bandwidth to |
| 37 // new concurrent flows and speed up convergence. | 37 // new concurrent flows and speed up convergence. |
| 38 const float kBetaLastMax = 0.85f; | 38 const float kBetaLastMax = 0.85f; |
| 39 | 39 |
| 40 } // namespace | 40 } // namespace |
| 41 | 41 |
| 42 CubicBytes::CubicBytes(const QuicClock* clock) | 42 CubicBytes::CubicBytes(const QuicClock* clock) |
| 43 : clock_(clock), | 43 : clock_(clock), |
| 44 num_connections_(kDefaultNumConnections), | 44 num_connections_(kDefaultNumConnections), |
| 45 epoch_(QuicTime::Zero()), | 45 epoch_(QuicTime::Zero()), |
| 46 last_update_time_(QuicTime::Zero()) { | 46 last_update_time_(QuicTime::Zero()), |
| 47 fix_convex_mode_(false) { |
| 47 Reset(); | 48 Reset(); |
| 48 } | 49 } |
| 49 | 50 |
| 50 void CubicBytes::SetNumConnections(int num_connections) { | 51 void CubicBytes::SetNumConnections(int num_connections) { |
| 51 num_connections_ = num_connections; | 52 num_connections_ = num_connections; |
| 52 } | 53 } |
| 53 | 54 |
| 54 float CubicBytes::Alpha() const { | 55 float CubicBytes::Alpha() const { |
| 55 // TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that | 56 // TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that |
| 56 // beta here is a cwnd multiplier, and is equal to 1-beta from the paper. | 57 // beta here is a cwnd multiplier, and is equal to 1-beta from the paper. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 70 void CubicBytes::Reset() { | 71 void CubicBytes::Reset() { |
| 71 epoch_ = QuicTime::Zero(); // Reset time. | 72 epoch_ = QuicTime::Zero(); // Reset time. |
| 72 last_update_time_ = QuicTime::Zero(); // Reset time. | 73 last_update_time_ = QuicTime::Zero(); // Reset time. |
| 73 last_congestion_window_ = 0; | 74 last_congestion_window_ = 0; |
| 74 last_max_congestion_window_ = 0; | 75 last_max_congestion_window_ = 0; |
| 75 acked_bytes_count_ = 0; | 76 acked_bytes_count_ = 0; |
| 76 estimated_tcp_congestion_window_ = 0; | 77 estimated_tcp_congestion_window_ = 0; |
| 77 origin_point_congestion_window_ = 0; | 78 origin_point_congestion_window_ = 0; |
| 78 time_to_origin_point_ = 0; | 79 time_to_origin_point_ = 0; |
| 79 last_target_congestion_window_ = 0; | 80 last_target_congestion_window_ = 0; |
| 81 fix_convex_mode_ = false; |
| 82 } |
| 83 |
| 84 void CubicBytes::SetFixConvexMode(bool fix_convex_mode) { |
| 85 fix_convex_mode_ = fix_convex_mode; |
| 80 } | 86 } |
| 81 | 87 |
| 82 void CubicBytes::OnApplicationLimited() { | 88 void CubicBytes::OnApplicationLimited() { |
| 83 // When sender is not using the available congestion window, the window does | 89 // When sender is not using the available congestion window, the window does |
| 84 // not grow. But to be RTT-independent, Cubic assumes that the sender has been | 90 // not grow. But to be RTT-independent, Cubic assumes that the sender has been |
| 85 // using the entire window during the time since the beginning of the current | 91 // using the entire window during the time since the beginning of the current |
| 86 // "epoch" (the end of the last loss recovery period). Since | 92 // "epoch" (the end of the last loss recovery period). Since |
| 87 // application-limited periods break this assumption, we reset the epoch when | 93 // application-limited periods break this assumption, we reset the epoch when |
| 88 // in such a period. This reset effectively freezes congestion window growth | 94 // in such a period. This reset effectively freezes congestion window growth |
| 89 // through application-limited periods and allows Cubic growth to continue | 95 // through application-limited periods and allows Cubic growth to continue |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 } | 145 } |
| 140 } | 146 } |
| 141 // Change the time unit from microseconds to 2^10 fractions per second. Take | 147 // Change the time unit from microseconds to 2^10 fractions per second. Take |
| 142 // the round trip time in account. This is done to allow us to use shift as a | 148 // the round trip time in account. This is done to allow us to use shift as a |
| 143 // divide operator. | 149 // divide operator. |
| 144 int64_t elapsed_time = | 150 int64_t elapsed_time = |
| 145 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / | 151 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / |
| 146 kNumMicrosPerSecond; | 152 kNumMicrosPerSecond; |
| 147 | 153 |
| 148 int64_t offset = time_to_origin_point_ - elapsed_time; | 154 int64_t offset = time_to_origin_point_ - elapsed_time; |
| 155 if (fix_convex_mode_) { |
| 156 // Right-shifts of negative, signed numbers have |
| 157 // implementation-dependent behavior. In the fix, force the |
| 158 // offset to be positive, as is done in the kernel. |
| 159 const int64_t positive_offset = labs(time_to_origin_point_ - elapsed_time); |
| 160 offset = positive_offset; |
| 161 } |
| 149 QuicByteCount delta_congestion_window = | 162 QuicByteCount delta_congestion_window = |
| 150 ((kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale) * | 163 ((kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale) * |
| 151 kDefaultTCPMSS; | 164 kDefaultTCPMSS; |
| 152 | 165 |
| 166 const bool add_delta = elapsed_time > time_to_origin_point_; |
| 167 DCHECK(add_delta || |
| 168 (origin_point_congestion_window_ > delta_congestion_window)); |
| 153 QuicByteCount target_congestion_window = | 169 QuicByteCount target_congestion_window = |
| 154 origin_point_congestion_window_ - delta_congestion_window; | 170 (fix_convex_mode_ && add_delta) |
| 171 ? origin_point_congestion_window_ + delta_congestion_window |
| 172 : origin_point_congestion_window_ - delta_congestion_window; |
| 155 // Limit the CWND increase to half the acked bytes. | 173 // Limit the CWND increase to half the acked bytes. |
| 156 target_congestion_window = | 174 target_congestion_window = |
| 157 min(target_congestion_window, | 175 min(target_congestion_window, |
| 158 current_congestion_window + acked_bytes_count_ / 2); | 176 current_congestion_window + acked_bytes_count_ / 2); |
| 159 | 177 |
| 160 DCHECK_LT(0u, estimated_tcp_congestion_window_); | 178 DCHECK_LT(0u, estimated_tcp_congestion_window_); |
| 161 // Increase the window by Alpha * 1 MSS of bytes every time we ack an | 179 // Increase the window by approximately Alpha * 1 MSS of bytes every |
| 162 // estimated tcp window of bytes. | 180 // time we ack an estimated tcp window of bytes. For small |
| 181 // congestion windows (less than 25), the formula below will |
| 182 // increase slightly slower than linearly per estimated tcp window |
| 183 // of bytes. |
| 163 estimated_tcp_congestion_window_ += acked_bytes_count_ * | 184 estimated_tcp_congestion_window_ += acked_bytes_count_ * |
| 164 (Alpha() * kDefaultTCPMSS) / | 185 (Alpha() * kDefaultTCPMSS) / |
| 165 estimated_tcp_congestion_window_; | 186 estimated_tcp_congestion_window_; |
| 166 acked_bytes_count_ = 0; | 187 acked_bytes_count_ = 0; |
| 167 | 188 |
| 168 // We have a new cubic congestion window. | 189 // We have a new cubic congestion window. |
| 169 last_target_congestion_window_ = target_congestion_window; | 190 last_target_congestion_window_ = target_congestion_window; |
| 170 | 191 |
| 171 // Compute target congestion_window based on cubic target and estimated TCP | 192 // Compute target congestion_window based on cubic target and estimated TCP |
| 172 // congestion_window, use highest (fastest). | 193 // congestion_window, use highest (fastest). |
| 173 if (target_congestion_window < estimated_tcp_congestion_window_) { | 194 if (target_congestion_window < estimated_tcp_congestion_window_) { |
| 174 target_congestion_window = estimated_tcp_congestion_window_; | 195 target_congestion_window = estimated_tcp_congestion_window_; |
| 175 } | 196 } |
| 176 | 197 |
| 177 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; | 198 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; |
| 178 return target_congestion_window; | 199 return target_congestion_window; |
| 179 } | 200 } |
| 180 | 201 |
| 181 } // namespace net | 202 } // namespace net |
| OLD | NEW |