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