Exchange data between wireless interfaces with the help of wifirouter

MAC80211 HWSIM is validating injected messages against port
id belonging to whoever registers as wifi medium.
Only medium is allowed to inject messages.

With this change WIFI is capable of authenticating with remote
server. I am still trying to figure why regular data exchange is not
functioning properly.

Also: we are missing something in device.mk - don't know what it is yet.
Android is unable to start wifi by itself, so all tests are made
manually.

Change-Id: I6916c59f93168f7c5b8630cb684279db866ecbe7
Merged-In: I6916c59f93168f7c5b8630cb684279db866ecbe7
(cherry picked from commit 96638a79490091ecf64eedd5226de14b69dd1023)
diff --git a/common/libs/wifi/cmd.cc b/common/libs/wifi/cmd.cc
index 2576359..5c9208c 100644
--- a/common/libs/wifi/cmd.cc
+++ b/common/libs/wifi/cmd.cc
@@ -21,6 +21,11 @@
 
 Cmd::Cmd(nlmsghdr* h) : msg_(nlmsg_convert(h)) {}
 
+Cmd::Cmd(nl_msg* h) {
+  nlmsg_get(h);
+  msg_ = h;
+}
+
 Cmd::~Cmd() {
   for (auto& msg : responses_) {
     nlmsg_free(msg);
@@ -57,9 +62,13 @@
 }
 
 const std::vector<nl_msg*> Cmd::Responses() const {
+  WaitComplete();
+  return responses_;
+}
+
+void Cmd::WaitComplete() const {
   std::unique_lock<std::mutex> lock(ready_mutex_);
   ready_signal_.wait(lock, [this]() { return responses_.size() > 0; });
-  return responses_;
 }
 
 }  // namespace cvd
diff --git a/common/libs/wifi/cmd.h b/common/libs/wifi/cmd.h
index f9ff509..f0d633f 100644
--- a/common/libs/wifi/cmd.h
+++ b/common/libs/wifi/cmd.h
@@ -29,6 +29,7 @@
  public:
   Cmd();
   explicit Cmd(nlmsghdr* h);
+  explicit Cmd(nl_msg* h);
   ~Cmd();
 
   // Cmd() creates netlink request to be sent to kernel.
@@ -45,6 +46,9 @@
   // - true, if processing is complete and instance can be disposed of.
   bool OnResponse(nl_msg* msg);
 
+  // Wait until message processing is complete.
+  void WaitComplete() const;
+
  private:
   nl_msg* msg_;
   std::vector<nl_msg*> responses_;
diff --git a/common/libs/wifi/packet_switch.cc b/common/libs/wifi/packet_switch.cc
index f365c29..04c0593 100644
--- a/common/libs/wifi/packet_switch.cc
+++ b/common/libs/wifi/packet_switch.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 #include "common/libs/wifi/packet_switch.h"
+
+#include "common/libs/wifi/mac80211.h"
 #include "common/libs/wifi/router.h"
 
 #ifdef CUTTLEFISH_HOST
@@ -25,11 +27,17 @@
 PacketSwitch::~PacketSwitch() { Stop(); }
 
 bool PacketSwitch::Init() {
+  bool res;
 #ifdef CUTTLEFISH_HOST
-  return shm_wifi_.Open(vsoc::GetDomain().c_str());
+  res = shm_wifi_.Open(vsoc::GetDomain().c_str());
 #else
-  return shm_wifi_.Open();
+  res = shm_wifi_.Open();
 #endif
+
+  if (res) {
+    worker_ = shm_wifi_.StartWorker();
+  }
+  return res;
 }
 
 void PacketSwitch::Start() {
@@ -48,9 +56,14 @@
       auto hdr = reinterpret_cast<nlmsghdr*>(msg.get());
       std::unique_ptr<nl_msg, void (*)(nl_msg*)> nlm(nullptr, nlmsg_free);
 
-      int item = 0;
       while (started_) {
+#ifdef CUTTLEFISH_HOST
+      LOG(INFO) << "Awaiting packet.";
+#endif
         auto len = shm_wifi_.Recv(msg.get(), maxlen);
+#ifdef CUTTLEFISH_HOST
+      LOG(INFO) << "Received packet.";
+#endif
         nlm.reset(nlmsg_convert(hdr));
         ProcessPacket(nlm.get(), true);
       }
@@ -72,35 +85,22 @@
   auto genhdr = reinterpret_cast<genlmsghdr*>(nlmsg_data(header));
 
   if (genhdr->cmd == WIFIROUTER_CMD_NOTIFY) {
-    // This attribute is mandatory: it contains MAC80211_HWSIM frame.
-    auto packet =
-        nlmsg_find_attr(header, sizeof(*genhdr), WIFIROUTER_ATTR_PACKET);
-    if (!packet) return;
-
     // If origin is not local (= not set from local WIFI), then forward it to
     // local WIFI.
     if (is_incoming) {
+#ifdef CUTTLEFISH_HOST
+      LOG(INFO) << "Forwarding packet.";
+#endif
       // Need to update MAC80211_HWSIM WIFI family before injecting packet.
       // Different kernels may have different family numbers allocated.
-      auto frame = reinterpret_cast<nlmsghdr*>(nla_data(packet));
-      frame->nlmsg_type = nl_->FamilyMAC80211();
-      frame->nlmsg_pid = 0;
-      frame->nlmsg_seq = 0;
-      frame->nlmsg_flags = NLM_F_REQUEST;
-      Cmd local(frame);
-
-      nl_->GeNL().Send(&local);
-
-      for (auto* r : local.Responses()) {
-        auto hdr = nlmsg_hdr(r);
-        if (hdr->nlmsg_type == NLMSG_ERROR) {
-          nlmsgerr* err = static_cast<nlmsgerr*>(nlmsg_data(hdr));
-          if (err->error < 0) {
-            LOG(ERROR) << "Could not send WIFI message: "
-                       << strerror(-err->error);
-          }
-        }
-      }
+      header->nlmsg_type = nl_->FamilyMAC80211();
+      header->nlmsg_pid = 0;
+      header->nlmsg_seq = 0;
+      header->nlmsg_flags = NLM_F_REQUEST;
+      genhdr->cmd = WIFIROUTER_CMD_SEND;
+      Cmd c(m);
+      nl_->WRCL().Send(&c);
+      c.WaitComplete();
     } else {
       shm_wifi_.Send(header, header->nlmsg_len);
     }
diff --git a/common/libs/wifi/packet_switch.h b/common/libs/wifi/packet_switch.h
index 0fbe213..e2b027c 100644
--- a/common/libs/wifi/packet_switch.h
+++ b/common/libs/wifi/packet_switch.h
@@ -45,6 +45,7 @@
   bool started_ = false;
 
   std::unique_ptr<std::thread> shm_xchg_;
+  std::unique_ptr<vsoc::RegionWorker> worker_;
   vsoc::wifi::WifiExchangeView shm_wifi_;
 
   PacketSwitch(const PacketSwitch&) = delete;
diff --git a/common/libs/wifi/virtual_wifi.cc b/common/libs/wifi/virtual_wifi.cc
index 140ff77..1c38201 100644
--- a/common/libs/wifi/virtual_wifi.cc
+++ b/common/libs/wifi/virtual_wifi.cc
@@ -189,12 +189,13 @@
   return -1;
 }
 
-bool RegisterForRouterNotifications(Netlink* nl, int hwsim_id) {
+bool RegisterForRouterNotifications(Netlink* nl, int hwsim_id, uint8_t* addr) {
   Cmd msg;
 
   if (!genlmsg_put(msg.Msg(), NL_AUTO_PID, NL_AUTO_SEQ, 0, 0,
                    NLM_F_REQUEST, WIFIROUTER_CMD_REGISTER, 0) ||
-      nla_put_u32(msg.Msg(), WIFIROUTER_ATTR_HWSIM_ID, hwsim_id)) {
+      nla_put_u32(msg.Msg(), WIFIROUTER_ATTR_HWSIM_ID, hwsim_id) ||
+      nla_put(msg.Msg(), WIFIROUTER_ATTR_HWSIM_ADDR, ETH_ALEN, addr)) {
     LOG(ERROR) << "Could not create wifirouter register message.";
     return false;
   }
@@ -277,14 +278,14 @@
 
   // 4. Apply requested interface name.
   LOG(INFO) << "Updating interface name to: " << name_;
-  if (!SetWLANInterface(nl_, iface_number_, name_, &mac_addr_[0])) {
+  if (!SetWLANInterface(nl_, iface_number_, name_, mac_addr_)) {
     LOG(ERROR) << "Could not update wlan interface name.";
     return false;
   }
 
   // 5. Register with wifi router.
   LOG(INFO) << "Registering for notifications for: " << addr_;
-  if (!RegisterForRouterNotifications(nl_, hwsim_number_)) {
+  if (!RegisterForRouterNotifications(nl_, hwsim_number_, mac_addr_)) {
     LOG(ERROR) << "Could not register with wifi router.";
     return false;
   }