Clean up and simplify WiFi

* Add a flag to save a pcap file
* Strip netlink headers before forwarding the packet
* Remove libraries and dead code

BUG: 78296257
Change-Id: I6a4b2bb4899a989cf214b627cdfd78fe5b3d844d
Test: Local build and boot on pi-gce-dev
diff --git a/common/commands/wifi_relay/Android.bp b/common/commands/wifi_relay/Android.bp
index e39accd..c496ef0 100644
--- a/common/commands/wifi_relay/Android.bp
+++ b/common/commands/wifi_relay/Android.bp
@@ -16,6 +16,9 @@
 cc_binary {
     name: "wifi_relay",
     srcs: [
+        "cmd.cpp",
+	"mac80211_hwsim.cpp",
+        "nl_client.cpp",
         "wifi_relay.cpp",
     ],
     shared_libs: [
@@ -28,8 +31,6 @@
     ],
     static_libs: [
         "libgflags",
-        "libcuttlefish_wifi_relay",
-        "libcuttlefish_wifi",
     ],
     header_libs: [
         "cuttlefish_glog",
diff --git a/common/libs/wifi/cmd.cc b/common/commands/wifi_relay/cmd.cpp
similarity index 97%
rename from common/libs/wifi/cmd.cc
rename to common/commands/wifi_relay/cmd.cpp
index 5c9208c..7e5a88d 100644
--- a/common/libs/wifi/cmd.cc
+++ b/common/commands/wifi_relay/cmd.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "common/libs/wifi/cmd.h"
+#include "common/commands/wifi_relay/cmd.h"
 
 namespace cvd {
 
diff --git a/common/libs/wifi/cmd.h b/common/commands/wifi_relay/cmd.h
similarity index 100%
rename from common/libs/wifi/cmd.h
rename to common/commands/wifi_relay/cmd.h
diff --git a/common/libs/wifi_relay/mac80211_hwsim.cpp b/common/commands/wifi_relay/mac80211_hwsim.cpp
similarity index 78%
rename from common/libs/wifi_relay/mac80211_hwsim.cpp
rename to common/commands/wifi_relay/mac80211_hwsim.cpp
index ed72ce7..ab52a15 100644
--- a/common/libs/wifi_relay/mac80211_hwsim.cpp
+++ b/common/commands/wifi_relay/mac80211_hwsim.cpp
@@ -14,14 +14,19 @@
  * limitations under the License.
  */
 
-#include "common/libs/wifi_relay/mac80211_hwsim.h"
+#include "common/commands/wifi_relay/mac80211_hwsim.h"
 
-#include "common/libs/wifi_relay/mac80211_hwsim_driver.h"
+#include "common/commands/wifi_relay/mac80211_hwsim_driver.h"
 
 #include <glog/logging.h>
 #include <netlink/genl/ctrl.h>
 #include <netlink/genl/genl.h>
 #include <signal.h>
+#include <sys/uio.h>
+#include <gflags/gflags.h>
+
+DEFINE_string(
+        pcap, "", "Path to save a pcap file of packets");
 
 static constexpr char kWifiSimFamilyName[] = "MAC80211_HWSIM";
 static constexpr char kNl80211FamilyName[] = "nl80211";
@@ -32,6 +37,65 @@
 static constexpr size_t ETH_ALEN = 6;
 #endif
 
+namespace {
+
+struct pcap_hdr_t {
+  uint32_t magic_number;   /* magic number */
+  uint16_t version_major;  /* major version number */
+  uint16_t version_minor;  /* minor version number */
+  int32_t  thiszone;       /* GMT to local correction */
+  uint32_t sigfigs;        /* accuracy of timestamps */
+  uint32_t snaplen;        /* max length of captured packets, in octets */
+  uint32_t network;        /* data link type */
+};
+
+struct pcaprec_hdr_t {
+  uint32_t ts_sec;         /* timestamp seconds */
+  uint32_t ts_usec;        /* timestamp microseconds */
+  uint32_t incl_len;       /* number of octets of packet saved in file */
+  uint32_t orig_len;       /* actual length of packet */
+};
+
+const pcap_hdr_t pcap_file_header{
+  0xa1b2c3d4,
+  2,
+  4,
+  0,
+  0,
+  65536,
+  105    // IEEE802.11 without radiotap
+};
+
+void WritePCap(const void* buffer, size_t length) {
+  if (FLAGS_pcap.empty()) {
+    return;
+  }
+  static int pcap = -1;
+  if (pcap == -1) {
+    pcap = open(FLAGS_pcap.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0644);
+    if (pcap == -1) {
+      return;
+    }
+    (void)write(pcap, &pcap_file_header, sizeof(pcap_file_header));
+  }
+  size_t write_length = length;
+  if (write_length > pcap_file_header.snaplen) {
+    write_length = pcap_file_header.snaplen;
+  }
+  pcaprec_hdr_t hdr;
+  struct timespec now;
+  clock_gettime(CLOCK_REALTIME, &now);
+  hdr.ts_sec = now.tv_sec;
+  hdr.ts_usec = now.tv_nsec / 1000;
+  hdr.incl_len = write_length;
+  hdr.orig_len = length;
+  struct iovec iov[2] { {&hdr, sizeof(hdr)},
+    { const_cast<void*>(buffer), static_cast<size_t>(write_length)}};
+  (void)writev(pcap, iov, 2);
+}
+
+}
+
 Mac80211HwSim::Remote::Remote(
         Mac80211HwSim *parent,
         vsoc::wifi::WifiExchangeView *wifiExchange)
@@ -51,17 +115,10 @@
             LOG(ERROR) << "WifiExchangeView::Recv failed w/ res " << res;
             continue;
           }
+          WritePCap(buf.get(), static_cast<size_t>(res));
 
           // LOG(INFO) << "GUEST->HOST packet of size " << res;
-
-          struct nlmsghdr *hdr = reinterpret_cast<struct nlmsghdr *>(buf.get());
-
-          int len = res;
-          while (nlmsg_ok(hdr, len)) {
-            mParent->injectMessage(hdr);
-
-            hdr = nlmsg_next(hdr, &len);
-          }
+          mParent->injectFrame(buf.get(), res);
     }});
 }
 
@@ -73,7 +130,8 @@
 }
 
 intptr_t Mac80211HwSim::Remote::send(const void *data, size_t size) {
-    return mWifiExchange->Send(data, size);
+  WritePCap(data, size);
+  return mWifiExchange->Send(data, size);
 }
 
 Mac80211HwSim::Mac80211HwSim(const MacAddress &mac)
@@ -147,73 +205,6 @@
     return nl_socket_get_fd(mSock.get());
 }
 
-void Mac80211HwSim::dumpMessage(nlmsghdr *msg) const {
-    genlmsghdr *hdr = genlmsg_hdr(msg);
-
-    LOG(VERBOSE) << "message cmd = " << (int)hdr->cmd;
-
-    nlattr *attrs[__HWSIM_ATTR_MAX + 1];
-    int res = genlmsg_parse(
-            msg,
-            0 /* hdrlen */,
-            attrs,
-            __HWSIM_ATTR_MAX,
-            nullptr /* policy */);
-
-    if (res < 0) {
-        LOG(ERROR) << "genlmsg_parse failed.";
-        return;
-    }
-
-    // for HWSIM_CMD_FRAME, the following attributes are present:
-    // HWSIM_ATTR_ADDR_TRANSMITTER, HWSIM_ATTR_FRAME, HWSIM_ATTR_FLAGS,
-    // HWSIM_ATTR_TX_INFO, HWSIM_ATTR_COOKIE, HWSIM_ATTR_FREQ
-
-    for (size_t i = 0; i < __HWSIM_ATTR_MAX; ++i) {
-        if (attrs[i]) {
-            LOG(VERBOSE) << "Got attribute " << i;
-        }
-    }
-}
-
-void Mac80211HwSim::injectMessage(nlmsghdr *msg) {
-#ifdef CUTTLEFISH_HOST
-    LOG(VERBOSE) << "------------------- Guest -> Host -----------------------";
-#else
-    LOG(VERBOSE) << "------------------- Host -> Guest -----------------------";
-#endif
-    dumpMessage(msg);
-
-    // Do NOT check nlmsg_type against mMac80211Family, these are dynamically
-    // assigned and may not necessarily match across machines!
-
-    genlmsghdr *hdr = genlmsg_hdr(msg);
-    if (hdr->cmd != HWSIM_CMD_FRAME) {
-        LOG(VERBOSE) << "injectMessage: not cmd HWSIM_CMD_FRAME.";
-        return;
-    }
-
-    nlattr *attrs[__HWSIM_ATTR_MAX + 1];
-    int res = genlmsg_parse(
-            msg,
-            0 /* hdrlen */,
-            attrs,
-            __HWSIM_ATTR_MAX,
-            nullptr /* policy */);
-
-    if (res < 0) {
-        LOG(ERROR) << "genlmsg_parse failed.";
-        return;
-    }
-
-    nlattr *attr = attrs[HWSIM_ATTR_FRAME];
-    if (attr) {
-        injectFrame(nla_data(attr), nla_len(attr));
-    } else {
-        LOG(ERROR) << "injectMessage: no HWSIM_ATTR_FRAME.";
-    }
-}
-
 void Mac80211HwSim::ackFrame(nlmsghdr *inMsg) {
     nlattr *attrs[__HWSIM_ATTR_MAX + 1];
     int res = genlmsg_parse(
@@ -297,7 +288,6 @@
     nla_put_u32(msg.get(), HWSIM_ATTR_SIGNAL, kSignalLevelDefault);
 
     LOG(VERBOSE) << "INJECTING!";
-    dumpMessage(nlmsg_hdr(msg.get()));
 
     int res = nl_send_auto_complete(mSock.get(), msg.get());
 
@@ -339,18 +329,41 @@
     LOG(VERBOSE) << "------------------- Guest -> Host -----------------------";
 #endif
 
-    dumpMessage(msg.get());
+    genlmsghdr *hdr = genlmsg_hdr(msg.get());
+    if (hdr->cmd != HWSIM_CMD_FRAME) {
+        LOG(VERBOSE) << "cmd HWSIM_CMD_FRAME.";
+        return;
+    }
+
+    nlattr *attrs[__HWSIM_ATTR_MAX + 1];
+    int res = genlmsg_parse(
+        msg.get(),
+        0 /* hdrlen */,
+        attrs,
+        __HWSIM_ATTR_MAX,
+        nullptr /* policy */);
+
+    if (res < 0) {
+        LOG(ERROR) << "genlmsg_parse failed.";
+        return;
+    }
+
+    nlattr *attr = attrs[HWSIM_ATTR_FRAME];
+    if (!attr) {
+        LOG(ERROR) << "no HWSIM_ATTR_FRAME.";
+        return;
+    }
+    std::lock_guard<std::mutex> autoLock(mRemotesLock);
+    for (auto &remoteEntry : mRemotes) {
+      // TODO(andih): Check which remotes to forward this packet to based
+      // on the destination address.
+      remoteEntry.second->send(nla_data(attr), nla_len(attr));
+    }
 
 #if !defined(CUTTLEFISH_HOST)
     ackFrame(msg.get());
 #endif
 
-    std::lock_guard<std::mutex> autoLock(mRemotesLock);
-    for (auto &remoteEntry : mRemotes) {
-        // TODO(andih): Check which remotes to forward this packet to based
-        // on the destination address.
-        remoteEntry.second->send(msg.get(), msg->nlmsg_len);
-    }
 }
 
 int Mac80211HwSim::registerOrSubscribe(const MacAddress &mac) {
diff --git a/common/libs/wifi_relay/mac80211_hwsim.h b/common/commands/wifi_relay/mac80211_hwsim.h
similarity index 96%
rename from common/libs/wifi_relay/mac80211_hwsim.h
rename to common/commands/wifi_relay/mac80211_hwsim.h
index d9e4e0f..fb2fc99 100644
--- a/common/libs/wifi_relay/mac80211_hwsim.h
+++ b/common/commands/wifi_relay/mac80211_hwsim.h
@@ -82,9 +82,7 @@
     std::mutex mRemotesLock;
     std::map<MacAddress, std::unique_ptr<Remote>> mRemotes;
 
-    void injectMessage(nlmsghdr *hdr);
     void injectFrame(const void *data, size_t size);
     void ackFrame(nlmsghdr *msg);
-    void dumpMessage(nlmsghdr *msg) const;
     int registerOrSubscribe(const MacAddress &mac);
 };
diff --git a/common/libs/wifi_relay/mac80211_hwsim_driver.h b/common/commands/wifi_relay/mac80211_hwsim_driver.h
similarity index 100%
rename from common/libs/wifi_relay/mac80211_hwsim_driver.h
rename to common/commands/wifi_relay/mac80211_hwsim_driver.h
diff --git a/common/libs/wifi/netlink.h b/common/commands/wifi_relay/netlink.h
similarity index 100%
rename from common/libs/wifi/netlink.h
rename to common/commands/wifi_relay/netlink.h
diff --git a/common/libs/wifi/nl_client.cc b/common/commands/wifi_relay/nl_client.cpp
similarity index 97%
rename from common/libs/wifi/nl_client.cc
rename to common/commands/wifi_relay/nl_client.cpp
index 5588e3d..a00fab1 100644
--- a/common/libs/wifi/nl_client.cc
+++ b/common/commands/wifi_relay/nl_client.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "common/libs/wifi/nl_client.h"
+#include "common/commands/wifi_relay/nl_client.h"
 
 #include <glog/logging.h>
 
diff --git a/common/libs/wifi/nl_client.h b/common/commands/wifi_relay/nl_client.h
similarity index 97%
rename from common/libs/wifi/nl_client.h
rename to common/commands/wifi_relay/nl_client.h
index 2b5a57f..74bc122 100644
--- a/common/libs/wifi/nl_client.h
+++ b/common/commands/wifi_relay/nl_client.h
@@ -22,7 +22,7 @@
 
 #include <netlink/genl/genl.h>
 
-#include "common/libs/wifi/cmd.h"
+#include "common/commands/wifi_relay/cmd.h"
 
 namespace cvd {
 
diff --git a/common/commands/wifi_relay/wifi_relay.cpp b/common/commands/wifi_relay/wifi_relay.cpp
index b57d710..2b21765 100644
--- a/common/commands/wifi_relay/wifi_relay.cpp
+++ b/common/commands/wifi_relay/wifi_relay.cpp
@@ -16,8 +16,8 @@
 
 #include "wifi_relay.h"
 
-#include "common/libs/wifi_relay/mac80211_hwsim_driver.h"
-#include "common/libs/wifi/nl_client.h"
+#include "common/commands/wifi_relay/mac80211_hwsim_driver.h"
+#include "common/commands/wifi_relay/nl_client.h"
 
 #if defined(CUTTLEFISH_HOST)
 #include "host/libs/config/host_config.h"
@@ -229,6 +229,7 @@
 }
 
 int main(int argc, char **argv) {
+  ::android::base::InitLogging(argv, android::base::StderrLogger);
   gflags::ParseCommandLineFlags(&argc, &argv, true);
 
   auto wifi_view = vsoc::wifi::WifiExchangeView::GetInstance(
diff --git a/common/commands/wifi_relay/wifi_relay.h b/common/commands/wifi_relay/wifi_relay.h
index db94648..2edc6db 100644
--- a/common/commands/wifi_relay/wifi_relay.h
+++ b/common/commands/wifi_relay/wifi_relay.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "common/libs/wifi_relay/mac80211_hwsim.h"
+#include "common/commands/wifi_relay/mac80211_hwsim.h"
 
 #include <errno.h>
 #include <memory>
diff --git a/common/libs/Android.bp b/common/libs/Android.bp
index cb4ec3e..fff0a84 100644
--- a/common/libs/Android.bp
+++ b/common/libs/Android.bp
@@ -21,6 +21,4 @@
     "tcp_socket",
     "threads",
     "time",
-    "wifi",
-    "wifi_relay",
 ]
diff --git a/common/libs/wifi/Android.bp b/common/libs/wifi/Android.bp
deleted file mode 100644
index 3d24abe..0000000
--- a/common/libs/wifi/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// 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.
-
-cc_library_static {
-    name: "libcuttlefish_wifi",
-
-    srcs: [
-        "cmd.cc",
-        "netlink.cc",
-        "nl_client.cc",
-        "packet_switch.cc",
-        "virtual_wifi.cc",
-        "wr_client.cc",
-    ],
-    shared_libs: [
-        "vsoc_lib",
-        "libbase",
-        "libnl",
-    ],
-    header_libs: [
-        "cuttlefish_glog",
-    ],
-    target: {
-        host: {
-            static_libs: [
-                "libcuttlefish_host_config",
-                "libgflags",
-            ],
-        }
-    },
-    defaults: ["cuttlefish_host_and_guest", "cuttlefish_native_isa"]
-}
diff --git a/common/libs/wifi/mac80211.h b/common/libs/wifi/mac80211.h
deleted file mode 100644
index 6435bcb..0000000
--- a/common/libs/wifi/mac80211.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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))
-#ifndef __packed
-#define __packed __attribute__((packed))
-#endif
-
-#include <uapi/mac80211_hwsim.h>
-
-#undef __packed
-#undef BIT
-#undef u8
-#undef s8
diff --git a/common/libs/wifi/netlink.cc b/common/libs/wifi/netlink.cc
deleted file mode 100644
index 61c848b..0000000
--- a/common/libs/wifi/netlink.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 "common/libs/wifi/netlink.h"
-
-#include <glog/logging.h>
-#include <netlink/genl/ctrl.h>
-#include <netlink/genl/family.h>
-
-namespace cvd {
-namespace {
-constexpr char kWifiSimFamilyName[] = "MAC80211_HWSIM";
-constexpr char kNl80211FamilyName[] = "nl80211";
-}  // namespace
-
-Netlink::Netlink(const std::string& wifirouter_socket)
-    : genl_(NETLINK_GENERIC), rtnl_(NETLINK_ROUTE), wrcl_(wifirouter_socket) {}
-
-bool Netlink::Init() {
-  if (!genl_.Init()) {
-    LOG(ERROR) << "Could not open Netlink Generic.";
-    return false;
-  }
-
-  if (!rtnl_.Init()) {
-    LOG(ERROR) << "Could not open Netlink Route.";
-    return false;
-  }
-
-  if (!wrcl_.Init()) {
-    LOG(ERROR) << "Could not connect to Wifi Router.";
-    return false;
-  }
-
-  // Start the thread processing asynchronous netlink responses.
-  std::thread([this] { HandleNetlinkMessages(); }).detach();
-
-  // Query relevant netlink families:
-  // MAC80211 family allows us to create virtual radios and corresponding
-  // interfaces.
-  mac80211_hwsim_family_ = genl_ctrl_resolve(genl_.Sock(), kWifiSimFamilyName);
-  if (mac80211_hwsim_family_ < 0) {
-    LOG(ERROR) << "Could not find virtual wifi family. Please make sure module "
-               << "'mac80211_hwsim' is loaded on your system.";
-    return false;
-  }
-  LOG(INFO) << "MAC80211_HWSIM found with family id: "
-            << mac80211_hwsim_family_;
-
-  // NL80211 family allows us to find radios and corresponding interfaces.
-  nl80211_family_ = genl_ctrl_resolve(genl_.Sock(), kNl80211FamilyName);
-  if (nl80211_family_ < 0) {
-    LOG(ERROR) << "Could not find nl80211 family. WIFI stack is unavailable.";
-    return false;
-  }
-  LOG(INFO) << "NL80211 found with family id: " << nl80211_family_;
-
-  return true;
-}
-
-void Netlink::HandleNetlinkMessages() {
-  fd_set nlfds;
-  int genl_fd = nl_socket_get_fd(GeNL().Sock());
-  int rtnl_fd = nl_socket_get_fd(RtNL().Sock());
-  int wrcl_fd = wrcl_.Sock();
-
-  int max_fd = std::max({genl_fd, rtnl_fd, wrcl_fd}) + 1;
-  while (true) {
-    FD_ZERO(&nlfds);
-    FD_SET(genl_fd, &nlfds);
-    FD_SET(rtnl_fd, &nlfds);
-    FD_SET(wrcl_fd, &nlfds);
-
-    int res = select(max_fd, &nlfds, nullptr, nullptr, nullptr);
-    if (res <= 0) continue;
-
-    if (FD_ISSET(genl_fd, &nlfds)) nl_recvmsgs_default(GeNL().Sock());
-    if (FD_ISSET(rtnl_fd, &nlfds)) nl_recvmsgs_default(RtNL().Sock());
-    if (FD_ISSET(wrcl_fd, &nlfds)) wrcl_.HandleResponses();
-  }
-}
-
-}  // namespace cvd
diff --git a/common/libs/wifi/packet_switch.cc b/common/libs/wifi/packet_switch.cc
deleted file mode 100644
index 523611e..0000000
--- a/common/libs/wifi/packet_switch.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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 "common/libs/wifi/packet_switch.h"
-
-#include "common/libs/wifi/mac80211.h"
-#include "common/libs/wifi/router.h"
-
-#ifdef CUTTLEFISH_HOST
-#include "host/libs/config/host_config.h"
-#endif
-
-namespace cvd {
-
-PacketSwitch::~PacketSwitch() { Stop(); }
-
-bool PacketSwitch::Init() {
-#ifdef CUTTLEFISH_HOST
-  shm_wifi_ =
-      vsoc::wifi::WifiExchangeView::GetInstance(vsoc::GetDomain().c_str());
-#else
-  shm_wifi_ = vsoc::wifi::WifiExchangeView::GetInstance();
-#endif
-
-  if (shm_wifi_) {
-    worker_ = shm_wifi_->StartWorker();
-    return true;
-  }
-  return false;
-}
-
-void PacketSwitch::Start() {
-  std::lock_guard<std::mutex> l(op_mutex_);
-  if (started_) return;
-  // set started to true immediately; this attribute is referenced by threads to
-  // know whether they should terminate.
-  started_ = true;
-
-  nl_->WRCL().SetDefaultHandler(
-      [this](nl_msg* m) { ProcessPacket(m, false); });
-
-  shm_xchg_ = std::thread([this] {
-      size_t maxlen = getpagesize();
-      std::unique_ptr<uint8_t[]> msg(new uint8_t[maxlen]);
-      auto hdr = reinterpret_cast<nlmsghdr*>(msg.get());
-      std::unique_ptr<nl_msg, void (*)(nl_msg*)> nlm(nullptr, nlmsg_free);
-
-      while (started_) {
-#ifdef CUTTLEFISH_HOST
-      LOG(INFO) << "Awaiting packet.";
-#endif
-        shm_wifi_->Recv(msg.get(), maxlen);
-#ifdef CUTTLEFISH_HOST
-      LOG(INFO) << "Received packet.";
-#endif
-        nlm.reset(nlmsg_convert(hdr));
-        ProcessPacket(nlm.get(), true);
-      }
-    });
-}
-
-void PacketSwitch::Stop() {
-  std::lock_guard<std::mutex> l(op_mutex_);
-  if (!started_) return;
-  started_ = false;
-  nl_->WRCL().SetDefaultHandler(std::function<void(nl_msg*)>());
-
-  shm_xchg_.join();
-}
-
-void PacketSwitch::ProcessPacket(nl_msg* m, bool is_incoming) {
-  auto header = nlmsg_hdr(m);
-  auto genhdr = reinterpret_cast<genlmsghdr*>(nlmsg_data(header));
-
-  if (genhdr->cmd == WIFIROUTER_CMD_NOTIFY) {
-    // 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.
-      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);
-    }
-  }
-}
-
-}  // namespace cvd
diff --git a/common/libs/wifi/packet_switch.h b/common/libs/wifi/packet_switch.h
deleted file mode 100644
index 4edf720..0000000
--- a/common/libs/wifi/packet_switch.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 <memory>
-#include <set>
-
-#include "common/libs/wifi/netlink.h"
-#include "common/libs/wifi/virtual_wifi.h"
-#include "common/libs/wifi/wr_client.h"
-#include "common/vsoc/lib/wifi_exchange_view.h"
-
-namespace cvd {
-
-class PacketSwitch {
- public:
-  PacketSwitch(Netlink* nl) : nl_(nl) {}
-  ~PacketSwitch();
-
-  bool Init();
-  void Start();
-  void Stop();
-
- private:
-  void ProcessPacket(nl_msg* m, bool is_incoming);
-
-  Netlink* nl_;
-
-  std::mutex op_mutex_;
-  // Started is referenced by all threads created by PacketSwitch to determine
-  // whether to carry on working, or terminate.
-  bool started_ = false;
-
-  std::thread shm_xchg_;
-  std::unique_ptr<vsoc::RegionWorker> worker_;
-  vsoc::wifi::WifiExchangeView* shm_wifi_;
-
-  PacketSwitch(const PacketSwitch&) = delete;
-  PacketSwitch& operator=(const PacketSwitch&) = delete;
-};
-
-}  // namespace cvd
diff --git a/common/libs/wifi/router.h b/common/libs/wifi/router.h
deleted file mode 100644
index 237417d..0000000
--- a/common/libs/wifi/router.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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
-
-namespace cvd {
-// Commands recognized by WIFIRouter netlink family.
-enum {
-  // WIFIROUTER_CMD_REGISTER is used by client to request notifications for
-  // packets sent from an interface with specific MAC address. Recognized
-  // attributes:
-  // - WIFIROUTER_ATTR_HWSIM_ID - ID of HWSIM card to receive notifications for,
-  // - WIFIROUTER_ATTR_HWSIM_ADDR - MAC address (byte array) of interface to
-  //   receive notifications for.
-  WIFIROUTER_CMD_REGISTER,
-
-  // WIFIROUTER_CMD_NOTIFY is issued by the server to notify clients for every
-  // new WIFIROUTER packet the client is registered for. Comes with attributes:
-  // - WIFIROUTER_ATTR_HWSIM_ID - MAC address of interface that received packet,
-  // - WIFIROUTER_ATTR_PACKET - content of the MAC80211_HWSIM packet.
-  WIFIROUTER_CMD_NOTIFY,
-
-  // WIFIROUTER_RMD_SEND is issued by the client to request injection of a
-  // packet to all interfaces the client is registered for. Comes with
-  // attributes:
-  // - WIFIROUTER_ATTR_PACKET - content of the MAC80211_HWSIM packet.
-  WIFIROUTER_CMD_SEND,
-};
-
-// Attributes recognized by WIFIRouter netlink family.
-enum {
-  // Don't use attribute 0 to avoid parsing malformed message.
-  WIFIROUTER_ATTR_UNSPEC,
-
-  // MAC address representing interface from which the packet originated.
-  WIFIROUTER_ATTR_HWSIM_ID,
-
-  // Physical address of wireless interface.
-  WIFIROUTER_ATTR_HWSIM_ADDR,
-
-  // MAC80211_HWSIM packet content.
-  WIFIROUTER_ATTR_PACKET,
-
-  // Keep this last.
-  WIFIROUTER_ATTR_MAX
-};
-
-}  // namespace cvd
diff --git a/common/libs/wifi/virtual_wifi.cc b/common/libs/wifi/virtual_wifi.cc
deleted file mode 100644
index 468c26d..0000000
--- a/common/libs/wifi/virtual_wifi.cc
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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 "common/libs/wifi/virtual_wifi.h"
-
-#include <fstream>
-
-#include <glog/logging.h>
-#include <linux/if_ether.h>
-#include <linux/nl80211.h>
-#include <netlink/genl/ctrl.h>
-
-#include "common/libs/wifi/cmd.h"
-#include "common/libs/wifi/mac80211.h"
-#include "common/libs/wifi/router.h"
-
-namespace cvd {
-namespace {
-// Create new HWSIM Radio.
-// Returns newly created HWSIM radio number, or negative errno code.
-int CreateHWSIM(Netlink* nl, const std::string& wiphy_name) {
-  Cmd msg;
-
-  if (!genlmsg_put(msg.Msg(), NL_AUTO_PID, NL_AUTO_SEQ, nl->FamilyMAC80211(), 0,
-                   NLM_F_REQUEST, HWSIM_CMD_NEW_RADIO, kWifiSimVersion) ||
-      nla_put_string(msg.Msg(), HWSIM_ATTR_RADIO_NAME, wiphy_name.c_str()) ||
-      nla_put_flag(msg.Msg(), HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE)) {
-    LOG(ERROR) << "Could not create new radio request.";
-    return -1;
-  }
-
-  nl->GeNL().Send(&msg);
-
-  // Responses() pauses until netlink responds to previously sent message.
-  for (auto* r : msg.Responses()) {
-    auto hdr = nlmsg_hdr(r);
-    if (hdr->nlmsg_type == NLMSG_ERROR) {
-      nlmsgerr* err = static_cast<nlmsgerr*>(nlmsg_data(hdr));
-      return err->error;
-    }
-  }
-
-  LOG(ERROR) << "Unknown or no response from netlink.";
-  return -1;
-}
-
-// Destroy existing HWSIM Radio.
-int DeleteHWSIM(Netlink* nl, int hwsim_number) {
-  Cmd msg;
-
-  if (!genlmsg_put(msg.Msg(), NL_AUTO_PID, NL_AUTO_SEQ, nl->FamilyMAC80211(), 0,
-                   NLM_F_REQUEST, HWSIM_CMD_DEL_RADIO, kWifiSimVersion) ||
-      nla_put_u32(msg.Msg(), HWSIM_ATTR_RADIO_ID, hwsim_number)) {
-    LOG(ERROR) << "Could not create del radio request.";
-    return -1;
-  }
-
-  nl->GeNL().Send(&msg);
-
-  // Responses() pauses until netlink responds to previously sent message.
-  for (auto* r : msg.Responses()) {
-    auto hdr = nlmsg_hdr(r);
-    if (hdr->nlmsg_type == NLMSG_ERROR) {
-      nlmsgerr* err = static_cast<nlmsgerr*>(nlmsg_data(hdr));
-      return err->error;
-    }
-  }
-
-  LOG(ERROR) << "Unknown or no response from netlink.";
-  return -1;
-}
-
-// Get WIPHY index number associated with a specified name.
-// Note: WIPHY number is not the same as HWSIM number:
-// - the former identifies physical radio in the system,
-// - the latter identifies simulated radio in the system.
-// TODO(ender): we can get the interface number from sysfs, but
-// the information we receive from HWSIM is not enough to get the
-// wiphy # from the system directly. Update this when there is a better
-// way to acquire radio number.
-int GetWIPHYIndex(const std::string& wiphy_name) {
-  int number;
-  std::ifstream file("/sys/class/ieee80211/" + wiphy_name + "/index");
-  file >> number;
-  return number;
-}
-
-// Get WLAN interface index associated with specific WIPHY index.
-// Returns interface index (> 0) or negative value indicating errno code.
-int GetWiphyInterface(Netlink* nl, uint32_t wiphy_index) {
-  Cmd msg;
-
-  if (!genlmsg_put(msg.Msg(), NL_AUTO_PID, NL_AUTO_SEQ, nl->FamilyNL80211(), 0,
-                   NLM_F_REQUEST | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0)) {
-    LOG(ERROR) << "Could not create interface query.";
-    return -1;
-  }
-
-  nl->GeNL().Send(&msg);
-
-  // Responses() pauses until netlink responds to previously sent message.
-  for (auto* r : msg.Responses()) {
-    auto hdr = nlmsg_hdr(r);
-    if (hdr->nlmsg_type == NLMSG_ERROR) {
-      nlmsgerr* err = static_cast<nlmsgerr*>(nlmsg_data(hdr));
-      LOG(ERROR) << "Could not query wiphy: " << strerror(-err->error);
-      return err->error;
-    }
-
-    // Last message in entire series.
-    if (hdr->nlmsg_type == NLMSG_DONE) break;
-
-    // !DONE && !ERROR => content.
-    // Decode attributes supplied by netlink.
-    // the genlmsg_parse puts each attribute in a respective slot in an array,
-    // so we have to preallocate enough space.
-    struct nlattr* attrs[NL80211_ATTR_MAX + 1];
-    auto err = genlmsg_parse(hdr, 0, attrs, NL80211_ATTR_MAX, nullptr);
-
-    // Return error if response could not be parsed. This is actually quite
-    // serious.
-    if (err < 0) {
-      LOG(ERROR) << "Could not process netlink response: " << strerror(-err);
-      return err;
-    }
-
-    // Check if we have WIPHY attribute in response -- and if it's the relevant
-    // one.
-    auto wiphy = attrs[NL80211_ATTR_WIPHY];
-    if (wiphy != nullptr && nla_get_u32(wiphy) == wiphy_index) {
-      auto number = attrs[NL80211_ATTR_IFINDEX];
-
-      if (number != nullptr) {
-        return nla_get_u32(number);
-      }
-    }
-  }
-
-  LOG(INFO) << "No interfaces found for wiphy " << wiphy_index;
-  return -1;
-}
-
-// Set WLAN interface name.
-// Uses Netlink Route to alter interface attributes (currently: name).
-bool SetWLANInterface(Netlink* nl, int iface_index, const std::string& name,
-                      const uint8_t* address) {
-  Cmd msg;
-
-  ifinfomsg ifm{};
-  ifm.ifi_index = iface_index;
-
-  if (!nlmsg_put(msg.Msg(), NL_AUTO_PID, NL_AUTO_SEQ, RTM_SETLINK, 0,
-                 NLM_F_REQUEST) ||
-      nlmsg_append(msg.Msg(), &ifm, sizeof(ifm), 0) ||
-      nla_put_string(msg.Msg(), IFLA_IFNAME, name.c_str()) ||
-      nla_put(msg.Msg(), IFLA_ADDRESS, MAX_ADDR_LEN, address)) {
-    LOG(ERROR) << "Could not create interface update.";
-    return false;
-  }
-
-  nl->RtNL().Send(&msg);
-
-  // Responses() pauses until netlink responds to previously sent message.
-  for (auto* r : msg.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) << "Failed to update iface " << iface_index
-                   << ": " << strerror(-err->error);
-      }
-      return err->error == 0;
-    }
-  }
-
-  LOG(ERROR) << "Unknown or no response from netlink.";
-  return -1;
-}
-
-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(msg.Msg(), WIFIROUTER_ATTR_HWSIM_ADDR, ETH_ALEN, addr)) {
-    LOG(ERROR) << "Could not create wifirouter register message.";
-    return false;
-  }
-
-  nl->WRCL().Send(&msg);
-
-  // Responses() pauses until netlink responds to previously sent message.
-  for (auto* r : msg.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) << "Failed to register with wifi router: "
-                   << strerror(err->error);
-      }
-      return err->error == 0;
-    }
-  }
-
-  LOG(ERROR) << "Unknown or no response from wifi router.";
-  return -1;
-}
-
-}  // namespace
-
-VirtualWIFI::~VirtualWIFI() {
-  LOG(INFO) << "Deleting virtual wifi: " << hwsim_number_;
-  if (hwsim_number_ > 0) {
-    auto res = DeleteHWSIM(nl_, hwsim_number_);
-    if (res < 0) {
-      LOG(ERROR) << "Could not delete radio: " << strerror(-res);
-    }
-    hwsim_number_ = 0;
-  }
-  LOG(INFO) << "Done.";
-}
-
-bool VirtualWIFI::Init() {
-  // Dummy variable is used with sscanf to determine mac address is well formed
-  // (that is: there's no trailing string content).
-  char dummy;
-
-  if (sscanf(addr_.c_str(), "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx%c",
-             &mac_addr_[0], &mac_addr_[1], &mac_addr_[2], &mac_addr_[3],
-             &mac_addr_[4], &mac_addr_[5], &dummy) != 6) {
-    LOG(ERROR) << "Malformed MAC address: " << addr_;
-    return false;
-  }
-
-  std::string phy = name_ + "phy";
-  // Each WLAN device consists of two sides:
-  // - WIPHY is the "radio" side,
-  // - WLAN is the "interface" side.
-  // Radios have more physical properties, while WLAN have more logical /
-  // interface properties. Each radio can have more than one WLAN.
-
-  // 1. Create new MAC80211 HWSIM radio.
-  LOG(INFO) << "Creating virtual radio: " << phy;
-  hwsim_number_ = CreateHWSIM(nl_, phy);
-  if (hwsim_number_ <= 0) {
-    LOG(ERROR) << "Could not create HWSIM: " << strerror(-hwsim_number_);
-    return false;
-  }
-
-  // 2. Acquire the WIPHY radio number created with HWSIM radio.
-  LOG(INFO) << "Querying WIPHY number for: " << phy;
-  wiphy_number_ = GetWIPHYIndex(phy);
-  if (wiphy_number_ <= 0) {
-    LOG(ERROR) << "Could not create WIPHY.";
-    return false;
-  }
-
-  // 3. Query interface index.
-  LOG(INFO) << "Querying WIFI number for: " << wiphy_number_;
-  iface_number_ = GetWiphyInterface(nl_, wiphy_number_);
-  if (iface_number_ <= 0) {
-    LOG(ERROR) << "Could not query interface details.";
-    return false;
-  }
-
-  // 4. Apply requested interface name.
-  LOG(INFO) << "Updating interface name to: " << name_;
-  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_, mac_addr_)) {
-    LOG(ERROR) << "Could not register with wifi router.";
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace cvd
diff --git a/common/libs/wifi/virtual_wifi.h b/common/libs/wifi/virtual_wifi.h
deleted file mode 100644
index fac70e0..0000000
--- a/common/libs/wifi/virtual_wifi.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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 <memory>
-#include <string>
-
-#include <netinet/in.h>
-#include <linux/netdevice.h>
-
-#include "common/libs/wifi/netlink.h"
-
-namespace cvd {
-
-// VirtualWIFI is an abstraction of an (individual) virtual WLAN device.
-// A virtual WLAN is a composition of the three elements:
-// - HWSIM RADIO, or an instance of a virtual MAC80211 device; this instance is
-//   later used to determine origin of the 802.11 frames (ie. which virtual
-//   interface was used to send them),
-// - WIPHY, or Radio that is recognized by Linux kernel; these instances are
-//   *named* representations of the HWSIM radios and can be used to identify
-//   associated WLAN interface,
-// - WLAN, or WIFI Interface, which is directly used network stack and tools.
-//
-// Typically, Cuttlefish guests will run with just one VirtualWIFI instance, but
-// the host will need (typically) one per Guest instance. This is dictated by
-// the fact that at most one user-space daemon can listen for MAC80211 packets
-// at any given time.
-class VirtualWIFI {
- public:
-  VirtualWIFI(Netlink* nl, const std::string& name, const std::string& macaddr)
-      : nl_(nl), name_(name), addr_(macaddr) {}
-  ~VirtualWIFI();
-
-  const uint8_t* MacAddr() const { return &mac_addr_[0]; }
-  const std::string& Name() const { return name_; }
-
-  bool Init();
-
- private:
-  Netlink* nl_;
-  std::string name_;
-
-  // MAC address associated with primary WLAN interface.
-  // This is the only way to identify origin of the packets.
-  // Sadly, if MAC Address is altered manually at runtime, we
-  // will stop working.
-  std::string addr_;
-
-  // NOTE: this has to be MAX_ADDR_LEN, even if we occupy fewer bytes.
-  // Netlink requires this to be full length.
-  uint8_t mac_addr_[MAX_ADDR_LEN];
-
-  // HWSIM number is required to identify HWSIM device that we want destroyed
-  // when we no longer need it.
-  int hwsim_number_ = 0;
-
-  // WIPHY and WIFI interface numbers. Useful for local operations, such as
-  // renaming interface.
-  int wiphy_number_ = 0;
-  int iface_number_ = 0;
-
-  VirtualWIFI(const VirtualWIFI&) = delete;
-  VirtualWIFI& operator=(const VirtualWIFI&) = delete;
-};
-
-}  // namespace cvd
diff --git a/common/libs/wifi/wr_client.cc b/common/libs/wifi/wr_client.cc
deleted file mode 100644
index 7b342b0..0000000
--- a/common/libs/wifi/wr_client.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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 "common/libs/wifi/wr_client.h"
-
-#include <glog/logging.h>
-
-namespace cvd {
-namespace {
-const int kMaxSupportedPacketSize = getpagesize();
-}  // namespace
-WRClient::WRClient(const std::string& address) : address_(address) {}
-
-bool WRClient::Init() {
-  // Sadly, we can't use SharedFD, because we need access to raw file
-  // descriptor.
-
-  struct sockaddr_un addr {};
-  addr.sun_family = AF_UNIX;
-  memcpy(addr.sun_path + 1, address_.c_str(), address_.size());
-  socklen_t len = offsetof(struct sockaddr_un, sun_path) + address_.size() + 1;
-  socket_ = socket(AF_UNIX, SOCK_SEQPACKET, 0);
-  if (socket_ < 0) {
-    LOG(ERROR) << "socket() failed: " << strerror(errno);
-    return false;
-  }
-
-  auto res = connect(socket_, reinterpret_cast<sockaddr*>(&addr), len);
-  if (res < 0) {
-    LOG(ERROR) << "Could not connect to wifi router: " << strerror(errno);
-    return false;
-  }
-
-  return true;
-}
-
-void WRClient::Send(Cmd* msg) {
-  std::lock_guard<std::mutex> guard(in_flight_mutex_);
-  // Make sure to execute this while in critical section to ensure we have time
-  // to set up seq number & callback before we receive response.
-  auto hdr = nlmsg_hdr(msg->Msg());
-  int seq = in_flight_last_seq_++;
-  // Do not use 0 for sequence numbers. 0 is reserved for async notifications.
-  if (!in_flight_last_seq_) in_flight_last_seq_ = 1;
-
-  hdr->nlmsg_seq = seq;
-  send(socket_, hdr, hdr->nlmsg_len, MSG_NOSIGNAL);
-  in_flight_[seq] = msg;
-}
-
-// Handle asynchronous messages & responses from netlink.
-void WRClient::HandleResponses() {
-  std::unique_ptr<uint8_t[]> buf(new uint8_t[kMaxSupportedPacketSize]);
-
-  auto size = recv(socket_, buf.get(), kMaxSupportedPacketSize, 0);
-  if (size <= 0) {
-    LOG(FATAL) << "No data from WIFI Router - likely dead: " << strerror(errno);
-    return;
-  }
-
-  auto hdr = reinterpret_cast<nlmsghdr*>(buf.get());
-  if (static_cast<uint32_t>(size) != hdr->nlmsg_len) {
-    LOG(FATAL) << "Malformed message from WIFI Router.";
-    return;
-  }
-
-  int seq = hdr->nlmsg_seq;
-  std::unique_ptr<nl_msg, void (*)(nl_msg*)> nlmsg(
-      nlmsg_convert(hdr), [](nl_msg* m) { nlmsg_free(m); });
-
-  // Find & invoke corresponding callback, if any.
-  std::lock_guard<std::mutex> guard(in_flight_mutex_);
-  auto pos = in_flight_.find(seq);
-  if (pos != in_flight_.end()) {
-    if (pos->second->OnResponse(nlmsg.get())) {
-      // Erase command if reports it's done.
-      in_flight_.erase(seq);
-    }
-  } else if (default_handler_) {
-    default_handler_(nlmsg.get());
-  }
-}
-
-void WRClient::SetDefaultHandler(std::function<void(nl_msg*)> cb) {
-  std::lock_guard<std::mutex> guard(in_flight_mutex_);
-  default_handler_ = std::move(cb);
-}
-
-int WRClient::Sock() const { return socket_; }
-
-}  // namespace cvd
diff --git a/common/libs/wifi/wr_client.h b/common/libs/wifi/wr_client.h
deleted file mode 100644
index 71a6438..0000000
--- a/common/libs/wifi/wr_client.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 <functional>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <string>
-
-#include <netlink/msg.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/wifi/cmd.h"
-
-namespace cvd {
-
-class WRClient {
- public:
-  WRClient(const std::string& socket_address);
-  ~WRClient() = default;
-
-  // Init this client: open socket to wifi router.
-  bool Init();
-
-  // Get wifirouter socket used for sending and receiving messages.
-  int Sock() const;
-
-  // Send message to wifi router.
-  void Send(Cmd* msg);
-
-  // Handle incoming responses from wifi router.
-  void HandleResponses();
-
-  // Set callback receiving all asynchronous messages and responses that do not
-  // have any proper recipient.
-  void SetDefaultHandler(std::function<void(nl_msg*)> cb);
-
- private:
-  // Receive & dispatch netlink response.
-
-  std::string address_;
-  int socket_ = 0;
-  std::mutex in_flight_mutex_;
-  // Do not use 0 as a sequence number. 0 is reserved for asynchronous
-  // notifications.
-  int in_flight_last_seq_ = 1;
-  std::map<uint32_t, Cmd*> in_flight_;
-  std::function<void(nl_msg*)> default_handler_;
-
-  WRClient(const WRClient&) = delete;
-  WRClient& operator=(const WRClient&) = delete;
-};
-
-}  // namespace cvd
diff --git a/common/libs/wifi_relay/Android.bp b/common/libs/wifi_relay/Android.bp
deleted file mode 100644
index c527134..0000000
--- a/common/libs/wifi_relay/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (C) 2018 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.
-
-cc_library_static {
-    name: "libcuttlefish_wifi_relay",
-
-    srcs: [
-        "mac80211_hwsim.cpp",
-    ],
-    shared_libs: [
-        "libbase",
-        "libnl",
-        "vsoc_lib",
-    ],
-    header_libs: [
-        "cuttlefish_glog",
-    ],
-    target: {
-        host: {
-            static_libs: [
-                "libcuttlefish_host_config",
-                "libgflags",
-            ],
-        }
-    },
-    defaults: ["cuttlefish_host_and_guest", "cuttlefish_native_isa"]
-}
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index ab3bad2..e9789b8 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -35,7 +35,6 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
-        "libcuttlefish_wifi_relay",
         "libivserver",
         "libvadb",
         "libusbip",