system_queries: Get Interface Info from netlink

This reduces all of the interface information probing down to a single
netlink request for all the label + mac information needed to build an
ethernet interface.

If we ever plumb the ethernet stats into dbus, we can get that
information with this same netlink code.

Change-Id: Ied8a73639dcd74bcfecda392905638573ab7970f
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 09fd9dd..021c126 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -12,6 +12,7 @@
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
 #include <linux/rtnetlink.h>
+#include <net/if.h>
 
 #include <algorithm>
 #include <filesystem>
@@ -64,15 +65,6 @@
     return fallback;
 }
 
-InterfaceInfo getInterfaceInfo(stdplus::zstring_view ifname)
-{
-    return InterfaceInfo{.running = system::intfIsRunning(ifname),
-                         .index = system::intfIndex(ifname),
-                         .name = std::string(ifname),
-                         .mac = system::getMAC(ifname),
-                         .mtu = system::getMTU(ifname)};
-}
-
 static std::string makeObjPath(std::string_view root, std::string_view intf)
 {
     auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
@@ -81,18 +73,18 @@
 }
 
 EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
-                                     const InterfaceInfo& info,
+                                     const system::InterfaceInfo& info,
                                      std::string_view objRoot,
                                      const config::Parser& config,
                                      bool emitSignal,
                                      std::optional<bool> enabled) :
-    EthernetInterface(bus, manager, info, makeObjPath(objRoot, info.name),
+    EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
                       config, emitSignal, enabled)
 {
 }
 
 EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
-                                     const InterfaceInfo& info,
+                                     const system::InterfaceInfo& info,
                                      std::string&& objPath,
                                      const config::Parser& config,
                                      bool emitSignal,
@@ -100,9 +92,9 @@
     Ifaces(bus, objPath.c_str(),
            emitSignal ? Ifaces::action::defer_emit
                       : Ifaces::action::emit_no_signals),
-    bus(bus), manager(manager), objPath(std::move(objPath)), ifIdx(info.index)
+    bus(bus), manager(manager), objPath(std::move(objPath)), ifIdx(info.idx)
 {
-    interfaceName(info.name);
+    interfaceName(*info.name);
     auto dhcpVal = getDHCPValue(config);
     EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
     EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
@@ -115,7 +107,7 @@
 
     for (const auto& gateway : gatewayList)
     {
-        if (gateway.first == info.name)
+        if (gateway.first == *info.name)
         {
             defaultGateway = gateway.second;
             break;
@@ -124,7 +116,7 @@
 
     for (const auto& gateway6 : gateway6List)
     {
-        if (gateway6.first == info.name)
+        if (gateway6.first == *info.name)
         {
             defaultGateway6 = gateway6.second;
             break;
@@ -138,8 +130,8 @@
 
     if (ifIdx > 0)
     {
-        auto ethInfo = ignoreError("GetEthInfo", info.name, {}, [&] {
-            return system::getEthInfo(info.name);
+        auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
+            return system::getEthInfo(*info.name);
         });
         EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
         EthernetInterfaceIntf::speed(ethInfo.speed);
@@ -154,9 +146,9 @@
     }
 }
 
-void EthernetInterface::updateInfo(const InterfaceInfo& info)
+void EthernetInterface::updateInfo(const system::InterfaceInfo& info)
 {
-    EthernetInterfaceIntf::linkUp(info.running);
+    EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
     if (info.mac)
     {
         MacAddressIntf::macAddress(std::to_string(*info.mac));
@@ -775,14 +767,13 @@
     return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
 }
 
-void EthernetInterface::loadVLAN(std::string_view objRoot, uint16_t id)
+void EthernetInterface::loadVLAN(std::string_view objRoot, uint16_t id,
+                                 system::InterfaceInfo&& info)
 {
-    auto vlanInterfaceName = vlanIntfName(id);
     config::Parser config(
-        config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
+        config::pathForIntfConf(manager.getConfDir(), *info.name));
     auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
-        bus, manager, getInterfaceInfo(vlanInterfaceName), objRoot, config, id,
-        *this);
+        bus, manager, info, objRoot, config, id, *this);
 
     // Fetch the ip address from the system
     // and create the dbus object.
@@ -791,8 +782,7 @@
     vlanIntf->loadNameServers(config);
     vlanIntf->loadNTPServers(config);
 
-    this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
-                                 std::move(vlanIntf));
+    this->vlanInterfaces.emplace(std::move(*info.name), std::move(vlanIntf));
 }
 
 ObjectPath EthernetInterface::createVLAN(uint16_t id)
@@ -808,8 +798,19 @@
     }
 
     auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
-    auto info = getInterfaceInfo(interfaceName());
-    info.name = vlanInterfaceName;
+    auto macStr = MacAddressIntf::macAddress();
+    std::optional<ether_addr> mac;
+    if (!macStr.empty())
+    {
+        mac.emplace(mac_address::fromString(macStr));
+    }
+    auto info = system::InterfaceInfo{
+        .idx = 0, // TODO: Query the correct value after creation
+        .flags = 0,
+        .name = vlanInterfaceName,
+        .mac = std::move(mac),
+        .mtu = mtu(),
+    };
 
     // Pass the parents nicEnabled property, so that the child
     // VLAN interface can inherit.
@@ -821,7 +822,8 @@
     // write the device file for the vlan interface.
     vlanIntf->writeDeviceFile();
 
-    this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
+    this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
+                                 std::move(vlanIntf));
 
     writeConfigurationFile();
     manager.reloadConfigs();