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