1//
2// Copyright (C) 2013 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef SHILL_TRAFFIC_MONITOR_H_
18#define SHILL_TRAFFIC_MONITOR_H_
19
20#include <map>
21#include <memory>
22#include <string>
23#include <vector>
24
25#include <base/callback.h>
26#include <base/cancelable_callback.h>
27#include <gtest/gtest_prod.h>  // for FRIEND_TEST
28
29#include "shill/connection_info.h"
30#include "shill/connection_info_reader.h"
31#include "shill/refptr_types.h"
32#include "shill/socket_info.h"
33
34namespace shill {
35
36class EventDispatcher;
37class SocketInfoReader;
38
39// TrafficMonitor detects certain abnormal scenarios on a network interface
40// and notifies an observer of various scenarios via callbacks.
41class TrafficMonitor {
42 public:
43  // Network problem detected by traffic monitor.
44  enum NetworkProblem {
45    kNetworkProblemCongestedTxQueue = 0,
46    kNetworkProblemDNSFailure,
47    kNetworkProblemMax
48  };
49
50  typedef base::Callback<void(int)> NetworkProblemDetectedCallback;
51
52  TrafficMonitor(const DeviceRefPtr& device, EventDispatcher* dispatcher);
53  virtual ~TrafficMonitor();
54
55  // Starts traffic monitoring on the selected device.
56  virtual void Start();
57
58  // Stops traffic monitoring on the selected device.
59  virtual void Stop();
60
61  // Sets the callback to invoke, if the traffic monitor detects a network
62  // problem, either too many packets are failing to get transmitted over a
63  // TCP connection or DNS is failing.
64  void set_network_problem_detected_callback(
65      const NetworkProblemDetectedCallback& callback) {
66    network_problem_detected_callback_ = callback;
67  }
68
69 private:
70  friend class TrafficMonitorTest;
71  FRIEND_TEST(TrafficMonitorTest,
72      BuildIPPortToTxQueueLengthInvalidConnectionState);
73  FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidDevice);
74  FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidTimerState);
75  FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthMultipleEntries);
76  FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthValid);
77  FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthZero);
78  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsFailureThenSuccess);
79  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsOutstanding);
80  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsStatsReset);
81  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsSuccessful);
82  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOut);
83  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidProtocol);
84  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidSourceIp);
85  FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutOutsideTimeWindow);
86  FRIEND_TEST(TrafficMonitorTest, SampleTrafficNonDnsTimedOut);
87  FRIEND_TEST(TrafficMonitorTest,
88      SampleTrafficStuckTxQueueIncreasingQueueLength);
89  FRIEND_TEST(TrafficMonitorTest, SampleTrafficStuckTxQueueSameQueueLength);
90  FRIEND_TEST(TrafficMonitorTest,
91      SampleTrafficStuckTxQueueVariousQueueLengths);
92  FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueNoConnection);
93  FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueStateChanged);
94  FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueZeroQueueLength);
95  FRIEND_TEST(TrafficMonitorTest, StartAndStop);
96
97  typedef std::map<std::string, uint64_t> IPPortToTxQueueLengthMap;
98
99  // The minimum number of samples that indicate an abnormal scenario
100  // required to trigger the callback.
101  static const int kMinimumFailedSamplesToTrigger;
102  // The frequency at which to sample the TCP connections.
103  static const int64_t kSamplingIntervalMilliseconds;
104  // DNS port.
105  static const uint16_t kDnsPort;
106  // If a DNS "connection" time-to-expire falls below this threshold, then
107  // it's considered a timed out DNS request.
108  static const int64_t kDnsTimedOutThresholdSeconds;
109
110  // Resets congested tx-queues tracking statistics.
111  void ResetCongestedTxQueuesStats();
112  void ResetCongestedTxQueuesStatsWithLogging();
113
114  // Builds map of IP address/port to tx queue lengths from socket info vector.
115  // Skips sockets not on device, tx queue length is 0, connection state is not
116  // established or does not have a pending retransmit timer.
117  void BuildIPPortToTxQueueLength(
118      const std::vector<SocketInfo>& socket_infos,
119      IPPortToTxQueueLengthMap* tx_queue_length);
120
121  // Checks for congested tx-queue via network statistics.
122  // Returns |true| if tx-queue is congested.
123  bool IsCongestedTxQueues();
124
125  // Resets failing DNS queries tracking statistics.
126  void ResetDnsFailingStats();
127  void ResetDnsFailingStatsWithLogging();
128
129  // Checks to see for failed DNS queries.
130  bool IsDnsFailing();
131
132  // Samples traffic (e.g. receive and transmit byte counts) on the
133  // selected device and invokes appropriate callbacks when certain
134  // abnormal scenarios are detected.
135  void SampleTraffic();
136
137  // The device on which to perform traffic monitoring.
138  DeviceRefPtr device_;
139
140  // Dispatcher on which to create delayed tasks.
141  EventDispatcher* dispatcher_;
142
143  // Callback to invoke when TrafficMonitor needs to sample traffic
144  // of the network interface.
145  base::CancelableClosure sample_traffic_callback_;
146
147  // Callback to invoke when we detect a network problem. Possible network
148  // problems that can be detected are congested TCP TX queue and DNS failure.
149  // Refer to enum NetworkProblem for all possible network problems that can be
150  // detected by Traffic Monitor.
151  NetworkProblemDetectedCallback network_problem_detected_callback_;
152
153  // Reads and parses socket information from the system.
154  std::unique_ptr<SocketInfoReader> socket_info_reader_;
155
156  // Number of consecutive congested tx-queue cases sampled.
157  int accummulated_congested_tx_queues_samples_;
158
159  // Map of tx queue lengths from previous sampling pass.
160  IPPortToTxQueueLengthMap old_tx_queue_lengths_;
161
162  // Reads and parses connection information from the system.
163  std::unique_ptr<ConnectionInfoReader> connection_info_reader_;
164
165  // Number of consecutive sample intervals that contains failed DNS requests.
166  int accummulated_dns_failures_samples_;
167
168  DISALLOW_COPY_AND_ASSIGN(TrafficMonitor);
169};
170
171}  // namespace shill
172
173#endif  // SHILL_TRAFFIC_MONITOR_H_
174