Virtual WIFI, stage 2: netlink commands and mac80211_hwsim header
NOTE: Some headers are not included in this CL. I've done this to split
a larger code review into smaller chunks.
Makefiles not included, either.
Change-Id: I976699e916db221cfee6545921888454bb975f9e
diff --git a/common/libs/wifi/cmd.cc b/common/libs/wifi/cmd.cc
new file mode 100644
index 0000000..762e7fb
--- /dev/null
+++ b/common/libs/wifi/cmd.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "host/commands/wifid/cmd.h"
+
+namespace avd {
+
+Cmd::Cmd() : msg_(nlmsg_alloc()) {}
+
+Cmd::~Cmd() {
+ for (auto& msg : responses_) {
+ nlmsg_free(msg);
+ }
+ nlmsg_free(msg_);
+}
+
+bool Cmd::OnResponse(nl_msg* msg) {
+ // nlmsg_get increases refcount on msg, but does not return the msg
+ // so we can't exactly use it as an argument to unique_ptr.
+ nlmsg_get(msg);
+ responses_.emplace_back(msg);
+ auto hdr = nlmsg_hdr(msg);
+
+ // Kernel documentation seems to be a bit misleading on this topic saying:
+ //
+ // In multipart messages (multiple nlmsghdr headers with associated
+ // payload in one byte stream) the first and all following headers have
+ // the NLM_F_MULTI flag set, except for the last header which has the type
+ // NLMSG_DONE.
+ //
+ // In theory, that would make processing multi-part messages simple, but in
+ // practice this does not seem to be true. Specifying exit criteria solely on
+ // NLM_F_MULTI flag setting will block some, if not all calls that dump
+ // NL80211 wifi interfaces for example.
+ if (!(hdr->nlmsg_flags & NLM_F_MULTI) || (hdr->nlmsg_type == NLMSG_DONE) ||
+ (hdr->nlmsg_type == NLMSG_ERROR)) {
+ std::lock_guard<std::mutex> lock(ready_mutex_);
+ ready_signal_.notify_all();
+ return true;
+ }
+
+ return false;
+}
+
+const std::vector<nl_msg*> Cmd::Responses() const {
+ std::unique_lock<std::mutex> lock(ready_mutex_);
+ ready_signal_.wait(lock, [this]() { return responses_.size() > 0; });
+ return responses_;
+}
+
+} // namespace avd
diff --git a/common/libs/wifi/cmd.h b/common/libs/wifi/cmd.h
new file mode 100644
index 0000000..c4bc57b
--- /dev/null
+++ b/common/libs/wifi/cmd.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <condition_variable>
+#include <memory>
+#include <thread>
+#include <vector>
+
+#include <netlink/msg.h>
+
+namespace avd {
+constexpr int kWifiSimVersion = 1;
+
+class Cmd {
+ public:
+ Cmd();
+ ~Cmd();
+
+ // Cmd() creates netlink request to be sent to kernel.
+ // Returns netlink message header structure.
+ nl_msg* Msg() const { return msg_; }
+
+ // Responses() holds execution until netlink responds to this message.
+ // Returns all netlink replies.
+ const std::vector<nl_msg*> Responses() const;
+
+ // OnResponse() handles data response from netlink.
+ // Returns value indicating 'done' state:
+ // - false, if more data is expected, or
+ // - true, if processing is complete and instance can be disposed of.
+ bool OnResponse(nl_msg* msg);
+
+ private:
+ nl_msg* msg_;
+ std::vector<nl_msg*> responses_;
+
+ mutable std::mutex ready_mutex_;
+ mutable std::condition_variable ready_signal_;
+
+ Cmd(const Cmd&) = delete;
+ Cmd& operator=(const Cmd&) = delete;
+};
+
+} // namespace avd
diff --git a/common/libs/wifi/mac80211.h b/common/libs/wifi/mac80211.h
new file mode 100644
index 0000000..c879174
--- /dev/null
+++ b/common/libs/wifi/mac80211.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <stdint.h>
+
+// The following definitions are required by uapi/mac80211_hwsim.h header.
+#define s8 int8_t
+#define u8 uint8_t
+#define BIT(x) (1 << (x))
+#define __packed __attribute__((packed))
+
+#include <uapi/mac80211_hwsim.h>
+
+#undef __packed
+#undef BIT
+#undef u8
+#undef s8