Peter Qiu | c0beca5 | 2015-09-03 11:25:46 -0700 | [diff] [blame] | 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 | // |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 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 | |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 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); |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 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 | |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 95 | virtual const ByteString& gateway_mac_address() const { |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 96 | return gateway_mac_address_; |
| 97 | } |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 98 | virtual void set_gateway_mac_address(const ByteString& gateway_mac_address) { |
Peter Qiu | ffa5637 | 2015-01-22 14:25:23 -0800 | [diff] [blame] | 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 | } |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 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. |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 137 | static std::string HardwareAddressToString(const ByteString& address); |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 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. |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 150 | EventDispatcher* dispatcher_; |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 151 | // Metrics instance on which to post performance results. |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 152 | Metrics* metrics_; |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 153 | // DeviceInfo instance for retrieving the MAC address of a device. |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 154 | DeviceInfo* device_info_; |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 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(). |
Paul Stewart | a794cd6 | 2015-06-16 13:13:10 -0700 | [diff] [blame] | 207 | Time* time_; |
Peter Qiu | d788102 | 2015-01-21 12:27:41 -0800 | [diff] [blame] | 208 | |
| 209 | DISALLOW_COPY_AND_ASSIGN(ActiveLinkMonitor); |
| 210 | }; |
| 211 | |
| 212 | } // namespace shill |
| 213 | |
| 214 | #endif // SHILL_ACTIVE_LINK_MONITOR_H_ |