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 
32 namespace shill {
33 
34 class ArpClient;
35 class DeviceInfo;
36 class EventDispatcher;
37 class IOHandler;
38 class 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.
49 class 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 
gateway_mac_address()95   virtual const ByteString& gateway_mac_address() const {
96     return gateway_mac_address_;
97   }
set_gateway_mac_address(const ByteString & gateway_mac_address)98   virtual void set_gateway_mac_address(const ByteString& gateway_mac_address) {
99     gateway_mac_address_ = gateway_mac_address;
100   }
101 
gateway_supports_unicast_arp()102   virtual bool gateway_supports_unicast_arp() const {
103     return gateway_supports_unicast_arp_;
104   }
set_gateway_supports_unicast_arp(bool gateway_supports_unicast_arp)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