Makes wifi configurable over shared memory

Passes the mac addresses of host and guest devices through the wifi
exchange region.
Changes MacAddress type to std::array to make its size known at
compile time and moves it to the region view.

Test: run on gce
Bug: 76433498
Change-Id: Ie964a22424f0ff5004d32efcdf487894b8083c62
diff --git a/common/commands/wifi_relay/wifi_relay.cpp b/common/commands/wifi_relay/wifi_relay.cpp
index 1af95d9..27fede1 100644
--- a/common/commands/wifi_relay/wifi_relay.cpp
+++ b/common/commands/wifi_relay/wifi_relay.cpp
@@ -33,16 +33,6 @@
 
 #include <fstream>
 
-DEFINE_string(
-        guest_mac_address,
-        "00:43:56:44:80:02",
-        "MAC address of the wifi interface to be created on the guest.");
-
-DEFINE_string(
-        host_mac_address,
-        "42:00:00:00:00:00",
-        "MAC address of the wifi interface running on the host.");
-
 #if !defined(CUTTLEFISH_HOST)
 DEFINE_string(
         iface_name, "wlan0", "Name of the wifi interface to be created.");
@@ -241,11 +231,14 @@
 int main(int argc, char **argv) {
   gflags::ParseCommandLineFlags(&argc, &argv, true);
 
-  Mac80211HwSim::MacAddress guestMAC, hostMAC;
-  if (!Mac80211HwSim::ParseMACAddress(FLAGS_guest_mac_address, &guestMAC)
-          || !Mac80211HwSim::ParseMACAddress(FLAGS_host_mac_address, &hostMAC)) {
-      exit(1);
-  }
+  auto wifi_view = vsoc::wifi::WifiExchangeView::GetInstance(
+#if defined(CUTTLEFISH_HOST)
+      vsoc::GetDomain().c_str()
+#endif
+  );
+
+  Mac80211HwSim::MacAddress guestMAC = wifi_view->GetGuestMACAddress();
+  Mac80211HwSim::MacAddress hostMAC = wifi_view->GetHostMACAddress();
 
 #ifdef CUTTLEFISH_HOST
   WifiRelay relay(hostMAC, guestMAC);
diff --git a/common/commands/wifi_relay/wifi_relay.h b/common/commands/wifi_relay/wifi_relay.h
index 98dce3a..db94648 100644
--- a/common/commands/wifi_relay/wifi_relay.h
+++ b/common/commands/wifi_relay/wifi_relay.h
@@ -44,4 +44,3 @@
 
   std::unique_ptr<Mac80211HwSim> mMac80211HwSim;
 };
-
diff --git a/common/libs/wifi_relay/mac80211_hwsim.cpp b/common/libs/wifi_relay/mac80211_hwsim.cpp
index c08fcc9..2fc9c70 100644
--- a/common/libs/wifi_relay/mac80211_hwsim.cpp
+++ b/common/libs/wifi_relay/mac80211_hwsim.cpp
@@ -22,7 +22,6 @@
 #include <netlink/genl/ctrl.h>
 #include <netlink/genl/genl.h>
 #include <signal.h>
-#include <string>
 
 static constexpr char kWifiSimFamilyName[] = "MAC80211_HWSIM";
 static constexpr char kNl80211FamilyName[] = "nl80211";
@@ -419,24 +418,3 @@
         mRemotes.erase(it);
     }
 }
-
-// static
-bool Mac80211HwSim::ParseMACAddress(const std::string &s, MacAddress *mac) {
-    mac->resize(ETH_ALEN);
-
-    char dummy;
-    if (sscanf(s.c_str(),
-               "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx%c",
-               &(*mac)[0],
-               &(*mac)[1],
-               &(*mac)[2],
-               &(*mac)[3],
-               &(*mac)[4],
-               &(*mac)[5],
-               &dummy) != 6) {
-        LOG(ERROR) << "Failed to parse MAC address: " << s;
-        return false;
-    }
-
-    return true;
-}
diff --git a/common/libs/wifi_relay/mac80211_hwsim.h b/common/libs/wifi_relay/mac80211_hwsim.h
index 43f94fe..d0801d2 100644
--- a/common/libs/wifi_relay/mac80211_hwsim.h
+++ b/common/libs/wifi_relay/mac80211_hwsim.h
@@ -24,10 +24,9 @@
 #include <memory>
 #include <mutex>
 #include <netlink/netlink.h>
-#include <vector>
 
 struct Mac80211HwSim {
-    using MacAddress = std::vector<uint8_t>;
+    using MacAddress = vsoc::wifi::WifiExchangeView::MacAddress;
 
     static constexpr size_t kMessageSizeMax = 128 * 1024;
 
@@ -52,8 +51,6 @@
 
     void removeRemote(const MacAddress &mac);
 
-    static bool ParseMACAddress(const std::string &s, MacAddress *mac);
-
 private:
     struct Remote {
         explicit Remote(
diff --git a/common/vsoc/lib/wifi_exchange_view.cpp b/common/vsoc/lib/wifi_exchange_view.cpp
index 1cb3bf9..23dcd09 100644
--- a/common/vsoc/lib/wifi_exchange_view.cpp
+++ b/common/vsoc/lib/wifi_exchange_view.cpp
@@ -15,6 +15,9 @@
  */
 #include "common/vsoc/lib/wifi_exchange_view.h"
 
+#include <algorithm>
+#include <string>
+
 #include <linux/if_ether.h>
 #include "common/vsoc/lib/circqueue_impl.h"
 
@@ -41,12 +44,74 @@
 #endif
 }
 
-void WifiExchangeView::SetGuestMACAddress(const uint8_t* mac_address) {
-  memcpy(data()->mac_address, mac_address, ETH_ALEN);
+void WifiExchangeView::SetGuestMACAddress(
+    const WifiExchangeView::MacAddress& mac_address) {
+  std::copy(std::begin(mac_address),
+            std::end(mac_address),
+            std::begin(data()->guest_mac_address));
 }
 
-void WifiExchangeView::GetGuestMACAddress(uint8_t* mac_address) {
-  memcpy(mac_address, data()->mac_address, ETH_ALEN);
+WifiExchangeView::MacAddress WifiExchangeView::GetGuestMACAddress() {
+  WifiExchangeView::MacAddress ret;
+  std::copy(std::begin(data()->guest_mac_address),
+            std::end(data()->guest_mac_address),
+            std::begin(ret));
+  return ret;
+}
+
+void WifiExchangeView::SetHostMACAddress(
+    const WifiExchangeView::MacAddress& mac_address) {
+  std::copy(std::begin(mac_address),
+            std::end(mac_address),
+            std::begin(data()->host_mac_address));
+}
+
+WifiExchangeView::MacAddress WifiExchangeView::GetHostMACAddress() {
+  WifiExchangeView::MacAddress ret;
+  std::copy(std::begin(data()->host_mac_address),
+            std::end(data()->host_mac_address),
+            std::begin(ret));
+  return ret;
+}
+
+// static
+bool WifiExchangeView::ParseMACAddress(const std::string& s,
+                                       WifiExchangeView::MacAddress* mac) {
+  char dummy;
+  // This is likely to always be true, but better safe than sorry
+  static_assert(std::tuple_size<WifiExchangeView::MacAddress>::value == 6,
+                "Mac address size has changed");
+  if (sscanf(s.c_str(),
+             "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx%c",
+             &(*mac)[0],
+             &(*mac)[1],
+             &(*mac)[2],
+             &(*mac)[3],
+             &(*mac)[4],
+             &(*mac)[5],
+             &dummy) != 6) {
+    return false;
+  }
+  return true;
+}
+
+// static
+std::string WifiExchangeView::MacAddressToString(
+    const WifiExchangeView::MacAddress& mac) {
+  char buffer[3 * mac.size()];
+  // This is likely to always be true, but better safe than sorry
+  static_assert(std::tuple_size<WifiExchangeView::MacAddress>::value == 6,
+                "Mac address size has changed");
+  snprintf(buffer,
+           sizeof(buffer),
+           "%02x:%02x:%02x:%02x:%02x:%02x",
+           mac[0],
+           mac[1],
+           mac[2],
+           mac[3],
+           mac[4],
+           mac[5]);
+  return std::string(buffer);
 }
 
 }  // namespace wifi
diff --git a/common/vsoc/lib/wifi_exchange_view.h b/common/vsoc/lib/wifi_exchange_view.h
index ad0d968..5230a8e 100644
--- a/common/vsoc/lib/wifi_exchange_view.h
+++ b/common/vsoc/lib/wifi_exchange_view.h
@@ -15,6 +15,7 @@
  */
 #pragma once
 
+#include <array>
 #include <memory>
 
 #include "common/vsoc/lib/typed_region_view.h"
@@ -29,6 +30,10 @@
         WifiExchangeView,
         vsoc::layout::wifi::WifiExchangeLayout> {
  public:
+  using MacAddress = std::array<
+      uint8_t,
+      sizeof(vsoc::layout::wifi::WifiExchangeLayout::guest_mac_address)>;
+
   // Send netlink packet to peer.
   // returns true, if operation was successful.
   intptr_t Send(const void* buffer, intptr_t length);
@@ -38,11 +43,18 @@
   intptr_t Recv(void* buffer, intptr_t max_length);
 
   // Set guest MAC address.
-  void SetGuestMACAddress(const uint8_t* mac_address);
-  void GetGuestMACAddress(uint8_t* mac_address);
+  void SetGuestMACAddress(const MacAddress& mac_address);
+  MacAddress GetGuestMACAddress();
+
+  // Set host MAC address.
+  void SetHostMACAddress(const MacAddress& mac_address);
+  MacAddress GetHostMACAddress();
 
   void SetConfigReady();
   void WaitConfigReady();
+
+  static bool ParseMACAddress(const std::string &s, MacAddress *mac);
+  static std::string MacAddressToString(const MacAddress& mac);
 };
 
 }  // namespace wifi
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index 4948de4..0efae81 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -126,14 +126,13 @@
 // Versioning information for wifi_layout.h
 namespace wifi {
 namespace {
-constexpr uint32_t version = 0;
+constexpr uint32_t version = 1;
 }  // namespace
 constexpr size_t WifiExchangeLayout_size =
     65548 + // sizeof(CircularPacketQueue<16, 8192>) - forward
     65548 + // sizeof(CircularPacketQueue<16, 8192>) - reverse
-    4 +     // Lock config_lock_
-    2 +     // bool config_ready_ (and even address alignment)
-    6;      // uint8_t[6] MAC address.
+    6 +     // uint8_t[6] MAC address.
+    6;     // uint8_t[6] MAC address.
 }  // namespace wifi
 
 // Versioning information for ril_layout.h
diff --git a/common/vsoc/shm/wifi_exchange_layout.h b/common/vsoc/shm/wifi_exchange_layout.h
index 2ca957c..93f1a9e 100644
--- a/common/vsoc/shm/wifi_exchange_layout.h
+++ b/common/vsoc/shm/wifi_exchange_layout.h
@@ -31,12 +31,10 @@
   // Traffic originating from guest that proceeds towards host.
   CircularPacketQueue<16, 8192> guest_egress;
 
-  // config_lock_ manages access to configuration section
-  SpinLock config_lock_;
-  // config_ready_ indicates whether config section is ready to be accessed.
-  bool config_ready_;
   // Desired MAC address for guest device.
-  uint8_t mac_address[6];
+  uint8_t guest_mac_address[6];
+  // MAC address of host device.
+  uint8_t host_mac_address[6];
 
   static const char* region_name;
 };
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index 420df07..c6b2163 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -4,6 +4,7 @@
         "main.cc",
         "screen_region_handler.cc",
         "ril_region_handler.cc",
+        "wifi_region_handler.cc",
     ],
     header_libs: [
         "cuttlefish_glog",
@@ -14,9 +15,11 @@
         "cuttlefish_auto_resources",
         "libicuuc",
         "libbase",
+        "libnl"
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libcuttlefish_wifi_relay",
         "libivserver",
         "libvadb",
         "libusbip",
diff --git a/host/commands/launch/pre_launch_initializers.h b/host/commands/launch/pre_launch_initializers.h
index 0d3746d..d5f44ed 100644
--- a/host/commands/launch/pre_launch_initializers.h
+++ b/host/commands/launch/pre_launch_initializers.h
@@ -22,11 +22,13 @@
 // source file and call from PreLaunchInitializers::Initialize().
 void InitializeScreenRegion();
 void InitializeRilRegion();
+void InitializeWifiRegion();
 
 class PreLaunchInitializers {
  public:
   static void Initialize() {
     InitializeScreenRegion();
     InitializeRilRegion();
+    InitializeWifiRegion();
   }
 };
diff --git a/host/commands/launch/screen_region_handler.cc b/host/commands/launch/screen_region_handler.cc
index 9ad0f50..5844537 100644
--- a/host/commands/launch/screen_region_handler.cc
+++ b/host/commands/launch/screen_region_handler.cc
@@ -30,7 +30,7 @@
   auto region =
       vsoc::screen::ScreenRegionView::GetInstance(vsoc::GetDomain().c_str());
   if (!region) {
-    LOG(INFO) << "Framebuffer region was not found";
+    LOG(ERROR) << "Framebuffer region was not found";
     return;
   }
   auto dest = region->data();
diff --git a/host/commands/launch/wifi_region_handler.cc b/host/commands/launch/wifi_region_handler.cc
new file mode 100644
index 0000000..7f82c6a
--- /dev/null
+++ b/host/commands/launch/wifi_region_handler.cc
@@ -0,0 +1,73 @@
+/*
+ * 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 <cassert>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+#include "common/vsoc/lib/wifi_exchange_view.h"
+#include "host/commands/launch/pre_launch_initializers.h"
+#include "host/libs/config/host_config.h"
+
+using vsoc::wifi::WifiExchangeView;
+
+namespace {
+
+std::string GetPerInstanceDefaultMacAddress(const char* base_mac) {
+  WifiExchangeView::MacAddress addr;
+  if (!WifiExchangeView::ParseMACAddress(base_mac, &addr)) {
+    LOG(FATAL) << "Unable to parse MAC address: " << base_mac;
+    return "";
+  }
+  // Modify the last byte of the mac address to make it different for every cvd
+  addr.back() = static_cast<uint8_t>(vsoc::GetPerInstanceDefault(addr.back()));
+  return WifiExchangeView::MacAddressToString(addr);
+}
+
+}  // namespace
+
+DEFINE_string(guest_mac_address,
+              GetPerInstanceDefaultMacAddress("00:43:56:44:80:01"),
+              "MAC address of the wifi interface to be created on the guest.");
+
+DEFINE_string(host_mac_address,
+              "42:00:00:00:00:00",
+              "MAC address of the wifi interface running on the host.");
+
+void InitializeWifiRegion() {
+  auto region = WifiExchangeView::GetInstance(vsoc::GetDomain().c_str());
+  if (!region) {
+    LOG(FATAL) << "Wifi region not found";
+    return;
+  }
+  WifiExchangeView::MacAddress guest_mac, host_mac;
+  if (!WifiExchangeView::ParseMACAddress(FLAGS_guest_mac_address, &guest_mac)) {
+    LOG(FATAL) << "Unable to parse guest mac address: "
+               << FLAGS_guest_mac_address;
+    return;
+  }
+  LOG(INFO) << "Setting guest mac to " << FLAGS_guest_mac_address;
+  region->SetGuestMACAddress(guest_mac);
+  if (!WifiExchangeView::ParseMACAddress(FLAGS_host_mac_address, &host_mac)) {
+    LOG(FATAL) << "Unable to parse guest mac address: "
+               << FLAGS_guest_mac_address;
+    return;
+  }
+  LOG(INFO) << "Setting host mac to " << FLAGS_host_mac_address;
+  region->SetHostMACAddress(host_mac);
+}