google-usb-dyamic: support setting host MAC from BMC

This adds a MacIdx field from EM that indexing the MAC list reversely,
and set it as the host MAC.

Tested: On a machine the host MAC address is correctly set.

Fusion-Link: https://fusion2.corp.google.com/10b38e56-a8f0-3b09-8e81-5f2a3654fc4
Google-Bug-Id: 392923910
Change-Id: I8eaba4b32a7fc280d2151b1120e458f8e160b874
Signed-off-by: Yuxiao Zhang <yuxiaozhang@google.com>
diff --git a/recipes-google/networking/google-usb-network/google-usb-dynamic.cpp b/recipes-google/networking/google-usb-network/google-usb-dynamic.cpp
index 8730e95..f99ddff 100644
--- a/recipes-google/networking/google-usb-network/google-usb-dynamic.cpp
+++ b/recipes-google/networking/google-usb-network/google-usb-dynamic.cpp
@@ -20,6 +20,10 @@
 #include <sdeventplus/event.hpp>
 #include <sdeventplus/source/signal.hpp>
 #include <stdplus/signal.hpp>
+#include <stdplus/fd/create.hpp>
+#include <stdplus/fd/managed.hpp>
+#include <stdplus/fd/ops.hpp>
+#include <stdplus/fd/line.hpp>
 
 #include <memory>
 #include <span>
@@ -35,6 +39,7 @@
 {
 
 constexpr char kInterface[] = "com.google.gbmc.USB";
+constexpr char kMacPath[] = "/run/gbmc-mac-config/gbmc-mac-list";
 
 using sdeventplus::source::Signal;
 using USBProps =
@@ -69,6 +74,18 @@
     exit(execv("/usr/bin/usb_network.sh", cptr.data()));
 }
 
+std::string getMacFromIdx(int idx)
+{
+    auto fd = stdplus::fd::open(kMacPath, stdplus::fd::OpenAccess::ReadOnly);
+    stdplus::fd::LineReader reader(fd);
+    for (; idx > 0; idx--)
+    {
+      reader.readLine();
+    }
+    return *reader.readLine();
+}
+
+
 class DeviceManager
 {
   public:
@@ -92,6 +109,7 @@
 
     void addDev(const char* obj, USBProps& props);
     void readDev(const char* svc, const char* obj, const char* intf);
+    void processMacIdx(USBProps& props);
 };
 
 DeviceManager::~DeviceManager()
@@ -113,6 +131,27 @@
     }
 }
 
+void DeviceManager::processMacIdx(USBProps& props)
+{
+    auto it = props.find("MacIdx");
+    if (it != props.end())
+    {
+        try
+        {
+            int idx = std::get<uint64_t>(it->second);
+            // Add/overwrite the host mac value
+            props["HostMac"] = getMacFromIdx(idx);;
+            fmt::print(stderr, "Generated MACAddress {} from MacIdx {}\n",
+                       std::get<std::string>(props["HostMac"]), idx);
+        }
+        catch (const std::exception& e)
+        {
+            fmt::print(stderr, "MacIdx detected but failed to set MAC: {}\n",
+                       e.what());
+        }
+    }
+}
+
 template <typename>
 inline constexpr bool always_false_v = false;
 
@@ -171,6 +210,8 @@
                 fmt::format("Obj {} missing param {}", obj, key));
         }
     };
+    processMacIdx(props);
+
     add("--product-id", "ProductId", /*required=*/true);
     add("--bind-device", "BindDevice", /*required=*/true);
     add("--product-name", "ProductName", /*required=*/false);
diff --git a/recipes-google/networking/google-usb-network/google-usb-dynamic.service b/recipes-google/networking/google-usb-network/google-usb-dynamic.service
index 9f45572..7e650e9 100644
--- a/recipes-google/networking/google-usb-network/google-usb-dynamic.service
+++ b/recipes-google/networking/google-usb-network/google-usb-dynamic.service
@@ -1,6 +1,6 @@
 [Unit]
-Wants=xyz.openbmc_project.ObjectMapper.service
-After=xyz.openbmc_project.ObjectMapper.service
+Wants=xyz.openbmc_project.ObjectMapper.service gbmc-mac-config.service
+After=xyz.openbmc_project.ObjectMapper.service gbmc-mac-config.service
 StartLimitIntervalSec=180
 StartLimitBurst=10