1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_ 6 #define NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_ 7 8 #include <array> 9 #include <map> 10 #include <optional> 11 #include <string> 12 13 #include "base/sequence_checker.h" 14 #include "base/time/time.h" 15 #include "net/base/net_export.h" 16 #include "net/base/network_change_notifier.h" 17 #include "net/nqe/effective_connection_type.h" 18 #include "net/nqe/network_quality.h" 19 20 namespace net { 21 22 // Forces NQE to return a specific effective connection type. Set using the 23 // |params| provided to the NetworkQualityEstimatorParams constructor. 24 NET_EXPORT extern const char kForceEffectiveConnectionType[]; 25 NET_EXPORT extern const char kEffectiveConnectionTypeSlow2GOnCellular[]; 26 27 // HTTP RTT thresholds for different effective connection types. 28 inline constexpr std::array<base::TimeDelta, EFFECTIVE_CONNECTION_TYPE_LAST> 29 kHttpRttEffectiveConnectionTypeThresholds = { 30 base::Milliseconds(0), base::Milliseconds(0), 31 base::Milliseconds(2010), base::Milliseconds(1420), 32 base::Milliseconds(272), base::Milliseconds(0)}; 33 34 // NetworkQualityEstimatorParams computes the configuration parameters for 35 // the network quality estimator. 36 class NET_EXPORT NetworkQualityEstimatorParams { 37 public: 38 // |params| is the map containing all field trial parameters related to 39 // NetworkQualityEstimator field trial. 40 explicit NetworkQualityEstimatorParams( 41 const std::map<std::string, std::string>& params); 42 43 NetworkQualityEstimatorParams(const NetworkQualityEstimatorParams&) = delete; 44 NetworkQualityEstimatorParams& operator=( 45 const NetworkQualityEstimatorParams&) = delete; 46 47 ~NetworkQualityEstimatorParams(); 48 49 // Returns the default observation for connection |type|. The default 50 // observations are different for different connection types (e.g., 2G, 3G, 51 // 4G, WiFi). The default observations may be used to determine the network 52 // quality in absence of any other information. 53 const nqe::internal::NetworkQuality& DefaultObservation( 54 NetworkChangeNotifier::ConnectionType type) const; 55 56 // Returns the typical network quality for connection |type|. 57 const nqe::internal::NetworkQuality& TypicalNetworkQuality( 58 EffectiveConnectionType type) const; 59 60 // Returns the threshold for effective connection type |type|. 61 const nqe::internal::NetworkQuality& ConnectionThreshold( 62 EffectiveConnectionType type) const; 63 64 // Returns the minimum number of requests in-flight to consider the network 65 // fully utilized. A throughput observation is taken only when the network is 66 // considered as fully utilized. 67 size_t throughput_min_requests_in_flight() const; 68 69 // Tiny transfer sizes may give inaccurate throughput results. 70 // Minimum size of the transfer over which the throughput is computed. 71 int64_t GetThroughputMinTransferSizeBits() const; 72 73 // Returns the weight multiplier per second, which represents the factor by 74 // which the weight of an observation reduces every second. weight_multiplier_per_second()75 double weight_multiplier_per_second() const { 76 return weight_multiplier_per_second_; 77 } 78 79 // Returns an unset value if the effective connection type has not been forced 80 // via the |params| provided to this class. Otherwise, returns a value set to 81 // the effective connection type that has been forced. Forced ECT can be 82 // forced based on |connection_type| (e.g. Slow-2G on cellular, and default on 83 // other connection type). 84 std::optional<EffectiveConnectionType> GetForcedEffectiveConnectionType( 85 NetworkChangeNotifier::ConnectionType connection_type); 86 SetForcedEffectiveConnectionType(EffectiveConnectionType forced_effective_connection_type)87 void SetForcedEffectiveConnectionType( 88 EffectiveConnectionType forced_effective_connection_type) { 89 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 90 forced_effective_connection_type_ = forced_effective_connection_type; 91 } 92 93 // Returns true if reading from the persistent cache is enabled. persistent_cache_reading_enabled()94 bool persistent_cache_reading_enabled() const { 95 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 96 return persistent_cache_reading_enabled_; 97 } 98 set_persistent_cache_reading_enabled(bool persistent_cache_reading_enabled)99 void set_persistent_cache_reading_enabled( 100 bool persistent_cache_reading_enabled) { 101 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 102 persistent_cache_reading_enabled_ = persistent_cache_reading_enabled; 103 } 104 105 // Returns the the minimum interval betweeen consecutive notifications to a 106 // single socket watcher. min_socket_watcher_notification_interval()107 base::TimeDelta min_socket_watcher_notification_interval() const { 108 return min_socket_watcher_notification_interval_; 109 } 110 111 // Number of bytes received during a throughput observation window of duration 112 // 1 HTTP RTT should be at least the value returned by this method times 113 // the typical size of a congestion window. If not, the throughput observation 114 // window is heuristically determined as hanging. throughput_hanging_requests_cwnd_size_multiplier()115 double throughput_hanging_requests_cwnd_size_multiplier() const { 116 return throughput_hanging_requests_cwnd_size_multiplier_; 117 } 118 119 // Returns the multiplier by which the transport RTT should be multipled when 120 // computing the HTTP RTT. The multiplied value of the transport RTT serves 121 // as a lower bound to the HTTP RTT estimate. e.g., if the multiplied 122 // transport RTT is 100 msec., then HTTP RTT estimate can't be lower than 123 // 100 msec. Returns a negative value if the param is not set. lower_bound_http_rtt_transport_rtt_multiplier()124 double lower_bound_http_rtt_transport_rtt_multiplier() const { 125 return lower_bound_http_rtt_transport_rtt_multiplier_; 126 } 127 128 // Returns the multiplier by which the end to end RTT estimate should be 129 // multiplied when computing the HTTP RTT. The multiplied value of the 130 // end to end RTT serves as an upper bound to the HTTP RTT estimate. e.g., if 131 // the multiplied end to end RTT is 100 msec., then HTTP RTT estimate can't be 132 // more than |upper_bound_http_rtt_endtoend_rtt_multiplier| times 100 msec. 133 // Returns a negative value if the param is not set. upper_bound_http_rtt_endtoend_rtt_multiplier()134 double upper_bound_http_rtt_endtoend_rtt_multiplier() const { 135 return upper_bound_http_rtt_endtoend_rtt_multiplier_; 136 } 137 138 // For the purpose of estimating the HTTP RTT, a request is marked as hanging 139 // only if its RTT is at least this times the transport RTT estimate. hanging_request_http_rtt_upper_bound_transport_rtt_multiplier()140 int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier() const { 141 return hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_; 142 } 143 144 // For the purpose of estimating the HTTP RTT, a request is marked as hanging 145 // only if its RTT is at least this times the HTTP RTT estimate. hanging_request_http_rtt_upper_bound_http_rtt_multiplier()146 int hanging_request_http_rtt_upper_bound_http_rtt_multiplier() const { 147 return hanging_request_http_rtt_upper_bound_http_rtt_multiplier_; 148 } 149 150 // For the purpose of estimating the HTTP RTT, a request is marked as hanging 151 // only if its RTT is at least as much the value returned by this method. hanging_request_upper_bound_min_http_rtt()152 base::TimeDelta hanging_request_upper_bound_min_http_rtt() const { 153 return hanging_request_upper_bound_min_http_rtt_; 154 } 155 156 // Returns the number of transport RTT observations that should be available 157 // before the transport RTT estimate can be used to clamp the HTTP RTT 158 // estimate. Set to 5 by default which ensures that when the transport RTT 159 // is available only from the connection type, it is not used for computing 160 // the HTTP RTT estimate. http_rtt_transport_rtt_min_count()161 size_t http_rtt_transport_rtt_min_count() const { 162 return http_rtt_transport_rtt_min_count_; 163 } 164 165 // Returns the minimum interval between successive computations of the 166 // increase in transport RTT. increase_in_transport_rtt_logging_interval()167 base::TimeDelta increase_in_transport_rtt_logging_interval() const { 168 return increase_in_transport_rtt_logging_interval_; 169 } 170 171 // The maximum age of RTT observations for them to be considered recent for 172 // the computation of the increase in RTT. recent_time_threshold()173 base::TimeDelta recent_time_threshold() const { 174 return recent_time_threshold_; 175 } 176 177 // The maximum age of observations for them to be considered useful for 178 // calculating the minimum transport RTT from the historical data. historical_time_threshold()179 base::TimeDelta historical_time_threshold() const { 180 return historical_time_threshold_; 181 } 182 183 // Determines if the responses smaller than |kMinTransferSizeInBytes| 184 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the 185 // network quality. Set to true only for tests. 186 bool use_small_responses() const; 187 188 // Returns the typical HTTP RTT that maps to the given 189 // |effective_connection_type|. May return invalid value if 190 // |effective_connection_type| is less than Slow2G or faster than 4G, 191 static base::TimeDelta GetDefaultTypicalHttpRtt( 192 EffectiveConnectionType effective_connection_type); 193 194 // Returns the typical downslink throughput (in kbps) that maps to the given 195 // |effective_connection_type|. May return invalid value if 196 // |effective_connection_type| is less than Slow2G or faster than 4G, 197 static int32_t GetDefaultTypicalDownlinkKbps( 198 EffectiveConnectionType effective_connection_type); 199 200 // |use_small_responses| should only be true when testing. 201 // Allows the responses smaller than |kMinTransferSizeInBits| to be used for 202 // network quality estimation. 203 void SetUseSmallResponsesForTesting(bool use_small_responses); 204 205 // If an in-flight request does not receive any data for a duration longer 206 // than the value of this multiplier times the current HTTP RTT estimate, then 207 // the request should be considered as hanging. If this multiplier has a 208 // negative or a zero value, then none of the request should be considered as 209 // hanging. hanging_request_duration_http_rtt_multiplier()210 int hanging_request_duration_http_rtt_multiplier() const { 211 return hanging_request_duration_http_rtt_multiplier_; 212 } 213 214 // An in-flight request may be marked as hanging only if it does not receive 215 // any data for at least this duration. hanging_request_min_duration()216 base::TimeDelta hanging_request_min_duration() const { 217 return hanging_request_min_duration_; 218 } 219 220 // Returns true if default values provided by the platform should be used for 221 // estimation. Set to false only for testing. add_default_platform_observations()222 bool add_default_platform_observations() const { 223 return add_default_platform_observations_; 224 } 225 226 // Number of observations received after which the effective connection type 227 // should be recomputed. count_new_observations_received_compute_ect()228 size_t count_new_observations_received_compute_ect() const { 229 return count_new_observations_received_compute_ect_; 230 } 231 232 // Maximum number of observations that can be held in a single 233 // ObservationBuffer. observation_buffer_size()234 size_t observation_buffer_size() const { return observation_buffer_size_; } 235 236 // Minimun interval between consecutive notifications from socket 237 // watchers who live on the same thread as the network quality estimator. socket_watchers_min_notification_interval()238 base::TimeDelta socket_watchers_min_notification_interval() const { 239 return socket_watchers_min_notification_interval_; 240 } 241 242 // Returns true if end-to-end RTT estimates can be used for computing network 243 // quality estimate. use_end_to_end_rtt()244 bool use_end_to_end_rtt() const { return use_end_to_end_rtt_; } 245 246 // Returns a multiplier which is used to clamp Kbps on slow connections. For 247 // a given ECT, the upper bound on Kbps is computed based on this returned 248 // multiplier and the typical Kbps for the given ECT. If 249 // upper_bound_typical_kbps_multiplier() is -1, then clamping should be 250 // disabled. upper_bound_typical_kbps_multiplier()251 double upper_bound_typical_kbps_multiplier() const { 252 return upper_bound_typical_kbps_multiplier_; 253 } 254 255 // Returns true if RTTs should be adjusted based on RTT counts. 256 // If there are not enough transport RTT samples, end-to-end RTT samples and 257 // the cached estimates are unavailble/too stale, then the computed value of 258 // HTTP RTT can't be trusted due to hanging GETs. In that case, NQE returns 259 // the typical HTTP RTT for a fast connection if 260 // adjust_rtt_based_on_rtt_counts() returns true. adjust_rtt_based_on_rtt_counts()261 bool adjust_rtt_based_on_rtt_counts() const { 262 return adjust_rtt_based_on_rtt_counts_; 263 } 264 265 // Sets the forced effective connection type as |type|. 266 void SetForcedEffectiveConnectionTypeForTesting(EffectiveConnectionType type); 267 268 private: 269 // Map containing all field trial parameters related to 270 // NetworkQualityEstimator field trial. 271 const std::map<std::string, std::string> params_; 272 273 const size_t throughput_min_requests_in_flight_; 274 const int throughput_min_transfer_size_kilobytes_; 275 const double throughput_hanging_requests_cwnd_size_multiplier_; 276 const double weight_multiplier_per_second_; 277 std::optional<EffectiveConnectionType> forced_effective_connection_type_; 278 const bool forced_effective_connection_type_on_cellular_only_; 279 bool persistent_cache_reading_enabled_; 280 const base::TimeDelta min_socket_watcher_notification_interval_; 281 const double lower_bound_http_rtt_transport_rtt_multiplier_ = 1.0; 282 const double upper_bound_http_rtt_endtoend_rtt_multiplier_; 283 const int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_; 284 const int hanging_request_http_rtt_upper_bound_http_rtt_multiplier_; 285 const base::TimeDelta hanging_request_upper_bound_min_http_rtt_ = 286 base::Milliseconds(500); 287 const size_t http_rtt_transport_rtt_min_count_; 288 const base::TimeDelta increase_in_transport_rtt_logging_interval_; 289 const base::TimeDelta recent_time_threshold_; 290 const base::TimeDelta historical_time_threshold_; 291 const int hanging_request_duration_http_rtt_multiplier_; 292 const base::TimeDelta hanging_request_min_duration_ = 293 base::Milliseconds(3000); 294 const bool add_default_platform_observations_; 295 const size_t count_new_observations_received_compute_ect_; 296 const size_t observation_buffer_size_; 297 const base::TimeDelta socket_watchers_min_notification_interval_; 298 const bool use_end_to_end_rtt_ = true; 299 const double upper_bound_typical_kbps_multiplier_; 300 const bool adjust_rtt_based_on_rtt_counts_; 301 302 bool use_small_responses_ = false; 303 304 // Default network quality observations obtained from |params_|. 305 nqe::internal::NetworkQuality 306 default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1]; 307 308 // Typical network quality for different effective connection types obtained 309 // from |params_|. 310 nqe::internal::NetworkQuality typical_network_quality_ 311 [EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST]; 312 313 // Thresholds for different effective connection types obtained from 314 // |params_|. These thresholds encode how different connection types behave 315 // in general. 316 nqe::internal::NetworkQuality connection_thresholds_ 317 [EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST]; 318 319 SEQUENCE_CHECKER(sequence_checker_); 320 }; 321 322 } // namespace net 323 324 #endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_ 325