• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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