// // Copyright (C) 2013 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef SHILL_TRAFFIC_MONITOR_H_ #define SHILL_TRAFFIC_MONITOR_H_ #include #include #include #include #include #include #include // for FRIEND_TEST #include "shill/connection_info.h" #include "shill/connection_info_reader.h" #include "shill/refptr_types.h" #include "shill/socket_info.h" namespace shill { class EventDispatcher; class SocketInfoReader; // TrafficMonitor detects certain abnormal scenarios on a network interface // and notifies an observer of various scenarios via callbacks. class TrafficMonitor { public: // Network problem detected by traffic monitor. enum NetworkProblem { kNetworkProblemCongestedTxQueue = 0, kNetworkProblemDNSFailure, kNetworkProblemMax }; typedef base::Callback NetworkProblemDetectedCallback; TrafficMonitor(const DeviceRefPtr& device, EventDispatcher* dispatcher); virtual ~TrafficMonitor(); // Starts traffic monitoring on the selected device. virtual void Start(); // Stops traffic monitoring on the selected device. virtual void Stop(); // Sets the callback to invoke, if the traffic monitor detects a network // problem, either too many packets are failing to get transmitted over a // TCP connection or DNS is failing. void set_network_problem_detected_callback( const NetworkProblemDetectedCallback& callback) { network_problem_detected_callback_ = callback; } private: friend class TrafficMonitorTest; FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidConnectionState); FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidDevice); FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidTimerState); FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthMultipleEntries); FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthValid); FRIEND_TEST(TrafficMonitorTest, BuildIPPortToTxQueueLengthZero); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsFailureThenSuccess); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsOutstanding); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsStatsReset); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsSuccessful); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOut); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidProtocol); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidSourceIp); FRIEND_TEST(TrafficMonitorTest, SampleTrafficDnsTimedOutOutsideTimeWindow); FRIEND_TEST(TrafficMonitorTest, SampleTrafficNonDnsTimedOut); FRIEND_TEST(TrafficMonitorTest, SampleTrafficStuckTxQueueIncreasingQueueLength); FRIEND_TEST(TrafficMonitorTest, SampleTrafficStuckTxQueueSameQueueLength); FRIEND_TEST(TrafficMonitorTest, SampleTrafficStuckTxQueueVariousQueueLengths); FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueNoConnection); FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueStateChanged); FRIEND_TEST(TrafficMonitorTest, SampleTrafficUnstuckTxQueueZeroQueueLength); FRIEND_TEST(TrafficMonitorTest, StartAndStop); typedef std::map IPPortToTxQueueLengthMap; // The minimum number of samples that indicate an abnormal scenario // required to trigger the callback. static const int kMinimumFailedSamplesToTrigger; // The frequency at which to sample the TCP connections. static const int64_t kSamplingIntervalMilliseconds; // DNS port. static const uint16_t kDnsPort; // If a DNS "connection" time-to-expire falls below this threshold, then // it's considered a timed out DNS request. static const int64_t kDnsTimedOutThresholdSeconds; // Resets congested tx-queues tracking statistics. void ResetCongestedTxQueuesStats(); void ResetCongestedTxQueuesStatsWithLogging(); // Builds map of IP address/port to tx queue lengths from socket info vector. // Skips sockets not on device, tx queue length is 0, connection state is not // established or does not have a pending retransmit timer. void BuildIPPortToTxQueueLength( const std::vector& socket_infos, IPPortToTxQueueLengthMap* tx_queue_length); // Checks for congested tx-queue via network statistics. // Returns |true| if tx-queue is congested. bool IsCongestedTxQueues(); // Resets failing DNS queries tracking statistics. void ResetDnsFailingStats(); void ResetDnsFailingStatsWithLogging(); // Checks to see for failed DNS queries. bool IsDnsFailing(); // Samples traffic (e.g. receive and transmit byte counts) on the // selected device and invokes appropriate callbacks when certain // abnormal scenarios are detected. void SampleTraffic(); // The device on which to perform traffic monitoring. DeviceRefPtr device_; // Dispatcher on which to create delayed tasks. EventDispatcher* dispatcher_; // Callback to invoke when TrafficMonitor needs to sample traffic // of the network interface. base::CancelableClosure sample_traffic_callback_; // Callback to invoke when we detect a network problem. Possible network // problems that can be detected are congested TCP TX queue and DNS failure. // Refer to enum NetworkProblem for all possible network problems that can be // detected by Traffic Monitor. NetworkProblemDetectedCallback network_problem_detected_callback_; // Reads and parses socket information from the system. std::unique_ptr socket_info_reader_; // Number of consecutive congested tx-queue cases sampled. int accummulated_congested_tx_queues_samples_; // Map of tx queue lengths from previous sampling pass. IPPortToTxQueueLengthMap old_tx_queue_lengths_; // Reads and parses connection information from the system. std::unique_ptr connection_info_reader_; // Number of consecutive sample intervals that contains failed DNS requests. int accummulated_dns_failures_samples_; DISALLOW_COPY_AND_ASSIGN(TrafficMonitor); }; } // namespace shill #endif // SHILL_TRAFFIC_MONITOR_H_