1 /*
2 * Copyright (C) 2016, 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 <functional>
18 #include <memory>
19 #include <vector>
20
21 #include <linux/netlink.h>
22
23 #include <gtest/gtest.h>
24
25 #include "android/net/wifi/nl80211/IWifiScannerImpl.h"
26 #include "wificond/net/kernel-header-latest/nl80211.h"
27 #include "wificond/scanning/scan_result.h"
28 #include "wificond/scanning/scan_utils.h"
29 #include "wificond/tests/mock_netlink_manager.h"
30
31 using std::bind;
32 using std::placeholders::_1;
33 using std::placeholders::_2;
34 using std::unique_ptr;
35 using std::vector;
36 using testing::AllOf;
37 using testing::Invoke;
38 using testing::NiceMock;
39 using testing::Not;
40 using testing::Return;
41 using testing::_;
42
43 using android::net::wifi::nl80211::IWifiScannerImpl;
44 using android::net::wifi::nl80211::NativeScanResult;
45
46 namespace android {
47 namespace wificond {
48
49 namespace {
50
51 constexpr uint32_t kFakeInterfaceIndex = 12;
52 constexpr uint32_t kFakeScheduledScanIntervalMs = 20000;
53 constexpr uint32_t kFakeSequenceNumber = 1984;
54 constexpr int kFakeErrorCode = EIO;
55 constexpr int32_t kFake2gRssiThreshold = -80;
56 constexpr int32_t kFake5gRssiThreshold = -77;
57 constexpr int32_t kFake6gRssiThreshold = -77;
58 constexpr bool kFakeUseRandomMAC = true;
59 constexpr bool kFakeRequestLowPower = true;
60 constexpr bool kFakeRequestSchedScanRelativeRssi = true;
61 constexpr int kFakeScanType = IWifiScannerImpl::SCAN_TYPE_LOW_SPAN;
62
63 // Currently, control messages are only created by the kernel and sent to us.
64 // Therefore NL80211Packet doesn't have corresponding constructor.
65 // For test we manually create control messages using this helper function.
CreateControlMessageError(int error_code)66 NL80211Packet CreateControlMessageError(int error_code) {
67 vector<uint8_t> data;
68 data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0);
69 // Initialize length field.
70 nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data());
71 nl_header->nlmsg_len = data.size();
72 nl_header->nlmsg_type = NLMSG_ERROR;
73 nl_header->nlmsg_seq = kFakeSequenceNumber;
74 nl_header->nlmsg_pid = getpid();
75 int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN);
76 *error_field = -error_code;
77
78 return NL80211Packet(data);
79 }
80
CreateControlMessageAck()81 NL80211Packet CreateControlMessageAck() {
82 return CreateControlMessageError(0);
83 }
84
85 // This is a helper function to mock the behavior of NetlinkManager::
86 // SendMessageAndGetResponses() when we expect a single packet response.
87 // |request_message| and |response| are mapped to existing parameters of
88 // SendMessageAndGetResponses().
89 // |mock_response| and |mock_return value| are additional parameters used
90 // for specifying expected results,
AppendMessageAndReturn(NL80211Packet & mock_response,bool mock_return_value,const NL80211Packet & request_message,vector<std::unique_ptr<const NL80211Packet>> * response)91 bool AppendMessageAndReturn(
92 NL80211Packet& mock_response,
93 bool mock_return_value,
94 const NL80211Packet& request_message,
95 vector<std::unique_ptr<const NL80211Packet>>* response) {
96 response->push_back(std::make_unique<NL80211Packet>(mock_response));
97 return mock_return_value;
98 }
99
100 } // namespace
101
102 class ScanUtilsTest : public ::testing::Test {
103 protected:
SetUp()104 virtual void SetUp() {
105 ON_CALL(netlink_manager_,
106 SendMessageAndGetResponses(_, _)).WillByDefault(Return(true));
107 }
108
109 NiceMock<MockNetlinkManager> netlink_manager_;
110 ScanUtils scan_utils_{&netlink_manager_};
111 };
112
113 MATCHER_P(DoesNL80211PacketMatchCommand, command,
114 "Check if the netlink packet matches |command|") {
115 return arg.GetCommand() == command;
116 }
117
118 MATCHER_P(DoesNL80211PacketHaveAttribute, attr,
119 "Check if the netlink packet has atttribute |attr|") {
120 return arg.HasAttribute(attr);
121 }
122
123 MATCHER_P2(DoesNL80211PacketHaveAttributeWithUint32Value, attr, expected_value,
124 "Check if the netlink packet has atttribute |attr| with "
125 "|expected_value|") {
126 uint32_t actual_value;
127 if (!arg.GetAttributeValue(attr, &actual_value)) {
128 return false;
129 }
130 return actual_value == expected_value;
131 }
132
TEST_F(ScanUtilsTest,CanGetScanResult)133 TEST_F(ScanUtilsTest, CanGetScanResult) {
134 vector<NativeScanResult> scan_results;
135 EXPECT_CALL(
136 netlink_manager_,
137 SendMessageAndGetResponses(
138 DoesNL80211PacketMatchCommand(NL80211_CMD_GET_SCAN), _));
139
140 // We don't use EXPECT_TRUE here because we need to mock a complete
141 // response for NL80211_CMD_GET_SCAN to satisfy the parsing code called
142 // by GetScanResult.
143 // TODO(b/34231002): Mock response for NL80211_CMD_GET_SCAN.
144 // TODO(b/34231420): Add validation of interface index.
145 scan_utils_.GetScanResult(kFakeInterfaceIndex, &scan_results);
146 }
147
TEST_F(ScanUtilsTest,CanSendScanRequest)148 TEST_F(ScanUtilsTest, CanSendScanRequest) {
149 NL80211Packet response = CreateControlMessageAck();
150 EXPECT_CALL(
151 netlink_manager_,
152 SendMessageAndGetResponses(
153 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
154 WillOnce(Invoke(bind(
155 AppendMessageAndReturn, response, true, _1, _2)));
156 int errno_ignored;
157 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC,
158 kFakeScanType, false, {}, {}, {}, &errno_ignored));
159 // TODO(b/34231420): Add validation of requested scan ssids, threshold,
160 // and frequencies.
161 }
162
TEST_F(ScanUtilsTest,CanSendScanRequestWithRandomAddr)163 TEST_F(ScanUtilsTest, CanSendScanRequestWithRandomAddr) {
164 NL80211Packet response = CreateControlMessageAck();
165 EXPECT_CALL(
166 netlink_manager_,
167 SendMessageAndGetResponses(
168 AllOf(
169 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
170 DoesNL80211PacketHaveAttributeWithUint32Value(
171 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_RANDOM_ADDR)),
172 _)).
173 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
174
175 int errno_ignored;
176 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, true,
177 IWifiScannerImpl::SCAN_TYPE_DEFAULT,
178 false, {}, {}, {}, &errno_ignored));
179 }
180
TEST_F(ScanUtilsTest,CanSendScanRequestForLowSpanScan)181 TEST_F(ScanUtilsTest, CanSendScanRequestForLowSpanScan) {
182 NL80211Packet response = CreateControlMessageAck();
183 EXPECT_CALL(
184 netlink_manager_,
185 SendMessageAndGetResponses(
186 AllOf(
187 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
188 DoesNL80211PacketHaveAttributeWithUint32Value(
189 NL80211_ATTR_SCAN_FLAGS,
190 static_cast<uint32_t>(NL80211_SCAN_FLAG_LOW_SPAN |
191 NL80211_SCAN_FLAG_COLOCATED_6GHZ))),
192 _)).
193 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
194
195 int errno_ignored;
196 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
197 IWifiScannerImpl::SCAN_TYPE_LOW_SPAN,
198 true, {}, {}, {}, &errno_ignored));
199 }
200
TEST_F(ScanUtilsTest,CanSendScanRequestForLowPowerScan)201 TEST_F(ScanUtilsTest, CanSendScanRequestForLowPowerScan) {
202 NL80211Packet response = CreateControlMessageAck();
203 EXPECT_CALL(
204 netlink_manager_,
205 SendMessageAndGetResponses(
206 AllOf(
207 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
208 DoesNL80211PacketHaveAttributeWithUint32Value(
209 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_LOW_POWER)),
210 _)).
211 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
212
213 int errno_ignored;
214 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
215 IWifiScannerImpl::SCAN_TYPE_LOW_POWER,
216 false, {}, {}, {}, &errno_ignored));
217 }
218
TEST_F(ScanUtilsTest,CanSendScanRequestForHighAccuracyScan)219 TEST_F(ScanUtilsTest, CanSendScanRequestForHighAccuracyScan) {
220 NL80211Packet response = CreateControlMessageAck();
221 EXPECT_CALL(
222 netlink_manager_,
223 SendMessageAndGetResponses(
224 AllOf(
225 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
226 DoesNL80211PacketHaveAttributeWithUint32Value(
227 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_HIGH_ACCURACY)),
228 _)).
229 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
230
231 int errno_ignored;
232 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
233 IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY,
234 false, {}, {}, {}, &errno_ignored));
235 }
236
TEST_F(ScanUtilsTest,CanSendScanRequestForHighAccuracyScanWithRandomAddr)237 TEST_F(ScanUtilsTest, CanSendScanRequestForHighAccuracyScanWithRandomAddr) {
238 NL80211Packet response = CreateControlMessageAck();
239 EXPECT_CALL(
240 netlink_manager_,
241 SendMessageAndGetResponses(
242 AllOf(
243 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
244 DoesNL80211PacketHaveAttributeWithUint32Value(
245 NL80211_ATTR_SCAN_FLAGS,
246 static_cast<uint32_t>(NL80211_SCAN_FLAG_RANDOM_ADDR |
247 NL80211_SCAN_FLAG_HIGH_ACCURACY))),
248 _)).
249 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
250
251 int errno_ignored;
252 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, true,
253 IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY,
254 false, {}, {}, {}, &errno_ignored));
255 }
256
TEST_F(ScanUtilsTest,CanHandleScanRequestFailure)257 TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) {
258 NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
259 EXPECT_CALL(
260 netlink_manager_,
261 SendMessageAndGetResponses(
262 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
263 WillOnce(Invoke(bind(
264 AppendMessageAndReturn, response, true, _1, _2)));
265 int error_code;
266 EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC,
267 kFakeScanType, false, {}, {}, {}, &error_code));
268 EXPECT_EQ(kFakeErrorCode, error_code);
269 }
270
TEST_F(ScanUtilsTest,CanSendSchedScanRequest)271 TEST_F(ScanUtilsTest, CanSendSchedScanRequest) {
272 NL80211Packet response = CreateControlMessageAck();
273 EXPECT_CALL(
274 netlink_manager_,
275 SendMessageAndGetResponses(
276 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
277 WillOnce(Invoke(bind(
278 AppendMessageAndReturn, response, true, _1, _2)));
279
280 const SchedScanReqFlags req_flags = {
281 kFakeUseRandomMAC, kFakeRequestLowPower, kFakeRequestSchedScanRelativeRssi
282 };
283 int errno_ignored;
284 EXPECT_TRUE(scan_utils_.StartScheduledScan(
285 kFakeInterfaceIndex,
286 SchedScanIntervalSetting(),
287 kFake2gRssiThreshold, kFake5gRssiThreshold, kFake6gRssiThreshold, req_flags, {}, {}, {},
288 &errno_ignored));
289 // TODO(b/34231420): Add validation of requested scan ssids, threshold,
290 // and frequencies.
291 }
292
TEST_F(ScanUtilsTest,CanHandleSchedScanRequestFailure)293 TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) {
294 NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
295 EXPECT_CALL(
296 netlink_manager_,
297 SendMessageAndGetResponses(
298 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
299 WillOnce(Invoke(bind(
300 AppendMessageAndReturn, response, true, _1, _2)));
301 const SchedScanReqFlags req_flags = {
302 kFakeUseRandomMAC, kFakeRequestLowPower, kFakeRequestSchedScanRelativeRssi
303 };
304 int error_code;
305 EXPECT_FALSE(scan_utils_.StartScheduledScan(
306 kFakeInterfaceIndex,
307 SchedScanIntervalSetting(),
308 kFake2gRssiThreshold, kFake5gRssiThreshold, kFake6gRssiThreshold,
309 req_flags, {}, {}, {}, &error_code));
310 EXPECT_EQ(kFakeErrorCode, error_code);
311 }
312
TEST_F(ScanUtilsTest,CanSendSchedScanRequestForLowPowerScan)313 TEST_F(ScanUtilsTest, CanSendSchedScanRequestForLowPowerScan) {
314 NL80211Packet response = CreateControlMessageAck();
315 EXPECT_CALL(
316 netlink_manager_,
317 SendMessageAndGetResponses(
318 AllOf(
319 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
320 DoesNL80211PacketHaveAttributeWithUint32Value(
321 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_LOW_POWER)),
322 _));
323 int errno_ignored;
324 const SchedScanReqFlags req_flags = {
325 false, true, false
326 };
327 scan_utils_.StartScheduledScan(
328 kFakeInterfaceIndex,
329 SchedScanIntervalSetting(),
330 kFake2gRssiThreshold, kFake5gRssiThreshold, kFake6gRssiThreshold,
331 req_flags, {}, {}, {}, &errno_ignored);
332 }
333
TEST_F(ScanUtilsTest,CanSpecifyScanPlansForSchedScanRequest)334 TEST_F(ScanUtilsTest, CanSpecifyScanPlansForSchedScanRequest) {
335 EXPECT_CALL(
336 netlink_manager_,
337 SendMessageAndGetResponses(
338 AllOf(
339 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
340 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_PLANS),
341 Not(DoesNL80211PacketHaveAttribute(
342 NL80211_ATTR_SCHED_SCAN_INTERVAL))),
343 _));
344 int errno_ignored;
345 SchedScanIntervalSetting interval_setting{
346 {{kFakeScheduledScanIntervalMs, 10 /* repeated times */}},
347 kFakeScheduledScanIntervalMs * 3 /* interval for infinite scans */};
348 const SchedScanReqFlags req_flags = {
349 kFakeUseRandomMAC, kFakeRequestLowPower, kFakeRequestSchedScanRelativeRssi
350 };
351 scan_utils_.StartScheduledScan(
352 kFakeInterfaceIndex,
353 interval_setting,
354 kFake2gRssiThreshold, kFake5gRssiThreshold, kFake6gRssiThreshold,
355 req_flags, {}, {}, {}, &errno_ignored);
356 }
357
TEST_F(ScanUtilsTest,CanSpecifySingleIntervalForSchedScanRequest)358 TEST_F(ScanUtilsTest, CanSpecifySingleIntervalForSchedScanRequest) {
359 EXPECT_CALL(
360 netlink_manager_,
361 SendMessageAndGetResponses(
362 AllOf(
363 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
364 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_INTERVAL),
365 Not(DoesNL80211PacketHaveAttribute(
366 NL80211_ATTR_SCHED_SCAN_PLANS))),
367 _));
368 int errno_ignored;
369 SchedScanIntervalSetting interval_setting{{}, kFakeScheduledScanIntervalMs};
370 const SchedScanReqFlags req_flags = {
371 kFakeUseRandomMAC, kFakeRequestLowPower, kFakeRequestSchedScanRelativeRssi
372 };
373 scan_utils_.StartScheduledScan(
374 kFakeInterfaceIndex,
375 interval_setting,
376 kFake2gRssiThreshold, kFake5gRssiThreshold, kFake6gRssiThreshold,
377 req_flags, {}, {}, {}, &errno_ignored);
378 }
379
TEST_F(ScanUtilsTest,CanPrioritizeLastSeenSinceBootNetlinkAttribute)380 TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) {
381 constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456;
382 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
383 NL80211NestedAttr bss(NL80211_ATTR_BSS);
384 bss.AddAttribute(
385 NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME,
386 kLastSeenTimestampNanoSeconds));
387 bss.AddAttribute(
388 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
389 uint64_t timestamp_microseconds;
390 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
391 bss, ×tamp_microseconds));
392 EXPECT_EQ(kLastSeenTimestampNanoSeconds/1000, timestamp_microseconds);
393 }
394
TEST_F(ScanUtilsTest,CanHandleMissingLastSeenSinceBootNetlinkAttribute)395 TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) {
396 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
397 NL80211NestedAttr bss(NL80211_ATTR_BSS);
398 bss.AddAttribute(
399 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
400 uint64_t timestamp_microseconds;
401 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
402 bss, ×tamp_microseconds));
403 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
404 }
405
406 // Probe TSF is newer.
TEST_F(ScanUtilsTest,CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1)407 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1) {
408 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 654321;
409 constexpr uint64_t kBssTsfTimestampMicroSeconds =
410 kBssBeaconTsfTimestampMicroSeconds + 2000;
411 NL80211NestedAttr bss(NL80211_ATTR_BSS);
412 bss.AddAttribute(
413 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
414 kBssBeaconTsfTimestampMicroSeconds));
415 bss.AddAttribute(
416 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
417 uint64_t timestamp_microseconds;
418 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
419 bss, ×tamp_microseconds));
420 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
421 }
422
423 // Beacon TSF is newer.
TEST_F(ScanUtilsTest,CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2)424 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2) {
425 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
426 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds =
427 kBssTsfTimestampMicroSeconds + 2000;
428 NL80211NestedAttr bss(NL80211_ATTR_BSS);
429 bss.AddAttribute(
430 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
431 kBssBeaconTsfTimestampMicroSeconds));
432 bss.AddAttribute(
433 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
434 uint64_t timestamp_microseconds;
435 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
436 bss, ×tamp_microseconds));
437 EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds);
438 }
439
440 } // namespace wificond
441 } // namespace android
442