types: Migrate to stdplus EtherAddr

Change-Id: I1ec2cd0b57a9f02fe96bbe9a068d1a437805b43a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index e4108f3..91e5ed5 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -136,7 +136,7 @@
     EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
     if (info.mac)
     {
-        MacAddressIntf::macAddress(std::to_string(*info.mac), skipSignal);
+        MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
     }
     if (info.mtu)
     {
@@ -203,7 +203,7 @@
 
     if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
     {
-        it->second->NeighborObj::macAddress(std::to_string(*info.mac));
+        it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
     }
     else
     {
@@ -292,10 +292,10 @@
                               Argument::ARGUMENT_VALUE(ipAddress.c_str()));
     }
 
-    ether_addr lladdr;
+    stdplus::EtherAddr lladdr;
     try
     {
-        lladdr = ToAddr<ether_addr>{}(macAddress);
+        lladdr = stdplus::fromStr<stdplus::EtherAddr>(macAddress);
     }
     catch (const std::exception& e)
     {
@@ -315,7 +315,7 @@
     }
     else
     {
-        auto str = std::to_string(lladdr);
+        auto str = stdplus::toStr(lladdr);
         if (it->second->macAddress() == str)
         {
             return it->second->getObjPath();
@@ -558,10 +558,10 @@
 
     auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
     auto macStr = MacAddressIntf::macAddress();
-    std::optional<ether_addr> mac;
+    std::optional<stdplus::EtherAddr> mac;
     if (!macStr.empty())
     {
-        mac.emplace(ToAddr<ether_addr>{}(macStr));
+        mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
     }
     auto info = AllIntfInfo{InterfaceInfo{
         .type = ARPHRD_ETHER,
@@ -739,10 +739,10 @@
         elog<InternalFailure>();
     }
 #ifdef PERSIST_MAC
-    ether_addr newMAC;
+    stdplus::EtherAddr newMAC;
     try
     {
-        newMAC = ToAddr<ether_addr>{}(value);
+        newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
     }
     catch (const std::invalid_argument&)
     {
@@ -750,7 +750,7 @@
         elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
                               Argument::ARGUMENT_VALUE(value.c_str()));
     }
-    if (!mac_address::isUnicast(newMAC))
+    if (!newMAC.isUnicast())
     {
         lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
         elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
@@ -758,10 +758,11 @@
     }
 
     auto interface = interfaceName();
-    auto validMAC = std::to_string(newMAC);
+    auto validMAC = stdplus::toStr(newMAC);
 
     // We don't need to update the system if the address is unchanged
-    ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
+    auto oldMAC =
+        stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
     if (newMAC != oldMAC)
     {
         // Update everything that depends on the MAC value
diff --git a/src/inventory_mac.cpp b/src/inventory_mac.cpp
index c9769d1..49beecd 100644
--- a/src/inventory_mac.cpp
+++ b/src/inventory_mac.cpp
@@ -76,7 +76,8 @@
     }
 }
 
-ether_addr getfromInventory(sdbusplus::bus_t& bus, const std::string& intfName)
+stdplus::EtherAddr getfromInventory(sdbusplus::bus_t& bus,
+                                    const std::string& intfName)
 {
     std::string interfaceName = configJson[intfName];
 
@@ -156,7 +157,7 @@
 
     std::variant<std::string> value;
     reply.read(value);
-    return ToAddr<ether_addr>{}(std::get<std::string>(value));
+    return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(value));
 }
 
 bool setInventoryMACOnSystem(sdbusplus::bus_t& bus, const std::string& intfname)
@@ -164,9 +165,9 @@
     try
     {
         auto inventoryMAC = getfromInventory(bus, intfname);
-        if (inventoryMAC != ether_addr{})
+        if (inventoryMAC != stdplus::EtherAddr{})
         {
-            auto macStr = std::to_string(inventoryMAC);
+            auto macStr = stdplus::toStr(inventoryMAC);
             lg2::info(
                 "Mac Address {NET_MAC} in Inventory on Interface {NET_INTF}",
                 "NET_MAC", macStr, "NET_INTF", intfname);
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index d9f2436..afbc062 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -23,19 +23,19 @@
 
 Neighbor::Neighbor(sdbusplus::bus_t& bus, std::string_view objRoot,
                    stdplus::PinnedRef<EthernetInterface> parent, InAddrAny addr,
-                   ether_addr lladdr, State state) :
+                   stdplus::EtherAddr lladdr, State state) :
     Neighbor(bus, makeObjPath(objRoot, addr), parent, addr, lladdr, state)
 {}
 
 Neighbor::Neighbor(sdbusplus::bus_t& bus,
                    sdbusplus::message::object_path objPath,
                    stdplus::PinnedRef<EthernetInterface> parent, InAddrAny addr,
-                   ether_addr lladdr, State state) :
+                   stdplus::EtherAddr lladdr, State state) :
     NeighborObj(bus, objPath.str.c_str(), NeighborObj::action::defer_emit),
     parent(parent), objPath(std::move(objPath))
 {
     NeighborObj::ipAddress(std::to_string(addr), true);
-    NeighborObj::macAddress(std::to_string(lladdr), true);
+    NeighborObj::macAddress(stdplus::toStr(lladdr), true);
     NeighborObj::state(state, true);
     emit_object_added();
 }
diff --git a/src/neighbor.hpp b/src/neighbor.hpp
index f36371a..9f964e8 100644
--- a/src/neighbor.hpp
+++ b/src/neighbor.hpp
@@ -40,7 +40,7 @@
      */
     Neighbor(sdbusplus::bus_t& bus, std::string_view objRoot,
              stdplus::PinnedRef<EthernetInterface> parent, InAddrAny addr,
-             ether_addr lladdr, State state);
+             stdplus::EtherAddr lladdr, State state);
 
     /** @brief Delete this d-bus object.
      */
@@ -67,7 +67,7 @@
 
     Neighbor(sdbusplus::bus_t& bus, sdbusplus::message::object_path objPath,
              stdplus::PinnedRef<EthernetInterface> parent, InAddrAny addr,
-             ether_addr lladdr, State state);
+             stdplus::EtherAddr lladdr, State state);
 };
 
 } // namespace network
diff --git a/src/rtnetlink.cpp b/src/rtnetlink.cpp
index 1c80c1d..4308d23 100644
--- a/src/rtnetlink.cpp
+++ b/src/rtnetlink.cpp
@@ -67,9 +67,10 @@
                 ret.name.emplace(data.begin(), data.end() - 1);
                 break;
             case IFLA_ADDRESS:
-                if (data.size() == sizeof(ether_addr))
+                if (data.size() == sizeof(stdplus::EtherAddr))
                 {
-                    ret.mac.emplace(stdplus::raw::copyFrom<ether_addr>(data));
+                    ret.mac.emplace(
+                        stdplus::raw::copyFrom<stdplus::EtherAddr>(data));
                 }
                 break;
             case IFLA_MTU:
@@ -171,7 +172,7 @@
         auto [hdr, data] = netlink::extractRtAttr(msg);
         if (hdr.rta_type == NDA_LLADDR)
         {
-            ret.mac = stdplus::raw::copyFrom<ether_addr>(data);
+            ret.mac = stdplus::raw::copyFrom<stdplus::EtherAddr>(data);
         }
         else if (hdr.rta_type == NDA_DST)
         {
diff --git a/src/types.cpp b/src/types.cpp
index 0a46b1f..901d77a 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -25,10 +25,6 @@
     return stdplus::hashMulti(addr.getAddr(), addr.getPfx());
 }
 
-std::string std::to_string(ether_addr value)
-{
-    return string(phosphor::network::detail::ToStrBuf<ether_addr>{}(value));
-}
 std::string std::to_string(in_addr value)
 {
     return string(phosphor::network::detail::ToStrBuf<in_addr>{}(value));
diff --git a/src/types.hpp b/src/types.hpp
index 53a3c89..f7c0fa3 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -1,8 +1,9 @@
 #pragma once
 #include <fmt/core.h>
-#include <net/ethernet.h>
 #include <netinet/in.h>
 
+#include <stdplus/net/addr/ether.hpp>
+
 #include <algorithm>
 #include <array>
 #include <numeric>
@@ -14,12 +15,6 @@
 #include <unordered_set>
 #include <variant>
 
-constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
-{
-    return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
-                      rhs.ether_addr_octet);
-}
-
 constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
 {
     return lhs.s_addr == rhs.s_addr;
@@ -85,7 +80,7 @@
     unsigned idx;
     unsigned flags;
     std::optional<std::string> name = std::nullopt;
-    std::optional<ether_addr> mac = std::nullopt;
+    std::optional<stdplus::EtherAddr> mac = std::nullopt;
     std::optional<unsigned> mtu = std::nullopt;
     std::optional<unsigned> parent_idx = std::nullopt;
     std::optional<std::string> kind = std::nullopt;
@@ -125,7 +120,7 @@
     unsigned ifidx;
     uint16_t state;
     std::optional<InAddrAny> addr;
-    std::optional<ether_addr> mac;
+    std::optional<stdplus::EtherAddr> mac;
 
     constexpr bool operator==(const NeighborInfo& rhs) const noexcept
     {
@@ -356,38 +351,6 @@
 {};
 
 template <>
-struct ToAddr<ether_addr>
-{
-    constexpr ether_addr operator()(std::string_view str) const
-    {
-        constexpr DecodeInt<uint8_t, 16> di;
-        ether_addr ret;
-        if (str.size() == 12 && str.find(":") == str.npos)
-        {
-            for (size_t i = 0; i < 6; ++i)
-            {
-                ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
-            }
-        }
-        else
-        {
-            for (size_t i = 0; i < 5; ++i)
-            {
-                auto loc = str.find(":");
-                ret.ether_addr_octet[i] = di(str.substr(0, loc));
-                str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
-                if (str.empty())
-                {
-                    throw std::invalid_argument("Missing mac data");
-                }
-            }
-            ret.ether_addr_octet[5] = di(str);
-        }
-        return ret;
-    }
-};
-
-template <>
 struct ToAddr<in_addr>
 {
     constexpr in_addr operator()(std::string_view str) const
@@ -516,29 +479,6 @@
 };
 
 template <>
-struct ToStr<ether_addr>
-{
-    // 6 octets * 2 hex chars + 5 separators
-    static constexpr uint8_t buf_size = 17;
-    using buf_type = std::array<char, buf_size>;
-
-    constexpr char* operator()(char* buf, ether_addr v) const noexcept
-    {
-        for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
-        {
-            *ptr = ':';
-        }
-        for (size_t i = 0; i < 6; ++i)
-        {
-            char* tmp = buf + i * 3;
-            uint8_t byte = v.ether_addr_octet[i];
-            EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
-        }
-        return buf + buf_size;
-    }
-};
-
-template <>
 struct ToStr<in_addr>
 {
     // 4 octets * 3 dec chars + 3 separators
@@ -742,9 +682,6 @@
 namespace fmt
 {
 template <>
-struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
-{};
-template <>
 struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
 {};
 template <>
@@ -762,7 +699,6 @@
 
 namespace std
 {
-string to_string(ether_addr value);
 string to_string(in_addr value);
 string to_string(in6_addr value);
 string to_string(phosphor::network::InAddrAny value);
@@ -777,11 +713,6 @@
     return phosphor::network::detail::veq(rhs, lhs);
 }
 
-auto& operator<<(auto& os, ether_addr v)
-{
-    return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
-}
-
 auto& operator<<(auto& os, in_addr v)
 {
     return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
diff --git a/src/util.cpp b/src/util.cpp
index dbc474a..7102372 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -216,24 +216,5 @@
         .value_or(true);
 }
 
-namespace mac_address
-{
-
-bool isEmpty(const ether_addr& mac)
-{
-    return mac == ether_addr{};
-}
-
-bool isMulticast(const ether_addr& mac)
-{
-    return mac.ether_addr_octet[0] & 0b1;
-}
-
-bool isUnicast(const ether_addr& mac)
-{
-    return !isEmpty(mac) && !isMulticast(mac);
-}
-
-} // namespace mac_address
 } // namespace network
 } // namespace phosphor
diff --git a/src/util.hpp b/src/util.hpp
index f35e512..7736f67 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -18,29 +18,6 @@
 class Parser;
 }
 
-namespace mac_address
-{
-
-/** @brief Determines if the mac address is empty
- *  @param[in] mac - The mac address
- *  @return True if 00:00:00:00:00:00
- */
-bool isEmpty(const ether_addr& mac);
-
-/** @brief Determines if the mac address is a multicast address
- *  @param[in] mac - The mac address
- *  @return True if multicast bit is set
- */
-bool isMulticast(const ether_addr& mac);
-
-/** @brief Determines if the mac address is a unicast address
- *  @param[in] mac - The mac address
- *  @return True if not multicast or empty
- */
-bool isUnicast(const ether_addr& mac);
-
-} // namespace mac_address
-
 /* @brief converts a sockaddr for the specified address family into
  *        a type_safe InAddrAny.
  * @param[in] family - The address family of the buf
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index f6c59b1..0596980 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -71,7 +71,7 @@
     EXPECT_EQ("", interface.macAddress());
     EXPECT_FALSE(interface.linkUp());
 
-    constexpr ether_addr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+    constexpr stdplus::EtherAddr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
     constexpr unsigned mtu = 150;
 
     AllIntfInfo info{InterfaceInfo{.type = ARPHRD_ETHER,
@@ -84,7 +84,7 @@
                                "/xyz/openbmc_test/network"sv, config::Parser());
 
     EXPECT_EQ(mtu, intf.mtu());
-    EXPECT_EQ(std::to_string(mac), intf.macAddress());
+    EXPECT_EQ(stdplus::toStr(mac), intf.macAddress());
     EXPECT_TRUE(intf.linkUp());
 }
 
diff --git a/test/test_types.cpp b/test/test_types.cpp
index ae5c96d..53d05a3 100644
--- a/test/test_types.cpp
+++ b/test/test_types.cpp
@@ -12,14 +12,6 @@
 
 using std::literals::string_view_literals::operator""sv;
 
-TEST(EqualOperator, EthAddr)
-{
-    EXPECT_EQ((ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}),
-              (ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}));
-    EXPECT_EQ((ether_addr{}), (ether_addr{}));
-    EXPECT_NE((ether_addr{1}), (ether_addr{}));
-}
-
 TEST(EqualOperator, InAddr)
 {
     EXPECT_EQ((in_addr{0xff00ff00}), (in_addr{0xff00ff00}));
@@ -112,39 +104,6 @@
     EXPECT_NE(InAddrAny(in6_addr{1}), InAddrAny(in6_addr{}));
 }
 
-TEST(ToAddr, EtherAddr)
-{
-    EXPECT_THROW(ToAddr<ether_addr>{}("0x:00:00:00:00:00"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00"), std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00:"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00::00"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}(":00:00:00:00:00"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00::00:00:00:00"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}(":::::"), std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00:0:0:0:0"), std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00:00:00"),
-                 std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}(""), std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("123456789XYZ"), std::invalid_argument);
-    EXPECT_THROW(ToAddr<ether_addr>{}("123456789AB"), std::overflow_error);
-    EXPECT_THROW(ToAddr<ether_addr>{}("123456789ABCD"), std::overflow_error);
-
-    EXPECT_EQ((ether_addr{}), ToAddr<ether_addr>{}("00:00:00:00:00:00"));
-    EXPECT_EQ((ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}),
-              ToAddr<ether_addr>{}("FF:EE:DD:cc:bb:aa"));
-    EXPECT_EQ((ether_addr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}),
-              ToAddr<ether_addr>{}("0:1:2:3:4:5"));
-    EXPECT_EQ((ether_addr{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
-              ToAddr<ether_addr>{}("0123456789AB"));
-    EXPECT_EQ((ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}),
-              ToAddr<ether_addr>{}("FFEEDDccbbaa"));
-}
-
 TEST(ToAddr, InAddr)
 {
     EXPECT_THROW(ToAddr<in_addr>{}(""), std::invalid_argument);
@@ -234,17 +193,6 @@
 namespace detail
 {
 
-TEST(BufMaker, EthAddr)
-{
-    ToStrBuf<ether_addr> abm;
-    EXPECT_EQ("11:22:33:44:55:66"sv,
-              abm(ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}));
-    EXPECT_EQ("01:02:03:04:05:67"sv,
-              abm(ether_addr{0x01, 0x02, 0x03, 0x04, 0x05, 0x67}));
-    EXPECT_EQ("00:00:00:00:00:00"sv,
-              abm(ether_addr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
-}
-
 TEST(BufMaker, InAddr)
 {
     ToStrBuf<in_addr> abm;
@@ -286,22 +234,18 @@
 {
     EXPECT_NE(InAddrAny{in6_addr{}}, InAddrAny{in_addr{}});
 
-    EXPECT_EQ("a 01:00:00:00:00:00", fmt::format("a {}", ether_addr{1}));
     EXPECT_EQ("a 0.0.0.1", fmt::format("a {}", in_addr{htonl(1)}));
     EXPECT_EQ("a 0.0.0.1", fmt::format("a {}", InAddrAny{in_addr{htonl(1)}}));
     EXPECT_EQ("a 100::", fmt::format("a {}", in6_addr{1}));
     EXPECT_EQ("a 100::", fmt::format("a {}", InAddrAny{in6_addr{1}}));
     EXPECT_EQ("a 100::/90", fmt::format("a {}", IfAddr{in6_addr{1}, 90}));
 
-    EXPECT_EQ("01:00:00:00:00:00", std::to_string(ether_addr{1}));
     EXPECT_EQ("0.0.0.1", std::to_string(in_addr{htonl(1)}));
     EXPECT_EQ("0.0.0.1", std::to_string(InAddrAny{in_addr{htonl(1)}}));
     EXPECT_EQ("100::", std::to_string(in6_addr{1}));
     EXPECT_EQ("100::", std::to_string(InAddrAny{in6_addr{1}}));
     EXPECT_EQ("100::/22", std::to_string(IfAddr{in6_addr{1}, 22}));
 
-    EXPECT_EQ("a01:00:00:00:00:00",
-              (std::stringstream{} << "a" << ether_addr{1}).str());
     EXPECT_EQ("a0.0.0.1",
               (std::stringstream{} << "a" << in_addr{htonl(1)}).str());
     EXPECT_EQ(
diff --git a/test/test_util.cpp b/test/test_util.cpp
index 7d4c611..ab66e28 100644
--- a/test/test_util.cpp
+++ b/test/test_util.cpp
@@ -52,43 +52,6 @@
 namespace mac_address
 {
 
-TEST(MacIsEmpty, True)
-{
-    EXPECT_TRUE(isEmpty({}));
-}
-
-TEST(MacIsEmpty, False)
-{
-    EXPECT_FALSE(isEmpty({1}));
-    EXPECT_FALSE(isEmpty({0, 0, 0, 1}));
-    EXPECT_FALSE(isEmpty({0, 0, 0, 0, 0, 1}));
-}
-
-TEST(MacIsMulticast, True)
-{
-    EXPECT_TRUE(isMulticast({255, 255, 255, 255, 255, 255}));
-    EXPECT_TRUE(isMulticast({1}));
-}
-
-TEST(MacIsMulticast, False)
-{
-    EXPECT_FALSE(isMulticast({0, 1, 2, 3, 4, 5}));
-    EXPECT_FALSE(isMulticast({0xfe, 255, 255, 255, 255, 255}));
-}
-
-TEST(MacIsUnicast, True)
-{
-    EXPECT_TRUE(isUnicast({0, 1, 2, 3, 4, 5}));
-    EXPECT_TRUE(isUnicast({0xfe, 255, 255, 255, 255, 255}));
-}
-
-TEST(MacIsUnicast, False)
-{
-    EXPECT_FALSE(isUnicast({}));
-    EXPECT_FALSE(isUnicast({1}));
-    EXPECT_FALSE(isUnicast({255, 255, 255, 255, 255, 255}));
-}
-
 TEST(IgnoredInterfaces, Empty)
 {
     auto ret = internal::parseInterfaces({});