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 #include <linux/nl80211.h> 23 24 #include <gtest/gtest.h> 25 26 #include "wificond/scanning/scan_result.h" 27 #include "wificond/scanning/scan_utils.h" 28 #include "wificond/tests/mock_netlink_manager.h" 29 30 using std::bind; 31 using std::placeholders::_1; 32 using std::placeholders::_2; 33 using std::unique_ptr; 34 using std::vector; 35 using testing::AllOf; 36 using testing::Invoke; 37 using testing::NiceMock; 38 using testing::Not; 39 using testing::Return; 40 using testing::_; 41 42 using com::android::server::wifi::wificond::NativeScanResult; 43 44 namespace android { 45 namespace wificond { 46 47 namespace { 48 49 constexpr uint32_t kFakeInterfaceIndex = 12; 50 constexpr uint32_t kFakeScheduledScanIntervalMs = 20000; 51 constexpr uint32_t kFakeSequenceNumber = 1984; 52 constexpr int kFakeErrorCode = EIO; 53 constexpr int32_t kFakeRssiThreshold = -80; 54 constexpr bool kFakeUseRandomMAC = true; 55 56 // Currently, control messages are only created by the kernel and sent to us. 57 // Therefore NL80211Packet doesn't have corresponding constructor. 58 // For test we manually create control messages using this helper function. 59 NL80211Packet CreateControlMessageError(int error_code) { 60 vector<uint8_t> data; 61 data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0); 62 // Initialize length field. 63 nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data()); 64 nl_header->nlmsg_len = data.size(); 65 nl_header->nlmsg_type = NLMSG_ERROR; 66 nl_header->nlmsg_seq = kFakeSequenceNumber; 67 nl_header->nlmsg_pid = getpid(); 68 int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN); 69 *error_field = -error_code; 70 71 return NL80211Packet(data); 72 } 73 74 NL80211Packet CreateControlMessageAck() { 75 return CreateControlMessageError(0); 76 } 77 78 // This is a helper function to mock the behavior of NetlinkManager:: 79 // SendMessageAndGetResponses() when we expect a single packet response. 80 // |request_message| and |response| are mapped to existing parameters of 81 // SendMessageAndGetResponses(). 82 // |mock_response| and |mock_return value| are additional parameters used 83 // for specifying expected results, 84 bool AppendMessageAndReturn( 85 NL80211Packet& mock_response, 86 bool mock_return_value, 87 const NL80211Packet& request_message, 88 vector<std::unique_ptr<const NL80211Packet>>* response) { 89 response->push_back(std::make_unique<NL80211Packet>(mock_response)); 90 return mock_return_value; 91 } 92 93 } // namespace 94 95 class ScanUtilsTest : public ::testing::Test { 96 protected: 97 virtual void SetUp() { 98 ON_CALL(netlink_manager_, 99 SendMessageAndGetResponses(_, _)).WillByDefault(Return(true)); 100 } 101 102 NiceMock<MockNetlinkManager> netlink_manager_; 103 ScanUtils scan_utils_{&netlink_manager_}; 104 }; 105 106 MATCHER_P(DoesNL80211PacketMatchCommand, command, 107 "Check if the netlink packet matches |command|") { 108 return arg.GetCommand() == command; 109 } 110 111 MATCHER_P(DoesNL80211PacketHaveAttribute, attr, 112 "Check if the netlink packet has atttribute |attr|") { 113 return arg.HasAttribute(attr); 114 } 115 116 TEST_F(ScanUtilsTest, CanGetScanResult) { 117 vector<NativeScanResult> scan_results; 118 EXPECT_CALL( 119 netlink_manager_, 120 SendMessageAndGetResponses( 121 DoesNL80211PacketMatchCommand(NL80211_CMD_GET_SCAN), _)); 122 123 // We don't use EXPECT_TRUE here because we need to mock a complete 124 // response for NL80211_CMD_GET_SCAN to satisfy the parsing code called 125 // by GetScanResult. 126 // TODO(b/34231002): Mock response for NL80211_CMD_GET_SCAN. 127 // TODO(b/34231420): Add validation of interface index. 128 scan_utils_.GetScanResult(kFakeInterfaceIndex, &scan_results); 129 } 130 131 TEST_F(ScanUtilsTest, CanSendScanRequest) { 132 NL80211Packet response = CreateControlMessageAck(); 133 EXPECT_CALL( 134 netlink_manager_, 135 SendMessageAndGetResponses( 136 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)). 137 WillOnce(Invoke(bind( 138 AppendMessageAndReturn, response, true, _1, _2))); 139 140 int errno_ignored; 141 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}, 142 &errno_ignored)); 143 // TODO(b/34231420): Add validation of requested scan ssids, threshold, 144 // and frequencies. 145 } 146 147 TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) { 148 NL80211Packet response = CreateControlMessageError(kFakeErrorCode); 149 EXPECT_CALL( 150 netlink_manager_, 151 SendMessageAndGetResponses( 152 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)). 153 WillOnce(Invoke(bind( 154 AppendMessageAndReturn, response, true, _1, _2))); 155 int error_code; 156 EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}, 157 &error_code)); 158 EXPECT_EQ(kFakeErrorCode, error_code); 159 } 160 161 TEST_F(ScanUtilsTest, CanSendSchedScanRequest) { 162 NL80211Packet response = CreateControlMessageAck(); 163 EXPECT_CALL( 164 netlink_manager_, 165 SendMessageAndGetResponses( 166 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)). 167 WillOnce(Invoke(bind( 168 AppendMessageAndReturn, response, true, _1, _2))); 169 int errno_ignored; 170 EXPECT_TRUE(scan_utils_.StartScheduledScan( 171 kFakeInterfaceIndex, 172 SchedScanIntervalSetting(), 173 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored)); 174 // TODO(b/34231420): Add validation of requested scan ssids, threshold, 175 // and frequencies. 176 } 177 178 TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) { 179 NL80211Packet response = CreateControlMessageError(kFakeErrorCode); 180 EXPECT_CALL( 181 netlink_manager_, 182 SendMessageAndGetResponses( 183 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)). 184 WillOnce(Invoke(bind( 185 AppendMessageAndReturn, response, true, _1, _2))); 186 int error_code; 187 EXPECT_FALSE(scan_utils_.StartScheduledScan( 188 kFakeInterfaceIndex, 189 SchedScanIntervalSetting(), 190 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &error_code)); 191 EXPECT_EQ(kFakeErrorCode, error_code); 192 } 193 194 TEST_F(ScanUtilsTest, CanSpecifyScanPlansForSchedScanRequest) { 195 EXPECT_CALL( 196 netlink_manager_, 197 SendMessageAndGetResponses( 198 AllOf( 199 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), 200 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_PLANS), 201 Not(DoesNL80211PacketHaveAttribute( 202 NL80211_ATTR_SCHED_SCAN_INTERVAL))), 203 _)); 204 int errno_ignored; 205 SchedScanIntervalSetting interval_setting{ 206 {{kFakeScheduledScanIntervalMs, 10 /* repeated times */}}, 207 kFakeScheduledScanIntervalMs * 3 /* interval for infinite scans */}; 208 209 scan_utils_.StartScheduledScan( 210 kFakeInterfaceIndex, 211 interval_setting, 212 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored); 213 } 214 215 TEST_F(ScanUtilsTest, CanSpecifySingleIntervalForSchedScanRequest) { 216 EXPECT_CALL( 217 netlink_manager_, 218 SendMessageAndGetResponses( 219 AllOf( 220 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), 221 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_INTERVAL), 222 Not(DoesNL80211PacketHaveAttribute( 223 NL80211_ATTR_SCHED_SCAN_PLANS))), 224 _)); 225 int errno_ignored; 226 SchedScanIntervalSetting interval_setting{{}, kFakeScheduledScanIntervalMs}; 227 228 scan_utils_.StartScheduledScan( 229 kFakeInterfaceIndex, 230 interval_setting, 231 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored); 232 } 233 234 TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) { 235 constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456; 236 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 237 NL80211NestedAttr bss(NL80211_ATTR_BSS); 238 bss.AddAttribute( 239 NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME, 240 kLastSeenTimestampNanoSeconds)); 241 bss.AddAttribute( 242 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 243 uint64_t timestamp_microseconds; 244 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 245 bss, ×tamp_microseconds)); 246 EXPECT_EQ(kLastSeenTimestampNanoSeconds/1000, timestamp_microseconds); 247 } 248 249 TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) { 250 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 251 NL80211NestedAttr bss(NL80211_ATTR_BSS); 252 bss.AddAttribute( 253 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 254 uint64_t timestamp_microseconds; 255 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 256 bss, ×tamp_microseconds)); 257 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds); 258 } 259 260 // Probe TSF is newer. 261 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1) { 262 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 654321; 263 constexpr uint64_t kBssTsfTimestampMicroSeconds = 264 kBssBeaconTsfTimestampMicroSeconds + 2000; 265 NL80211NestedAttr bss(NL80211_ATTR_BSS); 266 bss.AddAttribute( 267 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF, 268 kBssBeaconTsfTimestampMicroSeconds)); 269 bss.AddAttribute( 270 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 271 uint64_t timestamp_microseconds; 272 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 273 bss, ×tamp_microseconds)); 274 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds); 275 } 276 277 // Beacon TSF is newer. 278 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2) { 279 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 280 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 281 kBssTsfTimestampMicroSeconds + 2000; 282 NL80211NestedAttr bss(NL80211_ATTR_BSS); 283 bss.AddAttribute( 284 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF, 285 kBssBeaconTsfTimestampMicroSeconds)); 286 bss.AddAttribute( 287 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 288 uint64_t timestamp_microseconds; 289 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 290 bss, ×tamp_microseconds)); 291 EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds); 292 } 293 294 } // namespace wificond 295 } // namespace android 296