blob: c15596b95007678015c9b95a23dbcc352a78282c [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_LINK_MONITOR_H_
#define SHILL_LINK_MONITOR_H_
#include <time.h>
#include <string>
#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <base/memory/scoped_ptr.h>
#include "shill/byte_string.h"
#include "shill/refptr_types.h"
namespace shill {
class ArpClient;
class DeviceInfo;
class EventDispatcher;
class IOHandler;
class Metrics;
class Time;
// LinkMonitor tracks the status of a connection by sending ARP
// messages to the default gateway for a connection. It keeps
// track of response times which can be an indicator of link
// quality. It signals to caller that the link has failed if
// too many requests go unanswered. It also signals to caller
// when the gateway's mac address is found or changed.
class LinkMonitor {
public:
typedef base::Closure FailureCallback;
typedef base::Closure GatewayChangeCallback;
// The default number of milliseconds between ARP requests. Needed by Metrics.
static const int kDefaultTestPeriodMilliseconds;
// The default list of technologies for which link monitoring is enabled.
// Needed by DefaultProfile.
static const char kDefaultLinkMonitorTechnologies[];
// 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;
LinkMonitor(const ConnectionRefPtr &connection,
EventDispatcher *dispatcher, // Owned by caller; can't be NULL.
Metrics *metrics, // Owned by caller; must not be NULL.
DeviceInfo *device_info,
const FailureCallback &failure_callback,
const GatewayChangeCallback &gateway_change_callback);
virtual ~LinkMonitor();
// Starts link-monitoring on the selected connection. Returns
// true if successful, false otherwise.
virtual bool Start();
// Stop link-monitoring on the selected connection. Clears any
// accumulated statistics.
virtual void Stop();
// Inform LinkMonitor that the system is resuming from sleep.
// LinkMonitor will immediately probe the gateway, using a lower
// timeout than normal.
virtual void OnAfterResume();
// 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.
virtual int GetResponseTimeMilliseconds() const;
// Returns true if the LinkMonitor was ever able to find the default
// gateway via broadcast ARP.
virtual bool IsGatewayFound() const;
const ByteString &gateway_mac_address() const {
return gateway_mac_address_;
}
private:
friend class LinkMonitorForTest;
friend class LinkMonitorTest;
// The number of milliseconds between ARP requests when running a quick test.
// Needed by unit tests.
static const int kFastTestPeriodMilliseconds;
// 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);
// Add a response time sample to the buffer.
void AddResponseTimeSample(int response_time_milliseconds);
// Create an ArpClient instance so we can receive and transmit ARP
// packets. This method is virtual so it can be overridden in
// unit tests.
virtual bool CreateClient();
// 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. Returns true if successful, false
// otherwise.
bool 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_;
// Failure callback method to call if LinkMonitor fails.
FailureCallback failure_callback_;
// Callback method to call if gateway mac address changes.
GatewayChangeCallback gateway_change_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.
scoped_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 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().
scoped_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 link monitor started.
struct timeval started_monitoring_at_;
// 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(LinkMonitor);
};
} // namespace shill
#endif // SHILL_LINK_MONITOR_H_