11bbe3d1eSWilliam A. Kennington III #pragma once 2bb0eaccbSWilliam A. Kennington III #include <fmt/core.h> 3bb0eaccbSWilliam A. Kennington III #include <net/ethernet.h> 41bbe3d1eSWilliam A. Kennington III #include <netinet/in.h> 51bbe3d1eSWilliam A. Kennington III 6bb0eaccbSWilliam A. Kennington III #include <algorithm> 7bb0eaccbSWilliam A. Kennington III #include <array> 81bbe3d1eSWilliam A. Kennington III #include <chrono> 9*71de63a2SWilliam A. Kennington III #include <numeric> 101bbe3d1eSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 111bbe3d1eSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 121bbe3d1eSWilliam A. Kennington III #include <string> 13bb0eaccbSWilliam A. Kennington III #include <string_view> 14bb0eaccbSWilliam A. Kennington III #include <type_traits> 15dd9ef815SWilliam A. Kennington III #include <unordered_map> 16f7dce2e8SWilly Tu #include <unordered_set> 171bbe3d1eSWilliam A. Kennington III #include <variant> 181bbe3d1eSWilliam A. Kennington III 191bbe3d1eSWilliam A. Kennington III namespace phosphor 201bbe3d1eSWilliam A. Kennington III { 211bbe3d1eSWilliam A. Kennington III namespace network 221bbe3d1eSWilliam A. Kennington III { 231bbe3d1eSWilliam A. Kennington III 241bbe3d1eSWilliam A. Kennington III using namespace std::chrono_literals; 251bbe3d1eSWilliam A. Kennington III 26c7cf25f7SWilliam A. Kennington III // wait for three seconds before reloading systemd-networkd 27c7cf25f7SWilliam A. Kennington III constexpr auto reloadTimeout = 3s; 281bbe3d1eSWilliam A. Kennington III 29d41db383SWilliam A. Kennington III // refresh the objets after four seconds as network 30d41db383SWilliam A. Kennington III // configuration takes 3-4 sec to reconfigure at most. 31d41db383SWilliam A. Kennington III constexpr auto refreshTimeout = 4s; 321bbe3d1eSWilliam A. Kennington III 331bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order 34bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>; 351bbe3d1eSWilliam A. Kennington III 361bbe3d1eSWilliam A. Kennington III using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>; 371bbe3d1eSWilliam A. Kennington III 38dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 39dd9ef815SWilliam A. Kennington III { 40dd9ef815SWilliam A. Kennington III using is_transparent = void; 41dd9ef815SWilliam A. Kennington III }; 42dd9ef815SWilliam A. Kennington III template <typename V> 43dd9ef815SWilliam A. Kennington III using string_umap = 44dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 4596444795SWilliam A. Kennington III using string_uset = 4696444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 47dd9ef815SWilliam A. Kennington III 483e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 49991a8e81SWilliam A. Kennington III { 50991a8e81SWilliam A. Kennington III return 0; 51991a8e81SWilliam A. Kennington III } 52991a8e81SWilliam A. Kennington III 53991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 54becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept 55991a8e81SWilliam A. Kennington III { 56991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 57991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 58991a8e81SWilliam A. Kennington III } 59991a8e81SWilliam A. Kennington III 60bb0eaccbSWilliam A. Kennington III namespace detail 61bb0eaccbSWilliam A. Kennington III { 62bb0eaccbSWilliam A. Kennington III 63*71de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)> 64*71de63a2SWilliam A. Kennington III struct BswapAlign 65*71de63a2SWilliam A. Kennington III { 66*71de63a2SWilliam A. Kennington III using type = T; 67*71de63a2SWilliam A. Kennington III }; 68*71de63a2SWilliam A. Kennington III 69*71de63a2SWilliam A. Kennington III template <typename T> 70*71de63a2SWilliam A. Kennington III struct BswapAlign<T, 2> 71*71de63a2SWilliam A. Kennington III { 72*71de63a2SWilliam A. Kennington III using type alignas(uint16_t) = T; 73*71de63a2SWilliam A. Kennington III }; 74*71de63a2SWilliam A. Kennington III 75*71de63a2SWilliam A. Kennington III template <typename T> 76*71de63a2SWilliam A. Kennington III struct BswapAlign<T, 4> 77*71de63a2SWilliam A. Kennington III { 78*71de63a2SWilliam A. Kennington III using type alignas(uint32_t) = T; 79*71de63a2SWilliam A. Kennington III }; 80*71de63a2SWilliam A. Kennington III 81*71de63a2SWilliam A. Kennington III template <typename T> 82*71de63a2SWilliam A. Kennington III struct BswapAlign<T, 8> 83*71de63a2SWilliam A. Kennington III { 84*71de63a2SWilliam A. Kennington III using type alignas(uint64_t) = T; 85*71de63a2SWilliam A. Kennington III }; 86*71de63a2SWilliam A. Kennington III 87*71de63a2SWilliam A. Kennington III template <typename T> 88*71de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept 89*71de63a2SWilliam A. Kennington III { 90*71de63a2SWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>); 91*71de63a2SWilliam A. Kennington III if constexpr (sizeof(T) == 2) 92*71de63a2SWilliam A. Kennington III { 93*71de63a2SWilliam A. Kennington III reinterpret_cast<uint16_t&>(n) = 94*71de63a2SWilliam A. Kennington III __builtin_bswap16(reinterpret_cast<uint16_t&>(n)); 95*71de63a2SWilliam A. Kennington III } 96*71de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 4) 97*71de63a2SWilliam A. Kennington III { 98*71de63a2SWilliam A. Kennington III reinterpret_cast<uint32_t&>(n) = 99*71de63a2SWilliam A. Kennington III __builtin_bswap32(reinterpret_cast<uint32_t&>(n)); 100*71de63a2SWilliam A. Kennington III } 101*71de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 8) 102*71de63a2SWilliam A. Kennington III { 103*71de63a2SWilliam A. Kennington III reinterpret_cast<uint64_t&>(n) = 104*71de63a2SWilliam A. Kennington III __builtin_bswap64(reinterpret_cast<uint64_t&>(n)); 105*71de63a2SWilliam A. Kennington III } 106*71de63a2SWilliam A. Kennington III else 107*71de63a2SWilliam A. Kennington III { 108*71de63a2SWilliam A. Kennington III auto b = reinterpret_cast<std::byte*>(&n); 109*71de63a2SWilliam A. Kennington III std::reverse(b, b + sizeof(n)); 110*71de63a2SWilliam A. Kennington III } 111*71de63a2SWilliam A. Kennington III return n; 112*71de63a2SWilliam A. Kennington III } 113*71de63a2SWilliam A. Kennington III 114*71de63a2SWilliam A. Kennington III } // namespace detail 115*71de63a2SWilliam A. Kennington III 116*71de63a2SWilliam A. Kennington III template <typename T> 117*71de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept 118*71de63a2SWilliam A. Kennington III { 119*71de63a2SWilliam A. Kennington III return detail::bswapInt<T>(n); 120*71de63a2SWilliam A. Kennington III } 121*71de63a2SWilliam A. Kennington III 122*71de63a2SWilliam A. Kennington III template <typename T> 123*71de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept 124*71de63a2SWilliam A. Kennington III { 125*71de63a2SWilliam A. Kennington III if constexpr (std::endian::native == std::endian::big) 126*71de63a2SWilliam A. Kennington III { 127*71de63a2SWilliam A. Kennington III return n; 128*71de63a2SWilliam A. Kennington III } 129*71de63a2SWilliam A. Kennington III else if constexpr (std::endian::native == std::endian::little) 130*71de63a2SWilliam A. Kennington III { 131*71de63a2SWilliam A. Kennington III return bswap(n); 132*71de63a2SWilliam A. Kennington III } 133*71de63a2SWilliam A. Kennington III else 134*71de63a2SWilliam A. Kennington III { 135*71de63a2SWilliam A. Kennington III static_assert(std::is_same_v<T, void>); 136*71de63a2SWilliam A. Kennington III } 137*71de63a2SWilliam A. Kennington III } 138*71de63a2SWilliam A. Kennington III 139*71de63a2SWilliam A. Kennington III template <typename T> 140*71de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept 141*71de63a2SWilliam A. Kennington III { 142*71de63a2SWilliam A. Kennington III return hton(n); 143*71de63a2SWilliam A. Kennington III } 144*71de63a2SWilliam A. Kennington III 145*71de63a2SWilliam A. Kennington III namespace detail 146*71de63a2SWilliam A. Kennington III { 147*71de63a2SWilliam A. Kennington III 148bb0eaccbSWilliam A. Kennington III template <typename T> 149bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 150bb0eaccbSWilliam A. Kennington III { 151bb0eaccbSWilliam A. Kennington III return false; 152bb0eaccbSWilliam A. Kennington III } 153bb0eaccbSWilliam A. Kennington III 154bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 155bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 156bb0eaccbSWilliam A. Kennington III { 157bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 158bb0eaccbSWilliam A. Kennington III } 159bb0eaccbSWilliam A. Kennington III 160bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 161bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 162bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 163bb0eaccbSWilliam A. Kennington III { 164bb0eaccbSWilliam A. Kennington III return std::visit( 165bb0eaccbSWilliam A. Kennington III [t](auto v) { 166bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 167bb0eaccbSWilliam A. Kennington III { 168bb0eaccbSWilliam A. Kennington III return v == t; 169bb0eaccbSWilliam A. Kennington III } 170bb0eaccbSWilliam A. Kennington III else 171bb0eaccbSWilliam A. Kennington III { 172bb0eaccbSWilliam A. Kennington III return false; 173bb0eaccbSWilliam A. Kennington III } 174bb0eaccbSWilliam A. Kennington III }, 175bb0eaccbSWilliam A. Kennington III v); 176bb0eaccbSWilliam A. Kennington III } 177bb0eaccbSWilliam A. Kennington III 178bb0eaccbSWilliam A. Kennington III template <typename T> 179bb0eaccbSWilliam A. Kennington III struct AddrBufMaker 180bb0eaccbSWilliam A. Kennington III { 181bb0eaccbSWilliam A. Kennington III }; 182bb0eaccbSWilliam A. Kennington III 183bb0eaccbSWilliam A. Kennington III template <> 184bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<ether_addr> 185bb0eaccbSWilliam A. Kennington III { 186bb0eaccbSWilliam A. Kennington III public: 187bb0eaccbSWilliam A. Kennington III std::string_view operator()(ether_addr val) noexcept; 188bb0eaccbSWilliam A. Kennington III 189bb0eaccbSWilliam A. Kennington III private: 190bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf; 191bb0eaccbSWilliam A. Kennington III }; 192bb0eaccbSWilliam A. Kennington III 193bb0eaccbSWilliam A. Kennington III template <> 194bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in_addr> 195bb0eaccbSWilliam A. Kennington III { 196bb0eaccbSWilliam A. Kennington III public: 197bb0eaccbSWilliam A. Kennington III std::string_view operator()(in_addr val) noexcept; 198bb0eaccbSWilliam A. Kennington III 199bb0eaccbSWilliam A. Kennington III private: 200bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf; 201bb0eaccbSWilliam A. Kennington III }; 202bb0eaccbSWilliam A. Kennington III 203bb0eaccbSWilliam A. Kennington III template <> 204bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in6_addr> 205bb0eaccbSWilliam A. Kennington III { 206bb0eaccbSWilliam A. Kennington III public: 207bb0eaccbSWilliam A. Kennington III std::string_view operator()(in6_addr val) noexcept; 208bb0eaccbSWilliam A. Kennington III 209bb0eaccbSWilliam A. Kennington III private: 210bb0eaccbSWilliam A. Kennington III std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf; 211bb0eaccbSWilliam A. Kennington III }; 212bb0eaccbSWilliam A. Kennington III 213bb0eaccbSWilliam A. Kennington III template <typename BufMaker> 214bb0eaccbSWilliam A. Kennington III struct FormatFromBuf 215bb0eaccbSWilliam A. Kennington III { 216bb0eaccbSWilliam A. Kennington III private: 217bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 218bb0eaccbSWilliam A. Kennington III 219bb0eaccbSWilliam A. Kennington III public: 220bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 221bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 222bb0eaccbSWilliam A. Kennington III { 223bb0eaccbSWilliam A. Kennington III return ctx.begin(); 224bb0eaccbSWilliam A. Kennington III } 225bb0eaccbSWilliam A. Kennington III 226bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 227bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 228bb0eaccbSWilliam A. Kennington III { 229bb0eaccbSWilliam A. Kennington III return formatter.format(BufMaker{}(v), ctx); 230bb0eaccbSWilliam A. Kennington III } 231bb0eaccbSWilliam A. Kennington III }; 232bb0eaccbSWilliam A. Kennington III } // namespace detail 2331bbe3d1eSWilliam A. Kennington III } // namespace network 2341bbe3d1eSWilliam A. Kennington III } // namespace phosphor 2353e471c5fSWilliam A. Kennington III 2363e471c5fSWilliam A. Kennington III template <typename... Ts> 2373e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 2383e471c5fSWilliam A. Kennington III { 2393e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 2403e471c5fSWilliam A. Kennington III { 2413e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 2423e471c5fSWilliam A. Kennington III } 2433e471c5fSWilliam A. Kennington III }; 244bb0eaccbSWilliam A. Kennington III 245653114fcSWilliam A. Kennington III template <> 246653114fcSWilliam A. Kennington III struct std::hash<in_addr> 247653114fcSWilliam A. Kennington III { 248653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 249653114fcSWilliam A. Kennington III }; 250653114fcSWilliam A. Kennington III 251653114fcSWilliam A. Kennington III template <> 252653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 253653114fcSWilliam A. Kennington III { 254653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 255653114fcSWilliam A. Kennington III }; 256653114fcSWilliam A. Kennington III 257bb0eaccbSWilliam A. Kennington III namespace fmt 258bb0eaccbSWilliam A. Kennington III { 259bb0eaccbSWilliam A. Kennington III template <> 260bb0eaccbSWilliam A. Kennington III struct formatter<ether_addr> 261bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 262bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<ether_addr>> 263bb0eaccbSWilliam A. Kennington III { 264bb0eaccbSWilliam A. Kennington III }; 265bb0eaccbSWilliam A. Kennington III template <> 266bb0eaccbSWilliam A. Kennington III struct formatter<in_addr> 267bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 268bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in_addr>> 269bb0eaccbSWilliam A. Kennington III { 270bb0eaccbSWilliam A. Kennington III }; 271bb0eaccbSWilliam A. Kennington III template <> 272bb0eaccbSWilliam A. Kennington III struct formatter<in6_addr> 273bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 274bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in6_addr>> 275bb0eaccbSWilliam A. Kennington III { 276bb0eaccbSWilliam A. Kennington III }; 277bb0eaccbSWilliam A. Kennington III template <> 278bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny> 279bb0eaccbSWilliam A. Kennington III { 280bb0eaccbSWilliam A. Kennington III private: 281bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 282bb0eaccbSWilliam A. Kennington III 283bb0eaccbSWilliam A. Kennington III public: 284bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 285bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 286bb0eaccbSWilliam A. Kennington III { 287bb0eaccbSWilliam A. Kennington III return ctx.begin(); 288bb0eaccbSWilliam A. Kennington III } 289bb0eaccbSWilliam A. Kennington III 290bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 291bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 292bb0eaccbSWilliam A. Kennington III { 293bb0eaccbSWilliam A. Kennington III return std::visit( 294bb0eaccbSWilliam A. Kennington III [&](auto v) { 295bb0eaccbSWilliam A. Kennington III auto abm = 296bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<decltype(v)>{}; 297bb0eaccbSWilliam A. Kennington III return formatter.format(abm(v), ctx); 298bb0eaccbSWilliam A. Kennington III }, 299bb0eaccbSWilliam A. Kennington III v); 300bb0eaccbSWilliam A. Kennington III } 301bb0eaccbSWilliam A. Kennington III }; 302bb0eaccbSWilliam A. Kennington III } // namespace fmt 303bb0eaccbSWilliam A. Kennington III 304bb0eaccbSWilliam A. Kennington III namespace std 305bb0eaccbSWilliam A. Kennington III { 306bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 307bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 308bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 309bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 310bb0eaccbSWilliam A. Kennington III } // namespace std 311bb0eaccbSWilliam A. Kennington III 312bb0eaccbSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 313bb0eaccbSWilliam A. Kennington III { 314bb0eaccbSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 315bb0eaccbSWilliam A. Kennington III rhs.ether_addr_octet); 316bb0eaccbSWilliam A. Kennington III } 317bb0eaccbSWilliam A. Kennington III 318bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 319bb0eaccbSWilliam A. Kennington III { 320bb0eaccbSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 321bb0eaccbSWilliam A. Kennington III } 322bb0eaccbSWilliam A. Kennington III 323bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 324bb0eaccbSWilliam A. Kennington III { 325bb0eaccbSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 326bb0eaccbSWilliam A. Kennington III } 327bb0eaccbSWilliam A. Kennington III 328bb0eaccbSWilliam A. Kennington III template <typename T> 329bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 330bb0eaccbSWilliam A. Kennington III bool> 331bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 332bb0eaccbSWilliam A. Kennington III { 333bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 334bb0eaccbSWilliam A. Kennington III } 335bb0eaccbSWilliam A. Kennington III 33686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 337bb0eaccbSWilliam A. Kennington III { 338bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v); 339bb0eaccbSWilliam A. Kennington III } 340bb0eaccbSWilliam A. Kennington III 34186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 342bb0eaccbSWilliam A. Kennington III { 343bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v); 344bb0eaccbSWilliam A. Kennington III } 345bb0eaccbSWilliam A. Kennington III 34686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 347bb0eaccbSWilliam A. Kennington III { 348bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v); 349bb0eaccbSWilliam A. Kennington III } 350bb0eaccbSWilliam A. Kennington III 35186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 352bb0eaccbSWilliam A. Kennington III { 353bb0eaccbSWilliam A. Kennington III return os << std::visit( 354bb0eaccbSWilliam A. Kennington III [](auto v) { 355bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::AddrBufMaker< 356bb0eaccbSWilliam A. Kennington III decltype(v)>{}(v); 357bb0eaccbSWilliam A. Kennington III }, 358bb0eaccbSWilliam A. Kennington III v); 359bb0eaccbSWilliam A. Kennington III } 360