1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2015 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
16d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
17d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#ifndef SHILL_ACTIVE_LINK_MONITOR_H_
18d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#define SHILL_ACTIVE_LINK_MONITOR_H_
19d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
20d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include <time.h>
21d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
22d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include <memory>
23d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include <string>
24d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
25d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include <base/callback.h>
26d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include <base/cancelable_callback.h>
27d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
28d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include "shill/metrics.h"
29d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include "shill/net/byte_string.h"
30d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#include "shill/refptr_types.h"
31d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
32d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiunamespace shill {
33d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
34d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass ArpClient;
35d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass DeviceInfo;
36d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass EventDispatcher;
37d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass IOHandler;
38d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass Time;
39d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
40d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// ActiveLinkMonitor probes the status of a connection by sending ARP
41d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// messages to the default gateway for a connection. The link will be declared
42d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// as failure if no ARP reply is received for 5 consecutive broadcast ARP
43d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// requests or unicast ARP requests in the case when gateway unicast ARP
44d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// support is established. And active when an ARP reply is received.
45d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// A callback will be invoked  when the link is detected as failure or active.
46d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// The active link monitor will automatically stop when the link status is
47d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// determined. It also keeps track of response times which can be an indicator
48d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu// of link quality.
49d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiuclass ActiveLinkMonitor {
50d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu public:
51d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // FailureCallback takes monitor failure code, broadcast failure count, and
52d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // unicast failure count as arguments.
53d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  typedef base::Callback<void(Metrics::LinkMonitorFailure, int, int)>
54d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu      FailureCallback;
55d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  typedef base::Closure SuccessCallback;
56d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
57d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The default number of milliseconds between ARP requests. Needed by Metrics.
58d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  static const int kDefaultTestPeriodMilliseconds;
59d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
60d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of milliseconds between ARP requests when running a quick test.
61d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Used when the device just resume from suspend. Also needed by unit tests.
62d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  static const int kFastTestPeriodMilliseconds;
63d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
64d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // When the sum of consecutive counted unicast and broadcast failures
65d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // equals this value, the failure callback is called, the counters
66d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // are reset, and the link monitoring quiesces.  Needed by Metrics.
67d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  static const int kFailureThreshold;
68d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
69a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  ActiveLinkMonitor(const ConnectionRefPtr& connection,
70a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                    EventDispatcher* dispatcher,
71a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                    Metrics* metrics,
72a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                    DeviceInfo* device_info,
73a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                    const FailureCallback& failure_callback,
74a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                    const SuccessCallback& success_callback);
75d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  virtual ~ActiveLinkMonitor();
76d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
77d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Starts an active link-monitoring cycle on the selected connection, with
78d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // specified |probe_period_millisecond| milliseconds between each ARP
79d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // requests. Returns true if successful, false otherwise.
80d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  virtual bool Start(int probe_period_millisecond);
81d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Stop active link-monitoring on the selected connection. Clears any
82d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // accumulated statistics.
83d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  virtual void Stop();
84d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
85d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Return modified cumulative average of the gateway ARP response
86d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // time.  Returns zero if no samples are available.  For each
87d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // missed ARP response, the sample is assumed to be the full
88d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // test period.
89d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int GetResponseTimeMilliseconds() const;
90d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
91d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Returns true if the ActiveLinkMonitor was ever able to find the default
92d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // gateway via broadcast ARP.
93d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  bool IsGatewayFound() const;
94d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
95a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual const ByteString& gateway_mac_address() const {
96d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu    return gateway_mac_address_;
97d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  }
98a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual void set_gateway_mac_address(const ByteString& gateway_mac_address) {
99ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu    gateway_mac_address_ = gateway_mac_address;
100ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu  }
101ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu
102ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu  virtual bool gateway_supports_unicast_arp() const {
103ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu    return gateway_supports_unicast_arp_;
104ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu  }
105ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu  virtual void set_gateway_supports_unicast_arp(
106ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu      bool gateway_supports_unicast_arp) {
107ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu    gateway_supports_unicast_arp_ = gateway_supports_unicast_arp;
108ffa56374b5cfca653f458d072630bb02dbc7bcd7Peter Qiu  }
109d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
110d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu private:
111d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  friend class ActiveLinkMonitorTest;
112d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
113d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of samples to compute a "strict" average over.  When
114d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // more samples than this number arrive, this determines how "slow"
115d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // our simple low-pass filter works.
116d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  static const int kMaxResponseSampleFilterDepth;
117d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
118d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // When the sum of consecutive unicast successes equals this value,
119d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // we can assume that in general this gateway supports unicast ARP
120d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // requests, and we will count future unicast failures.
121d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  static const int kUnicastReplyReliabilityThreshold;
122d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
123d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Similar to Start, except that the initial probes use
124d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // |probe_period_milliseconds|. After successfully probing with both
125d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // broadcast and unicast ARPs (at least one of each), LinkMonitor
126d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // switches itself to kDefaultTestPeriodMilliseconds.
127d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  virtual bool StartInternal(int probe_period_milliseconds);
128d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Stop the current monitoring cycle. It is called when current monitor cycle
129d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // results in success.
130d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  void StopMonitorCycle();
131d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Add a response time sample to the buffer.
132d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  void AddResponseTimeSample(int response_time_milliseconds);
133d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Start and stop ARP client for sending/receiving ARP requests/replies.
134d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  bool StartArpClient();
135d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  void StopArpClient();
136d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Convert a hardware address byte-string to a colon-separated string.
137a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  static std::string HardwareAddressToString(const ByteString& address);
138d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Denote a missed response.  Returns true if this loss has caused us
139d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // to exceed the failure threshold.
140d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  bool AddMissedResponse();
141d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // This I/O callback is triggered whenever the ARP reception socket
142d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // has data available to be received.
143d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  void ReceiveResponse(int fd);
144d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Send the next ARP request.
145d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  void SendRequest();
146d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
147d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The connection on which to perform link monitoring.
148d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  ConnectionRefPtr connection_;
149d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Dispatcher on which to create delayed tasks.
150a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  EventDispatcher* dispatcher_;
151d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Metrics instance on which to post performance results.
152a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  Metrics* metrics_;
153d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // DeviceInfo instance for retrieving the MAC address of a device.
154a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  DeviceInfo* device_info_;
155d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Callback methods to call when ActiveLinkMonitor completes a cycle.
156d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  FailureCallback failure_callback_;
157d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  SuccessCallback success_callback_;
158d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The MAC address of device associated with this connection.
159d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  ByteString local_mac_address_;
160d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The MAC address of the default gateway.
161d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  ByteString gateway_mac_address_;
162d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // ArpClient instance used for performing link tests.
163d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  std::unique_ptr<ArpClient> arp_client_;
164d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
165d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // How frequently we send an ARP request. This is also the timeout
166d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // for a pending request.
167d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int test_period_milliseconds_;
168d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of consecutive times we have failed in receiving
169d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // responses to broadcast ARP requests.
170d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int broadcast_failure_count_;
171d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of consecutive times we have failed in receiving
172d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // responses to unicast ARP requests.
173d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int unicast_failure_count_;
174d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of consecutive times we have succeeded in receiving
175d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // responses to broadcast ARP requests.
176d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int broadcast_success_count_;
177d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The number of consecutive times we have succeeded in receiving
178d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // responses to unicast ARP requests.
179d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int unicast_success_count_;
180d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
181d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Whether this iteration of the test was a unicast request
182d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // to the gateway instead of broadcast.  The active link monitor
183d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // alternates between unicast and broadcast requests so that
184d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // both types of network traffic is monitored.
185d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  bool is_unicast_;
186d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
187d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Whether we have observed that the gateway reliably responds
188d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // to unicast ARP requests.
189d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  bool gateway_supports_unicast_arp_;
190d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
191d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Number of response samples received in our rolling averge.
192d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int response_sample_count_;
193d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The sum of response samples in our rolling average.
194d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  int response_sample_bucket_;
195d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
196d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // IOCallback that fires when the socket associated with our ArpClient
197d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // has a packet to be received.  Calls ReceiveResponse().
198d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  std::unique_ptr<IOHandler> receive_response_handler_;
199d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Callback method used for periodic transmission of ARP requests.
200d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // When the timer expires this will call SendRequest() through the
201d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // void callback function SendRequestTask().
202d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  base::CancelableClosure send_request_callback_;
203d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
204d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // The time at which the last ARP request was sent.
205d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  struct timeval sent_request_at_;
206d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  // Time instance for performing GetTimeMonotonic().
207a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  Time* time_;
208d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
209d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu  DISALLOW_COPY_AND_ASSIGN(ActiveLinkMonitor);
210d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu};
211d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
212d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu}  // namespace shill
213d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu
214d7881023468fa095b40a60145a2a3e4e1d316dfdPeter Qiu#endif  // SHILL_ACTIVE_LINK_MONITOR_H_
215