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