1//
2// Copyright (C) 2012 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#include "shill/link_monitor.h"
18
19#include <string>
20
21#include <base/bind.h>
22
23#include "shill/active_link_monitor.h"
24#include "shill/connection.h"
25#include "shill/device_info.h"
26#include "shill/event_dispatcher.h"
27#include "shill/logging.h"
28#include "shill/net/shill_time.h"
29#include "shill/passive_link_monitor.h"
30
31using base::Bind;
32using base::Unretained;
33using std::string;
34
35namespace shill {
36
37namespace Logging {
38static auto kModuleLogScope = ScopeLogger::kLink;
39static string ObjectID(Connection* c) { return c->interface_name(); }
40}
41
42const int LinkMonitor::kDefaultTestPeriodMilliseconds =
43    ActiveLinkMonitor::kDefaultTestPeriodMilliseconds;
44const int LinkMonitor::kFailureThreshold =
45    ActiveLinkMonitor::kFailureThreshold;
46const char LinkMonitor::kDefaultLinkMonitorTechnologies[] = "wifi";
47
48LinkMonitor::LinkMonitor(const ConnectionRefPtr& connection,
49                         EventDispatcher* dispatcher,
50                         Metrics* metrics,
51                         DeviceInfo* device_info,
52                         const FailureCallback& failure_callback,
53                         const GatewayChangeCallback& gateway_change_callback)
54    : connection_(connection),
55      dispatcher_(dispatcher),
56      metrics_(metrics),
57      failure_callback_(failure_callback),
58      gateway_change_callback_(gateway_change_callback),
59      active_link_monitor_(
60          new ActiveLinkMonitor(
61              connection,
62              dispatcher,
63              metrics,
64              device_info,
65              Bind(&LinkMonitor::OnActiveLinkMonitorFailure,
66                   Unretained(this)),
67              Bind(&LinkMonitor::OnActiveLinkMonitorSuccess,
68                   Unretained(this)))),
69      passive_link_monitor_(
70          new PassiveLinkMonitor(
71              connection,
72              dispatcher,
73              Bind(&LinkMonitor::OnPassiveLinkMonitorResultCallback,
74                   Unretained(this)))),
75      time_(Time::GetInstance()) {
76}
77
78LinkMonitor::~LinkMonitor() {
79  Stop();
80}
81
82bool LinkMonitor::Start() {
83  Stop();
84  time_->GetTimeMonotonic(&started_monitoring_at_);
85  // Start active link monitor.
86  return active_link_monitor_->Start(
87      ActiveLinkMonitor::kDefaultTestPeriodMilliseconds);
88}
89
90void LinkMonitor::Stop() {
91  SLOG(connection_.get(), 2) << "In " << __func__ << ".";
92  timerclear(&started_monitoring_at_);
93  active_link_monitor_->Stop();
94  passive_link_monitor_->Stop();
95  gateway_mac_address_.Clear();
96}
97
98void LinkMonitor::OnAfterResume() {
99  // Preserve gateway settings across resume.
100  ByteString prior_gateway_mac_address(gateway_mac_address_);
101  bool gateway_supports_unicast_arp =
102      active_link_monitor_->gateway_supports_unicast_arp();
103  Stop();
104  gateway_mac_address_ = prior_gateway_mac_address;
105  active_link_monitor_->set_gateway_mac_address(gateway_mac_address_);
106  active_link_monitor_->set_gateway_supports_unicast_arp(
107      gateway_supports_unicast_arp);
108
109  active_link_monitor_->Start(ActiveLinkMonitor::kFastTestPeriodMilliseconds);
110}
111
112int LinkMonitor::GetResponseTimeMilliseconds() const {
113  return active_link_monitor_->GetResponseTimeMilliseconds();
114}
115
116bool LinkMonitor::IsGatewayFound() const {
117  return !gateway_mac_address_.IsZero();
118}
119
120void LinkMonitor::OnActiveLinkMonitorFailure(
121    Metrics::LinkMonitorFailure failure,
122    int broadcast_failure_count,
123    int unicast_failure_count) {
124  failure_callback_.Run();
125
126  struct timeval now, elapsed_time;
127  time_->GetTimeMonotonic(&now);
128  timersub(&now, &started_monitoring_at_, &elapsed_time);
129
130  metrics_->NotifyLinkMonitorFailure(
131      connection_->technology(),
132      failure,
133      elapsed_time.tv_sec,
134      broadcast_failure_count,
135      unicast_failure_count);
136
137  Stop();
138}
139
140void LinkMonitor::OnActiveLinkMonitorSuccess() {
141  if (!gateway_mac_address_.Equals(
142      active_link_monitor_->gateway_mac_address())) {
143    gateway_mac_address_ = active_link_monitor_->gateway_mac_address();
144    // Notify device of the new gateway mac address.
145    gateway_change_callback_.Run();
146  }
147
148  // Start passive link monitoring.
149  passive_link_monitor_->Start(PassiveLinkMonitor::kDefaultMonitorCycles);
150}
151
152void LinkMonitor::OnPassiveLinkMonitorResultCallback(bool status) {
153  // TODO(zqiu): Add metrics for tracking passive link monitor results.
154
155  // Start active monitor
156  active_link_monitor_->Start(
157      ActiveLinkMonitor::kDefaultTestPeriodMilliseconds);
158}
159
160}  // namespace shill
161