// // Copyright (C) 2015 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_ACTIVE_LINK_MONITOR_H_ #define SHILL_ACTIVE_LINK_MONITOR_H_ #include <time.h> #include <memory> #include <string> #include <base/callback.h> #include <base/cancelable_callback.h> #include "shill/metrics.h" #include "shill/net/byte_string.h" #include "shill/refptr_types.h" namespace shill { class ArpClient; class DeviceInfo; class EventDispatcher; class IOHandler; class Time; // ActiveLinkMonitor probes the status of a connection by sending ARP // messages to the default gateway for a connection. The link will be declared // as failure if no ARP reply is received for 5 consecutive broadcast ARP // requests or unicast ARP requests in the case when gateway unicast ARP // support is established. And active when an ARP reply is received. // A callback will be invoked when the link is detected as failure or active. // The active link monitor will automatically stop when the link status is // determined. It also keeps track of response times which can be an indicator // of link quality. class ActiveLinkMonitor { public: // FailureCallback takes monitor failure code, broadcast failure count, and // unicast failure count as arguments. typedef base::Callback<void(Metrics::LinkMonitorFailure, int, int)> FailureCallback; typedef base::Closure SuccessCallback; // The default number of milliseconds between ARP requests. Needed by Metrics. static const int kDefaultTestPeriodMilliseconds; // The number of milliseconds between ARP requests when running a quick test. // Used when the device just resume from suspend. Also needed by unit tests. static const int kFastTestPeriodMilliseconds; // When the sum of consecutive counted unicast and broadcast failures // equals this value, the failure callback is called, the counters // are reset, and the link monitoring quiesces. Needed by Metrics. static const int kFailureThreshold; ActiveLinkMonitor(const ConnectionRefPtr& connection, EventDispatcher* dispatcher, Metrics* metrics, DeviceInfo* device_info, const FailureCallback& failure_callback, const SuccessCallback& success_callback); virtual ~ActiveLinkMonitor(); // Starts an active link-monitoring cycle on the selected connection, with // specified |probe_period_millisecond| milliseconds between each ARP // requests. Returns true if successful, false otherwise. virtual bool Start(int probe_period_millisecond); // Stop active link-monitoring on the selected connection. Clears any // accumulated statistics. virtual void Stop(); // Return modified cumulative average of the gateway ARP response // time. Returns zero if no samples are available. For each // missed ARP response, the sample is assumed to be the full // test period. int GetResponseTimeMilliseconds() const; // Returns true if the ActiveLinkMonitor was ever able to find the default // gateway via broadcast ARP. bool IsGatewayFound() const; virtual const ByteString& gateway_mac_address() const { return gateway_mac_address_; } virtual void set_gateway_mac_address(const ByteString& gateway_mac_address) { gateway_mac_address_ = gateway_mac_address; } virtual bool gateway_supports_unicast_arp() const { return gateway_supports_unicast_arp_; } virtual void set_gateway_supports_unicast_arp( bool gateway_supports_unicast_arp) { gateway_supports_unicast_arp_ = gateway_supports_unicast_arp; } private: friend class ActiveLinkMonitorTest; // The number of samples to compute a "strict" average over. When // more samples than this number arrive, this determines how "slow" // our simple low-pass filter works. static const int kMaxResponseSampleFilterDepth; // When the sum of consecutive unicast successes equals this value, // we can assume that in general this gateway supports unicast ARP // requests, and we will count future unicast failures. static const int kUnicastReplyReliabilityThreshold; // Similar to Start, except that the initial probes use // |probe_period_milliseconds|. After successfully probing with both // broadcast and unicast ARPs (at least one of each), LinkMonitor // switches itself to kDefaultTestPeriodMilliseconds. virtual bool StartInternal(int probe_period_milliseconds); // Stop the current monitoring cycle. It is called when current monitor cycle // results in success. void StopMonitorCycle(); // Add a response time sample to the buffer. void AddResponseTimeSample(int response_time_milliseconds); // Start and stop ARP client for sending/receiving ARP requests/replies. bool StartArpClient(); void StopArpClient(); // Convert a hardware address byte-string to a colon-separated string. static std::string HardwareAddressToString(const ByteString& address); // Denote a missed response. Returns true if this loss has caused us // to exceed the failure threshold. bool AddMissedResponse(); // This I/O callback is triggered whenever the ARP reception socket // has data available to be received. void ReceiveResponse(int fd); // Send the next ARP request. void SendRequest(); // The connection on which to perform link monitoring. ConnectionRefPtr connection_; // Dispatcher on which to create delayed tasks. EventDispatcher* dispatcher_; // Metrics instance on which to post performance results. Metrics* metrics_; // DeviceInfo instance for retrieving the MAC address of a device. DeviceInfo* device_info_; // Callback methods to call when ActiveLinkMonitor completes a cycle. FailureCallback failure_callback_; SuccessCallback success_callback_; // The MAC address of device associated with this connection. ByteString local_mac_address_; // The MAC address of the default gateway. ByteString gateway_mac_address_; // ArpClient instance used for performing link tests. std::unique_ptr<ArpClient> arp_client_; // How frequently we send an ARP request. This is also the timeout // for a pending request. int test_period_milliseconds_; // The number of consecutive times we have failed in receiving // responses to broadcast ARP requests. int broadcast_failure_count_; // The number of consecutive times we have failed in receiving // responses to unicast ARP requests. int unicast_failure_count_; // The number of consecutive times we have succeeded in receiving // responses to broadcast ARP requests. int broadcast_success_count_; // The number of consecutive times we have succeeded in receiving // responses to unicast ARP requests. int unicast_success_count_; // Whether this iteration of the test was a unicast request // to the gateway instead of broadcast. The active link monitor // alternates between unicast and broadcast requests so that // both types of network traffic is monitored. bool is_unicast_; // Whether we have observed that the gateway reliably responds // to unicast ARP requests. bool gateway_supports_unicast_arp_; // Number of response samples received in our rolling averge. int response_sample_count_; // The sum of response samples in our rolling average. int response_sample_bucket_; // IOCallback that fires when the socket associated with our ArpClient // has a packet to be received. Calls ReceiveResponse(). std::unique_ptr<IOHandler> receive_response_handler_; // Callback method used for periodic transmission of ARP requests. // When the timer expires this will call SendRequest() through the // void callback function SendRequestTask(). base::CancelableClosure send_request_callback_; // The time at which the last ARP request was sent. struct timeval sent_request_at_; // Time instance for performing GetTimeMonotonic(). Time* time_; DISALLOW_COPY_AND_ASSIGN(ActiveLinkMonitor); }; } // namespace shill #endif // SHILL_ACTIVE_LINK_MONITOR_H_