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