blob: 9851c34b2584d9bfdc7f5a9eedf9d25dd96da2aa [file] [log] [blame]
Paul Stewart3f43f432012-07-16 12:12:45 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/link_monitor.h"
6
Paul Stewart6c72c972012-07-27 11:29:20 -07007#include <base/bind.h>
Paul Stewart3f43f432012-07-16 12:12:45 -07008#include <gtest/gtest.h>
9
Paul Stewart6c72c972012-07-27 11:29:20 -070010#include "shill/arp_packet.h"
11#include "shill/ip_address.h"
12#include "shill/mock_arp_client.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070013#include "shill/mock_control.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070014#include "shill/mock_connection.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070015#include "shill/mock_device_info.h"
16#include "shill/mock_event_dispatcher.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070017#include "shill/mock_log.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070018#include "shill/mock_sockets.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070019#include "shill/mock_time.h"
20#include "shill/scope_logger.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070021
Paul Stewart6c72c972012-07-27 11:29:20 -070022using base::Bind;
23using base::Unretained;
24using testing::_;
25using testing::AnyNumber;
26using testing::HasSubstr;
27using testing::Invoke;
28using testing::Mock;
29using testing::NiceMock;
30using testing::Return;
31using testing::ReturnRef;
32using testing::SetArgumentPointee;
Paul Stewart3f43f432012-07-16 12:12:45 -070033using testing::StrictMock;
34using testing::Test;
35
36namespace shill {
37
Paul Stewart6c72c972012-07-27 11:29:20 -070038namespace {
39const int kInterfaceIndex = 123;
40const char kLocalIPAddress[] = "10.0.1.1";
41const uint8 kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
42const char kRemoteIPAddress[] = "10.0.1.2";
43const uint8 kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
44} // namespace {}
45
46
47class LinkMonitorForTest : public LinkMonitor {
48 public:
49 LinkMonitorForTest(const ConnectionRefPtr &connection,
50 EventDispatcher *dispatcher,
51 DeviceInfo *device_info)
52 : LinkMonitor(connection, dispatcher, device_info,
53 Bind(&LinkMonitorForTest::FailureCallback,
54 Unretained(this))) {}
55
56 virtual ~LinkMonitorForTest() {}
57
58 MOCK_METHOD0(CreateClient, bool());
59 MOCK_METHOD0(FailureCallback, void());
60};
61
62MATCHER_P4(IsArpRequest, local_ip, remote_ip, local_mac, remote_mac, "") {
63 return
64 local_ip.Equals(arg.local_ip_address()) &&
65 remote_ip.Equals(arg.remote_ip_address()) &&
66 local_mac.Equals(arg.local_mac_address()) &&
67 remote_mac.Equals(arg.remote_mac_address());
68}
69
Paul Stewart3f43f432012-07-16 12:12:45 -070070class LinkMonitorTest : public Test {
71 public:
72 LinkMonitorTest()
Paul Stewart6c72c972012-07-27 11:29:20 -070073 : device_info_(
74 &control_,
75 reinterpret_cast<EventDispatcher*>(NULL),
76 reinterpret_cast<Metrics*>(NULL),
77 reinterpret_cast<Manager*>(NULL)),
Paul Stewart3f43f432012-07-16 12:12:45 -070078 connection_(new StrictMock<MockConnection>(&device_info_)),
Paul Stewart6c72c972012-07-27 11:29:20 -070079 monitor_(connection_, &dispatcher_, &device_info_),
80 client_(NULL),
81 next_client_(new StrictMock<MockArpClient>()),
82 gateway_ip_(IPAddress::kFamilyIPv4),
83 local_ip_(IPAddress::kFamilyIPv4),
84 gateway_mac_(kRemoteMACAddress, arraysize(kRemoteMACAddress)),
85 local_mac_(kLocalMACAddress, arraysize(kLocalMACAddress)),
86 zero_mac_(arraysize(kLocalMACAddress)),
87 link_scope_logging_was_enabled_(false) {}
Paul Stewart3f43f432012-07-16 12:12:45 -070088 virtual ~LinkMonitorTest() {}
89
Paul Stewart6c72c972012-07-27 11:29:20 -070090 virtual void SetUp() {
91 link_scope_logging_was_enabled_ = SLOG_IS_ON(Link, 0);
92 if (!link_scope_logging_was_enabled_) {
93 ScopeLogger::GetInstance()->EnableScopesByName("link");
94 ScopeLogger::GetInstance()->set_verbose_level(4);
95 }
96 monitor_.time_ = &time_;
97 EXPECT_CALL(time_, GetTimeMonotonic(_))
98 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
99 EXPECT_TRUE(local_ip_.SetAddressFromString(kLocalIPAddress));
100 EXPECT_CALL(*connection_, local()).WillRepeatedly(ReturnRef(local_ip_));
101 EXPECT_TRUE(gateway_ip_.SetAddressFromString(kRemoteIPAddress));
102 EXPECT_CALL(*connection_, gateway()).WillRepeatedly(ReturnRef(gateway_ip_));
103 }
104
105 virtual void TearDown() {
106 if (!link_scope_logging_was_enabled_) {
107 ScopeLogger::GetInstance()->EnableScopesByName("-link");
108 ScopeLogger::GetInstance()->set_verbose_level(0);
109 }
110 }
111
112 void AdvanceTime(unsigned int time_ms) {
113 struct timeval adv_time = { time_ms/1000, (time_ms % 1000) * 1000 };
114 timeradd(&time_val_, &adv_time, &time_val_);
115 EXPECT_CALL(time_, GetTimeMonotonic(_))
116 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
117 }
118
119 bool CreateMockClient() {
120 EXPECT_FALSE(monitor_.arp_client_.get());
121 if (client_) {
122 Mock::VerifyAndClearExpectations(client_);
123 }
124 client_ = next_client_;
125 next_client_ = new StrictMock<MockArpClient>();
126 monitor_.arp_client_.reset(client_);
127 return true;
128 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700129
130 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700131 void ExpectReset() {
132 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
133 EXPECT_FALSE(GetArpClient());
134 EXPECT_TRUE(GetSendRequestCallback().IsCancelled());
135 EXPECT_EQ(0, GetBroadcastFailureCount());
136 EXPECT_EQ(0, GetUnicastFailureCount());
137 EXPECT_FALSE(IsUnicast());
138 }
139 const ArpClient *GetArpClient() { return monitor_.arp_client_.get(); }
140 void TriggerRequestTimer() {
141 GetSendRequestCallback().callback().Run();
142 }
143 const base::CancelableClosure &GetSendRequestCallback() {
144 return monitor_.send_request_callback_;
145 }
146 unsigned int GetBroadcastFailureCount() {
147 return monitor_.broadcast_failure_count_;
148 }
149 unsigned int GetUnicastFailureCount() {
150 return monitor_.unicast_failure_count_;
151 }
152 bool IsUnicast() { return monitor_.is_unicast_; }
153 unsigned int GetTestPeriodMilliseconds() {
154 return LinkMonitor::kTestPeriodMilliseconds;
155 }
156 unsigned int GetFailureThreshold() {
157 return LinkMonitor::kFailureThreshold;
158 }
159 unsigned int GetMaxResponseSampleFilterDepth() {
160 return LinkMonitor::kMaxResponseSampleFilterDepth;
161 }
162 void ExpectTransmit(bool is_unicast) {
163 const ByteString &destination_mac = is_unicast ? gateway_mac_ : zero_mac_;
164 if (monitor_.arp_client_.get()) {
165 EXPECT_EQ(client_, monitor_.arp_client_.get());
166 EXPECT_CALL(*client_, TransmitRequest(
167 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
168 .WillOnce(Return(true));
169 } else {
170 EXPECT_CALL(monitor_, CreateClient())
171 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
172 EXPECT_CALL(*next_client_, TransmitRequest(
173 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
174 .WillOnce(Return(true));
175 }
176 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
177 }
178 void SendNextRequest() {
179 EXPECT_CALL(monitor_, CreateClient())
180 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
181 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(true));
182 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
183 TriggerRequestTimer();
184 }
185 void ExpectNoTransmit() {
186 MockArpClient *client =
187 monitor_.arp_client_.get() ? client_ : next_client_;
188 EXPECT_CALL(*client, TransmitRequest(_)).Times(0);
189 }
190 void StartMonitor() {
191 EXPECT_CALL(device_info_, GetMACAddress(0, _))
192 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
193 ExpectTransmit(false);
194 EXPECT_TRUE(monitor_.Start());
195 EXPECT_TRUE(GetArpClient());
196 EXPECT_FALSE(IsUnicast());
197 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
198 }
199 bool SimulateReceiveReply(ArpPacket *packet, ByteString *sender) {
200 packet->set_local_ip_address(rx_packet_.local_ip_address());
201 packet->set_remote_ip_address(rx_packet_.remote_ip_address());
202 packet->set_local_mac_address(rx_packet_.local_mac_address());
203 packet->set_remote_mac_address(rx_packet_.remote_mac_address());
204 return true;
205 }
206 void ReceiveResponse(const IPAddress &local_ip,
207 const ByteString &local_mac,
208 const IPAddress &remote_ip,
209 const ByteString &remote_mac) {
210 rx_packet_.set_local_ip_address(local_ip);
211 rx_packet_.set_local_mac_address(local_mac);
212 rx_packet_.set_remote_ip_address(remote_ip);
213 rx_packet_.set_remote_mac_address(remote_mac);
214
215 EXPECT_CALL(*client_, ReceiveReply(_, _))
216 .WillOnce(Invoke(this, &LinkMonitorTest::SimulateReceiveReply));
217 monitor_.ReceiveResponse(0);
218 }
219 void ReceiveCorrectResponse() {
220 ReceiveResponse(local_ip_, local_mac_, gateway_ip_, gateway_mac_);
221 }
222
223 MockEventDispatcher dispatcher_;
224 MockControl control_;
225 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700226 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700227 StrictMock<LinkMonitorForTest> monitor_;
228 MockTime time_;
229 struct timeval time_val_;
230 // This is owned by the LinkMonitor, and only tracked here for EXPECT*().
231 MockArpClient *client_;
232 // This is owned by the test until it is handed to the LinkMonitorForTest
233 // and placed // in client_ above.
234 MockArpClient *next_client_;
235 IPAddress gateway_ip_;
236 IPAddress local_ip_;
237 ByteString gateway_mac_;
238 ByteString local_mac_;
239 ByteString zero_mac_;
240 ArpPacket rx_packet_;
241 bool link_scope_logging_was_enabled_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700242};
243
Paul Stewart6c72c972012-07-27 11:29:20 -0700244
Paul Stewart3f43f432012-07-16 12:12:45 -0700245TEST_F(LinkMonitorTest, Constructor) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700246 ExpectReset();
247}
248
249TEST_F(LinkMonitorTest, StartFailedGetMACAddress) {
250 ScopedMockLog log;
251 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
252 EXPECT_CALL(log,
253 Log(logging::LOG_ERROR, _,
254 HasSubstr("Could not get local MAC address"))).Times(1);
255 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false));
256 EXPECT_CALL(monitor_, CreateClient()).Times(0);
257 EXPECT_FALSE(monitor_.Start());
258 ExpectReset();
259}
260
261TEST_F(LinkMonitorTest, StartFailedCreateClient) {
262 ScopedMockLog log;
263 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
264 EXPECT_CALL(log,
265 Log(logging::LOG_ERROR, _,
266 HasSubstr("Failed to start ARP client"))).Times(1);
267 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
268 EXPECT_CALL(monitor_, CreateClient()).WillOnce(Return(false));
269 EXPECT_FALSE(monitor_.Start());
270 ExpectReset();
271}
272
273TEST_F(LinkMonitorTest, StartFailedTransmitRequest) {
274 ScopedMockLog log;
275 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
276 EXPECT_CALL(log,
277 Log(logging::LOG_ERROR, _,
278 HasSubstr("Failed to send ARP"))).Times(1);
279 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
280 EXPECT_CALL(monitor_, CreateClient())
281 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
282 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(false));
283 EXPECT_FALSE(monitor_.Start());
284 ExpectReset();
285}
286
287TEST_F(LinkMonitorTest, StartSuccess) {
288 StartMonitor();
289}
290
291TEST_F(LinkMonitorTest, Stop) {
292 StartMonitor();
293 monitor_.Stop();
294 ExpectReset();
295}
296
297TEST_F(LinkMonitorTest, ReplyReception) {
298 StartMonitor();
299 const unsigned int kResponseTime = 1234;
300 AdvanceTime(kResponseTime);
301 ScopedMockLog log;
302
303 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
304 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1);
305 ReceiveResponse(gateway_ip_, local_mac_, gateway_ip_, gateway_mac_);
306 Mock::VerifyAndClearExpectations(&log);
307
308 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
309 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1);
310 ReceiveResponse(local_ip_, gateway_mac_, gateway_ip_, gateway_mac_);
311 Mock::VerifyAndClearExpectations(&log);
312
313 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
314 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1);
315 ReceiveResponse(local_ip_, local_mac_, local_ip_, gateway_mac_);
316 Mock::VerifyAndClearExpectations(&log);
317
318 EXPECT_TRUE(GetArpClient());
319 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
320 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
321 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1);
322 ReceiveCorrectResponse();
323 EXPECT_FALSE(GetArpClient());
324 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds());
325 EXPECT_TRUE(IsUnicast());
326}
327
328TEST_F(LinkMonitorTest, TimeoutBroadcast) {
329 StartMonitor();
330 for (unsigned int i = 1; i < GetFailureThreshold(); ++i) {
331 ExpectTransmit(false);
332 TriggerRequestTimer();
333 EXPECT_FALSE(IsUnicast());
334 EXPECT_EQ(i, GetBroadcastFailureCount());
335 EXPECT_EQ(0, GetUnicastFailureCount());
336 EXPECT_EQ(GetTestPeriodMilliseconds(),
337 monitor_.GetResponseTimeMilliseconds());
338 }
339 ScopedMockLog log;
340 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
341 EXPECT_CALL(log,
342 Log(logging::LOG_ERROR, _,
343 HasSubstr("monitor has reached the failure threshold"))).Times(1);
344 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
345 ExpectNoTransmit();
346 EXPECT_CALL(monitor_, FailureCallback());
347 TriggerRequestTimer();
348 ExpectReset();
349}
350
351TEST_F(LinkMonitorTest, TimeoutUnicast) {
352 StartMonitor();
353 ReceiveCorrectResponse();
354 for (unsigned int i = 1; i < GetFailureThreshold(); ++i) {
355 // Failed unicast ARP.
356 ExpectTransmit(true);
357 TriggerRequestTimer();
358
359 // Successful broadcast ARP.
360 ExpectTransmit(false);
361 TriggerRequestTimer();
362 ReceiveCorrectResponse();
363
364 EXPECT_EQ(0, GetBroadcastFailureCount());
365 EXPECT_EQ(i, GetUnicastFailureCount());
366 }
367 // Last unicast ARP transmission.
368 ExpectTransmit(true);
369 TriggerRequestTimer();
370
371 ScopedMockLog log;
372 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
373 EXPECT_CALL(log,
374 Log(logging::LOG_ERROR, _,
375 HasSubstr("monitor has reached the failure threshold"))).Times(1);
376 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
377 ExpectNoTransmit();
378 EXPECT_CALL(monitor_, FailureCallback());
379 TriggerRequestTimer();
380 ExpectReset();
381}
382
383TEST_F(LinkMonitorTest, Average) {
384 const unsigned int kSamples[] = { 200, 950, 1200, 4096, 5000,
385 86, 120, 3060, 842, 750 };
386 const unsigned int filter_depth = GetMaxResponseSampleFilterDepth();
387 ASSERT_GT(arraysize(kSamples), filter_depth);
388 StartMonitor();
389 unsigned int i = 0;
390 unsigned int sum = 0;
391 for (; i < filter_depth; ++i) {
392 AdvanceTime(kSamples[i]);
393 ReceiveCorrectResponse();
394 sum += kSamples[i];
395 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds());
396 SendNextRequest();
397 }
398 for (; i < arraysize(kSamples); ++i) {
399 AdvanceTime(kSamples[i]);
400 ReceiveCorrectResponse();
401 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1);
402 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds());
403 SendNextRequest();
404 }
405}
406
407TEST_F(LinkMonitorTest, ImpulseResponse) {
408 const unsigned int kNormalValue = 50;
409 const unsigned int kExceptionalValue = 5000;
410 const unsigned int filter_depth = GetMaxResponseSampleFilterDepth();
411 StartMonitor();
412 for (unsigned int i = 0; i < filter_depth * 2; ++i) {
413 AdvanceTime(kNormalValue);
414 ReceiveCorrectResponse();
415 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds());
416 SendNextRequest();
417 }
418 AdvanceTime(kExceptionalValue);
419 ReceiveCorrectResponse();
420 // Our expectation is that an impulse input will be a
421 // impulse_height / (filter_depth + 1) increase to the running average.
422 unsigned int expected_impulse_response =
423 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1);
424 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds());
425 SendNextRequest();
426
427 // From here, if we end up continuing to receive normal values, our
428 // running average should decay backwards to the normal value.
429 const unsigned int failsafe = 100;
430 unsigned int last_value = monitor_.GetResponseTimeMilliseconds();
431 for (unsigned int i = 0; i < failsafe && last_value != kNormalValue; ++i) {
432 AdvanceTime(kNormalValue);
433 ReceiveCorrectResponse();
434 // We should advance monotonically (but not necessarily linearly)
435 // back towards the normal value.
436 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds());
437 SendNextRequest();
438 last_value = monitor_.GetResponseTimeMilliseconds();
439 }
440 EXPECT_EQ(kNormalValue, last_value);
Paul Stewart3f43f432012-07-16 12:12:45 -0700441}
442
443} // namespace shill