Home | History | Annotate | Download | only in shill
      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 
     34 namespace shill {
     35 
     36 class EventDispatcher;
     37 class SocketInfoReader;
     38 
     39 // TrafficMonitor detects certain abnormal scenarios on a network interface
     40 // and notifies an observer of various scenarios via callbacks.
     41 class 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