1 /*
2 * Copyright (C) 2017 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 "interface.h"
18
19 #include "log.h"
20 #include "netlink.h"
21 #include "netlinkmessage.h"
22
23 #include <linux/rtnetlink.h>
24
25 #include <algorithm>
26 #include <future>
27
28 static const int kApfRamSize = 4096;
29
30 // Provide some arbitrary firmware and driver versions for now
31 static const char kFirmwareVersion[] = "1.0";
32 static const char kDriverVersion[] = "1.0";
33
34 // A list of supported channels in the 2.4 GHz band, values in MHz
35 static const wifi_channel k2p4Channels[] = {
36 2412,
37 2417,
38 2422,
39 2427,
40 2432,
41 2437,
42 2442,
43 2447,
44 2452,
45 2457,
46 2462,
47 2467,
48 2472,
49 2484
50 };
51
52 template<typename T, size_t N>
arraySize(const T (&)[N])53 constexpr size_t arraySize(const T (&)[N]) {
54 return N;
55 }
56
Interface(Netlink & netlink,const char * name)57 Interface::Interface(Netlink& netlink, const char* name)
58 : mNetlink(netlink)
59 , mName(name)
60 , mInterfaceIndex(0)
61 , mApfMemory(kApfRamSize) {
62 }
63
Interface(Interface && other)64 Interface::Interface(Interface&& other) noexcept
65 : mNetlink(other.mNetlink)
66 , mName(std::move(other.mName))
67 , mInterfaceIndex(other.mInterfaceIndex)
68 , mApfMemory(std::move(other.mApfMemory)) {
69 }
70
init()71 bool Interface::init() {
72 mInterfaceIndex = if_nametoindex(mName.c_str());
73 if (mInterfaceIndex == 0) {
74 ALOGE("Unable to get interface index for %s", mName.c_str());
75 return false;
76 }
77 return true;
78 }
79
getSupportedFeatureSet(feature_set * set)80 wifi_error Interface::getSupportedFeatureSet(feature_set* set) {
81 if (set == nullptr) {
82 return WIFI_ERROR_INVALID_ARGS;
83 }
84 *set = 0;
85 return WIFI_SUCCESS;
86 }
87
getName(char * name,size_t size)88 wifi_error Interface::getName(char* name, size_t size) {
89 if (size < mName.size() + 1) {
90 return WIFI_ERROR_INVALID_ARGS;
91 }
92 strlcpy(name, mName.c_str(), size);
93 return WIFI_SUCCESS;
94 }
95
96 // Wifi legacy HAL implicitly assumes getLinkStats is blocking and
97 // handler will be set to nullptr immediately after invocation.
98 // Therefore, this function will wait until onLinkStatsReply is called.
getLinkStats(wifi_request_id requestId,wifi_stats_result_handler handler)99 wifi_error Interface::getLinkStats(wifi_request_id requestId,
100 wifi_stats_result_handler handler) {
101 NetlinkMessage message(RTM_GETLINK, mNetlink.getSequenceNumber());
102
103 ifinfomsg* info = message.payload<ifinfomsg>();
104 info->ifi_family = AF_UNSPEC;
105 info->ifi_type = 1;
106 info->ifi_index = mInterfaceIndex;
107 info->ifi_flags = 0;
108 info->ifi_change = 0xFFFFFFFF;
109
110 std::promise<void> p;
111
112 auto callback = [this, requestId, &handler,
113 &p] (const NetlinkMessage& message) {
114 onLinkStatsReply(requestId, handler, message);
115 p.set_value();
116 };
117
118 bool success = mNetlink.sendMessage(message, callback);
119 // Only wait when callback will be invoked. Therefore, test if the message
120 // is sent successfully first.
121 if (success) {
122 p.get_future().wait();
123 }
124 return success ? WIFI_SUCCESS : WIFI_ERROR_UNKNOWN;
125 }
126
setLinkStats(wifi_link_layer_params)127 wifi_error Interface::setLinkStats(wifi_link_layer_params /*params*/) {
128 return WIFI_SUCCESS;
129 }
130
setAlertHandler(wifi_request_id,wifi_alert_handler)131 wifi_error Interface::setAlertHandler(wifi_request_id /*id*/,
132 wifi_alert_handler /*handler*/) {
133 return WIFI_SUCCESS;
134 }
135
resetAlertHandler(wifi_request_id)136 wifi_error Interface::resetAlertHandler(wifi_request_id /*id*/) {
137 return WIFI_SUCCESS;
138 }
139
getFirmwareVersion(char * buffer,size_t size)140 wifi_error Interface::getFirmwareVersion(char* buffer, size_t size) {
141 if (size < sizeof(kFirmwareVersion)) {
142 return WIFI_ERROR_INVALID_ARGS;
143 }
144 strcpy(buffer, kFirmwareVersion);
145 return WIFI_SUCCESS;
146 }
147
getDriverVersion(char * buffer,size_t size)148 wifi_error Interface::getDriverVersion(char* buffer, size_t size) {
149 if (size < sizeof(kDriverVersion)) {
150 return WIFI_ERROR_INVALID_ARGS;
151 }
152 strcpy(buffer, kDriverVersion);
153 return WIFI_SUCCESS;
154 }
155
setScanningMacOui(oui)156 wifi_error Interface::setScanningMacOui(oui /*scan_oui*/) {
157 return WIFI_SUCCESS;
158 }
159
clearLinkStats(u32,u32 * responseMask,u8,u8 * response)160 wifi_error Interface::clearLinkStats(u32 /*requestMask*/,
161 u32* responseMask,
162 u8 /*request*/,
163 u8* response) {
164 if (responseMask == nullptr || response == nullptr) {
165 return WIFI_ERROR_INVALID_ARGS;
166 }
167 return WIFI_SUCCESS;
168 }
169
getValidChannels(int band,int maxChannels,wifi_channel * channels,int * numChannels)170 wifi_error Interface::getValidChannels(int band,
171 int maxChannels,
172 wifi_channel* channels,
173 int* numChannels) {
174 if (channels == nullptr || numChannels == nullptr || maxChannels < 0) {
175 return WIFI_ERROR_INVALID_ARGS;
176 }
177 switch (band) {
178 case WIFI_BAND_BG: // 2.4 GHz
179 *numChannels = std::min<int>(maxChannels,
180 arraySize(k2p4Channels));
181 memcpy(channels, k2p4Channels, *numChannels);
182
183 return WIFI_SUCCESS;
184 default:
185 return WIFI_ERROR_NOT_SUPPORTED;
186 }
187 }
188
startLogging(u32,u32,u32,u32,char *)189 wifi_error Interface::startLogging(u32 /*verboseLevel*/,
190 u32 /*flags*/,
191 u32 /*maxIntervalSec*/,
192 u32 /*minDataSize*/,
193 char* /*ringName*/) {
194 return WIFI_SUCCESS;
195 }
196
setCountryCode(const char *)197 wifi_error Interface::setCountryCode(const char* /*countryCode*/) {
198 return WIFI_SUCCESS;
199 }
200
setLogHandler(wifi_request_id,wifi_ring_buffer_data_handler)201 wifi_error Interface::setLogHandler(wifi_request_id /*id*/,
202 wifi_ring_buffer_data_handler /*handler*/) {
203 return WIFI_SUCCESS;
204 }
205
getRingBuffersStatus(u32 * numRings,wifi_ring_buffer_status * status)206 wifi_error Interface::getRingBuffersStatus(u32* numRings,
207 wifi_ring_buffer_status* status) {
208 if (numRings == nullptr || status == nullptr || *numRings == 0) {
209 return WIFI_ERROR_INVALID_ARGS;
210 }
211
212 memset(status, 0, sizeof(*status));
213 strlcpy(reinterpret_cast<char*>(status->name),
214 "ring0",
215 sizeof(status->name));
216 *numRings = 1;
217 return WIFI_SUCCESS;
218 }
219
getLoggerSupportedFeatureSet(unsigned int * support)220 wifi_error Interface::getLoggerSupportedFeatureSet(unsigned int* support) {
221 if (support == nullptr) {
222 return WIFI_ERROR_INVALID_ARGS;
223 }
224 *support = 0;
225 return WIFI_SUCCESS;
226 }
227
getRingData(char *)228 wifi_error Interface::getRingData(char* /*ringName*/) {
229 return WIFI_SUCCESS;
230 }
231
configureNdOffload(u8)232 wifi_error Interface::configureNdOffload(u8 /*enable*/) {
233 return WIFI_SUCCESS;
234 }
235
startPacketFateMonitoring()236 wifi_error Interface::startPacketFateMonitoring() {
237 return WIFI_SUCCESS;
238 }
239
getTxPacketFates(wifi_tx_report *,size_t,size_t * numProvidedFates)240 wifi_error Interface::getTxPacketFates(wifi_tx_report* /*txReportBuffers*/,
241 size_t /*numRequestedFates*/,
242 size_t* numProvidedFates) {
243 if (numProvidedFates == nullptr) {
244 return WIFI_ERROR_INVALID_ARGS;
245 }
246 *numProvidedFates = 0;
247 return WIFI_SUCCESS;
248 }
249
getRxPacketFates(wifi_rx_report *,size_t,size_t * numProvidedFates)250 wifi_error Interface::getRxPacketFates(wifi_rx_report* /*rxReportBuffers*/,
251 size_t /*numRequestedFates*/,
252 size_t* numProvidedFates) {
253 if (numProvidedFates == nullptr) {
254 return WIFI_ERROR_INVALID_ARGS;
255 }
256 *numProvidedFates = 0;
257 return WIFI_SUCCESS;
258 }
259
getPacketFilterCapabilities(u32 * version,u32 * maxLength)260 wifi_error Interface::getPacketFilterCapabilities(u32* version,
261 u32* maxLength) {
262 if (version == nullptr || maxLength == nullptr) {
263 return WIFI_ERROR_INVALID_ARGS;
264 }
265 *version = 4;
266 *maxLength = kApfRamSize;
267 return WIFI_SUCCESS;
268 }
269
readPacketFilter(u32 src_offset,u8 * host_dst,u32 length)270 wifi_error Interface::readPacketFilter(u32 src_offset, u8 *host_dst, u32 length) {
271 if (src_offset >= mApfMemory.size() || host_dst == nullptr
272 || length > mApfMemory.size() - src_offset) {
273 return WIFI_ERROR_INVALID_ARGS;
274 }
275 std::copy(mApfMemory.begin() + src_offset, mApfMemory.begin() + src_offset + length, host_dst);
276 return WIFI_SUCCESS;
277 }
278
setPacketFilter(const u8 * program,u32 len)279 wifi_error Interface::setPacketFilter(const u8 *program, u32 len) {
280 if (program == nullptr || len > mApfMemory.size()) {
281 return WIFI_ERROR_INVALID_ARGS;
282 }
283 std::copy(program, program + len, mApfMemory.begin());
284 return WIFI_SUCCESS;
285 }
286
287 wifi_error
getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT * wakeReasonCount)288 Interface::getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount) {
289 if (wakeReasonCount == nullptr) {
290 return WIFI_ERROR_INVALID_ARGS;
291 }
292 return WIFI_SUCCESS;
293 }
294
startSendingOffloadedPacket(wifi_request_id,u16,u8 *,u16,u8 *,u8 *,u32)295 wifi_error Interface::startSendingOffloadedPacket(wifi_request_id /*id*/,
296 u16 /*ether_type*/,
297 u8 * /*ip_packet*/,
298 u16 /*ip_packet_len*/,
299 u8 * /*src_mac_addr*/,
300 u8 * /*dst_mac_addr*/,
301 u32 /*period_msec*/) {
302 // Drop the packet and pretend everything is fine. Currentlty this is only
303 // used for keepalive packets to allow the CPU to go to sleep and let the
304 // hardware send keepalive packets on its own. By dropping this we lose the
305 // keepalive packets but networking will still be fine.
306 return WIFI_SUCCESS;
307 }
308
stopSendingOffloadedPacket(wifi_request_id)309 wifi_error Interface::stopSendingOffloadedPacket(wifi_request_id /*id*/) {
310 return WIFI_SUCCESS;
311 }
312
onLinkStatsReply(wifi_request_id requestId,wifi_stats_result_handler handler,const NetlinkMessage & message)313 void Interface::onLinkStatsReply(wifi_request_id requestId,
314 wifi_stats_result_handler handler,
315 const NetlinkMessage& message) {
316 if (message.size() < sizeof(nlmsghdr) + sizeof(ifinfomsg)) {
317 ALOGE("Invalid link stats response, too small");
318 return;
319 }
320 if (message.type() != RTM_NEWLINK) {
321 ALOGE("Recieved invalid link stats reply type: %u",
322 static_cast<unsigned int>(message.type()));
323 return;
324 }
325
326 int numRadios = 1;
327 wifi_radio_stat radioStats;
328 memset(&radioStats, 0, sizeof(radioStats));
329
330 wifi_iface_stat ifStats;
331 memset(&ifStats, 0, sizeof(ifStats));
332 ifStats.iface = reinterpret_cast<wifi_interface_handle>(this);
333
334 rtnl_link_stats64 netlinkStats64;
335 rtnl_link_stats netlinkStats;
336 if (message.getAttribute(IFLA_STATS64, &netlinkStats64)) {
337 ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats64.tx_packets;
338 ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats64.rx_packets;
339 } else if (message.getAttribute(IFLA_STATS, &netlinkStats)) {
340 ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats.tx_packets;
341 ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats.rx_packets;
342 } else {
343 return;
344 }
345
346 handler.on_link_stats_results(requestId, &ifStats, numRadios, &radioStats);
347 }
348