1 /*
2 * Copyright 2019, 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 "local_connection.h"
18
19 #include "hwsim.h"
20 #include "log.h"
21 #include "macaddress.h"
22 #include "netlink_message.h"
23
24 #include <net/ethernet.h>
25 #include <netlink/netlink.h>
26 #include <netlink/genl/ctrl.h>
27 #include <netlink/genl/genl.h>
28
29 #include <utils/CallStack.h>
30
31 #include <inttypes.h>
32 #include <stdlib.h>
33
34 static const char kHwSimFamilyName[] = "MAC80211_HWSIM";
35 static const int kHwSimVersion = 1;
36 static const unsigned int kDefaultSignalStrength = -50;
37 static const int kDefaultSocketBufferSize = 8 * (1 << 20);
38
getSeqNum(struct nl_msg * msg)39 static uint32_t getSeqNum(struct nl_msg* msg) {
40 return nlmsg_hdr(msg)->nlmsg_seq;
41 }
42
onSent(struct nl_msg *,void *)43 static int onSent(struct nl_msg* , void*) {
44 return NL_OK;
45 }
46
onSeqCheck(struct nl_msg * msg,void *)47 static int onSeqCheck(struct nl_msg* msg, void*) {
48 uint32_t seq = getSeqNum(msg);
49 return seq == 0 ? NL_SKIP : NL_OK;
50 }
51
LocalConnection(OnFrameCallback onFrameCallback,OnAckCallback onAckCallback,OnErrorCallback onErrorCallback)52 LocalConnection::LocalConnection(OnFrameCallback onFrameCallback,
53 OnAckCallback onAckCallback,
54 OnErrorCallback onErrorCallback)
55 : mOnFrameCallback(onFrameCallback)
56 , mOnAckCallback(onAckCallback)
57 , mOnErrorCallback(onErrorCallback) {
58
59 }
60
init(std::chrono::steady_clock::time_point now)61 Result LocalConnection::init(std::chrono::steady_clock::time_point now) {
62 Result res = mNetlinkSocket.init();
63 if (!res) { return res; }
64 res = mNetlinkSocket.setOnMsgInCallback(staticOnMessage, this);
65 if (!res) { return res; }
66 res = mNetlinkSocket.setOnMsgOutCallback(onSent, this);
67 if (!res) { return res; }
68 res = mNetlinkSocket.setOnSeqCheckCallback(onSeqCheck, this);
69 if (!res) { return res; }
70 res = mNetlinkSocket.setOnAckCallback(staticOnAck, this);
71 if (!res) { return res; }
72 res = mNetlinkSocket.setOnErrorCallback(staticOnError, this);
73 if (!res) { return res; }
74 res = mNetlinkSocket.connectGeneric();
75 if (!res) { return res; }
76 res = mNetlinkSocket.setBufferSizes(kDefaultSocketBufferSize,
77 kDefaultSocketBufferSize);
78 if (!res) { return res; }
79
80 mNetlinkFamily = mNetlinkSocket.resolveNetlinkFamily(kHwSimFamilyName);
81 if (mNetlinkFamily < 0) {
82 return Result::error("Failed to resolve netlink family name: %s",
83 nl_geterror(mNetlinkFamily));
84 }
85
86 mPendingFrames.setCurrentTime(now);
87 mSequenceNumberCookies.setCurrentTime(now);
88
89 mLastCacheTimeUpdate = now;
90 mLastCacheExpiration = now;
91
92 return registerReceiver();
93 }
94
getFd() const95 int LocalConnection::getFd() const {
96 return mNetlinkSocket.getFd();
97 }
98
receive()99 bool LocalConnection::receive() {
100 return mNetlinkSocket.receive();
101 }
102
transferFrame(std::unique_ptr<Frame> frame,const MacAddress & dest)103 uint32_t LocalConnection::transferFrame(std::unique_ptr<Frame> frame,
104 const MacAddress& dest) {
105 NetlinkMessage msg;
106
107 if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_FRAME, kHwSimVersion)) {
108 ALOGE("LocalConnection transferFrame failed to init msg");
109 return 0;
110 }
111
112 frame->incrementAttempts();
113
114 if (!msg.addAttribute(HWSIM_ATTR_ADDR_RECEIVER, dest.addr, ETH_ALEN) ||
115 !msg.addAttribute(HWSIM_ATTR_FRAME, frame->data(), frame->size()) ||
116 !msg.addAttribute(HWSIM_ATTR_RX_RATE, 1u) ||
117 !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
118 !msg.addAttribute(HWSIM_ATTR_FREQ, frame->channel())) {
119
120 ALOGE("LocalConnection transferFrame failed to set attrs");
121 return 0;
122 }
123
124 if (!mNetlinkSocket.send(msg)) {
125 return 0;
126 }
127
128 // Store the radio destination for potential retransmissions.
129 frame->setRadioDestination(dest);
130
131 uint32_t seqNum = msg.getSeqNum();
132 uint64_t cookie = frame->cookie();
133 FrameId id(cookie, frame->transmitter());
134 mSequenceNumberCookies[seqNum] = id;
135 mPendingFrames[id] = std::move(frame);
136
137 return seqNum;
138 }
139
cloneFrame(const Frame & frame,const MacAddress & dest)140 uint32_t LocalConnection::cloneFrame(const Frame& frame,
141 const MacAddress& dest) {
142 auto copy = std::make_unique<Frame>(frame.data(),
143 frame.size(),
144 frame.transmitter(),
145 frame.cookie(),
146 frame.flags(),
147 frame.channel(),
148 frame.rates().data(),
149 frame.rates().size());
150 return transferFrame(std::move(copy), dest);
151 }
152
ackFrame(FrameInfo & info,bool success)153 bool LocalConnection::ackFrame(FrameInfo& info, bool success) {
154 NetlinkMessage msg;
155
156 if (!msg.initGeneric(mNetlinkFamily,
157 HWSIM_CMD_TX_INFO_FRAME,
158 kHwSimVersion)) {
159 ALOGE("LocalConnection ackFrame failed to create msg");
160 return false;
161 }
162
163 uint32_t flags = info.flags();
164 if (success) {
165 flags |= HWSIM_TX_STAT_ACK;
166 }
167
168 const uint8_t* transmitter = info.transmitter().addr;
169 const Rates& rates = info.rates();
170 if (!msg.addAttribute(HWSIM_ATTR_ADDR_TRANSMITTER, transmitter, ETH_ALEN) ||
171 !msg.addAttribute(HWSIM_ATTR_TX_INFO, rates.data(), rates.size()) ||
172 !msg.addAttribute(HWSIM_ATTR_FLAGS, flags) ||
173 !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
174 !msg.addAttribute(HWSIM_ATTR_COOKIE, info.cookie())) {
175
176 ALOGE("LocalConnection ackFrame failed to set attributes");
177 return false;
178 }
179
180 if (!mNetlinkSocket.send(msg)) {
181 return false;
182 }
183 mPendingFrames.erase(FrameId(info.cookie(), info.transmitter()));
184 return true;
185 }
186
getTimeout() const187 std::chrono::steady_clock::time_point LocalConnection::getTimeout() const {
188 if (mRetryQueue.empty()) {
189 return std::chrono::steady_clock::time_point::max();
190 }
191 return mRetryQueue.top().first;
192 }
193
onTimeout(std::chrono::steady_clock::time_point now)194 void LocalConnection::onTimeout(std::chrono::steady_clock::time_point now) {
195
196 if (now - mLastCacheTimeUpdate > std::chrono::seconds(1)) {
197 // Only update the time once per second, there's no need for a super
198 // high resolution here. We just want to make sure these caches don't
199 // fill up over a long period of time.
200 mPendingFrames.setCurrentTime(now);
201 mSequenceNumberCookies.setCurrentTime(now);
202 mLastCacheTimeUpdate = now;
203 }
204 if (now - mLastCacheExpiration > std::chrono::seconds(10)) {
205 // Only expire entries every 10 seconds, this is an operation that has
206 // some cost to it and doesn't have to happen very often.
207 mPendingFrames.expireEntries();
208 mSequenceNumberCookies.expireEntries();
209 mLastCacheExpiration = now;
210 }
211
212 while (!mRetryQueue.empty() && now >= mRetryQueue.top().first) {
213 FrameId id = mRetryQueue.top().second;
214 auto frameIt = mPendingFrames.find(id);
215 if (frameIt != mPendingFrames.end()) {
216 // Frame is still available, retry it
217 std::unique_ptr<Frame> frame = std::move(frameIt->second);
218 mPendingFrames.erase(frameIt);
219 MacAddress dest = frame->radioDestination();
220 transferFrame(std::move(frame), dest);
221 }
222 mRetryQueue.pop();
223 }
224 }
225
registerReceiver()226 Result LocalConnection::registerReceiver() {
227 NetlinkMessage msg;
228
229 if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_REGISTER, kHwSimVersion)) {
230 return Result::error("Failed to create register receiver message");
231 }
232
233 if (!mNetlinkSocket.send(msg)) {
234 return Result::error("Failed to send register receiver message");
235 }
236 return Result::success();
237 }
238
staticOnMessage(struct nl_msg * msg,void * context)239 int LocalConnection::staticOnMessage(struct nl_msg* msg, void* context) {
240 if (!context) {
241 return NL_SKIP;
242 }
243 auto connection = static_cast<LocalConnection*>(context);
244 return connection->onMessage(msg);
245 }
246
staticOnAck(struct nl_msg * msg,void * context)247 int LocalConnection::staticOnAck(struct nl_msg* msg, void* context) {
248 if (!context) {
249 return NL_SKIP;
250 }
251 auto connection = static_cast<LocalConnection*>(context);
252 return connection->onAck(msg);
253 }
254
staticOnError(struct sockaddr_nl * addr,struct nlmsgerr * error,void * context)255 int LocalConnection::staticOnError(struct sockaddr_nl* addr,
256 struct nlmsgerr* error,
257 void* context) {
258 if (!context) {
259 return NL_SKIP;
260 }
261 auto connection = static_cast<LocalConnection*>(context);
262 return connection->onError(addr, error);
263 }
264
onMessage(struct nl_msg * msg)265 int LocalConnection::onMessage(struct nl_msg* msg) {
266 struct nlmsghdr* hdr = nlmsg_hdr(msg);
267 auto generic = reinterpret_cast<const struct genlmsghdr*>(nlmsg_data(hdr));
268
269 switch (generic->cmd) {
270 case HWSIM_CMD_FRAME:
271 return onFrame(msg);
272 }
273 return NL_OK;
274 }
275
onFrame(struct nl_msg * msg)276 int LocalConnection::onFrame(struct nl_msg* msg) {
277
278 struct nlmsghdr* hdr = nlmsg_hdr(msg);
279 std::unique_ptr<Frame> frame = parseFrame(hdr);
280 if (!frame) {
281 return NL_SKIP;
282 }
283
284 mOnFrameCallback(std::move(frame));
285 return NL_OK;
286 }
287
parseFrame(struct nlmsghdr * hdr)288 std::unique_ptr<Frame> LocalConnection::parseFrame(struct nlmsghdr* hdr) {
289 struct nlattr* attrs[HWSIM_ATTR_MAX + 1];
290 genlmsg_parse(hdr, 0, attrs, HWSIM_ATTR_MAX, nullptr);
291 if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
292 ALOGE("Received cmd frame without transmitter address");
293 return nullptr;
294 }
295 if (!attrs[HWSIM_ATTR_TX_INFO]) {
296 ALOGE("Received cmd frame without tx rates");
297 return nullptr;
298 }
299 if (!attrs[HWSIM_ATTR_FREQ]) {
300 ALOGE("Recieved cmd frame without channel frequency");
301 return nullptr;
302 }
303
304 uint64_t cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]);
305
306 const auto& source = *reinterpret_cast<const MacAddress*>(
307 nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]));
308
309 auto rates = reinterpret_cast<const hwsim_tx_rate*>(
310 nla_data(attrs[HWSIM_ATTR_TX_INFO]));
311 int rateLength = nla_len(attrs[HWSIM_ATTR_TX_INFO]);
312 // Make sure the length is valid, must be multiple of hwsim_tx_rate
313 if (rateLength <= 0 || (rateLength % sizeof(hwsim_tx_rate)) != 0) {
314 ALOGE("Invalid tx rate length %d", rateLength);
315 }
316 size_t numRates = static_cast<size_t>(rateLength) / sizeof(hwsim_tx_rate);
317
318 int length = nla_len(attrs[HWSIM_ATTR_FRAME]);
319 auto data = reinterpret_cast<uint8_t*>(nla_data(attrs[HWSIM_ATTR_FRAME]));
320
321 uint32_t flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]);
322
323 uint32_t channel = nla_get_u32(attrs[HWSIM_ATTR_FREQ]);
324
325 return std::make_unique<Frame>(data, length, source, cookie,
326 flags, channel, rates, numRates);
327 }
328
onAck(struct nl_msg * msg)329 int LocalConnection::onAck(struct nl_msg* msg) {
330 struct nlmsghdr* hdr = nlmsg_hdr(msg);
331 uint32_t seqNum = hdr->nlmsg_seq;
332 auto cookie = mSequenceNumberCookies.find(seqNum);
333 if (cookie == mSequenceNumberCookies.end()) {
334 // This is not a frame we sent. This is fairly common for libnl's
335 // internal use so don't log this.
336 return NL_SKIP;
337 }
338 auto pendingFrame = mPendingFrames.find(cookie->second);
339 // We don't need to keep this around anymore, erase it.
340 mSequenceNumberCookies.erase(seqNum);
341 if (pendingFrame == mPendingFrames.end()) {
342 // We have no cookie associated with this sequence number. This might
343 // happen if the remote connection already acked the frame and removed
344 // the frame info. Consider this resolved.
345 return NL_SKIP;
346 }
347
348 Frame* frame = pendingFrame->second.get();
349 mOnAckCallback(frame->info());
350 // Make sure to erase using the cookie instead of the iterator. The callback
351 // might have already erased this entry so the iterator could be invalid at
352 // this point. Instead of a fancy scheme of checking this just play it safe
353 // to allow the callback more freedom.
354 mPendingFrames.erase(cookie->second);
355
356 return NL_OK;
357 }
358
onError(struct sockaddr_nl *,struct nlmsgerr * error)359 int LocalConnection::onError(struct sockaddr_nl*, struct nlmsgerr* error) {
360 struct nlmsghdr* hdr = &error->msg;
361 uint32_t seqNum = hdr->nlmsg_seq;
362
363 auto idIt = mSequenceNumberCookies.find(seqNum);
364 if (idIt == mSequenceNumberCookies.end()) {
365 return NL_SKIP;
366 }
367 FrameId id = idIt->second;
368 // No need to keep the sequence number around anymore, it's expired and is
369 // no longer useful.
370 mSequenceNumberCookies.erase(idIt);
371
372 auto frameIt = mPendingFrames.find(id);
373 if (frameIt == mPendingFrames.end()) {
374 return NL_SKIP;
375 }
376 Frame* frame = frameIt->second.get();
377
378 if (!frame->hasRemainingAttempts()) {
379 // This frame has used up all its attempts, there's nothing we can do
380 mOnErrorCallback(frame->info());
381 mPendingFrames.erase(id);
382 return NL_SKIP;
383 }
384 // Store the frame in the retry queue
385 uint64_t timeout = frame->calcNextTimeout();
386 auto deadline = std::chrono::steady_clock::now() +
387 std::chrono::microseconds(timeout);
388 mRetryQueue.emplace(deadline, id);
389
390 return NL_SKIP;
391 }
392
393