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> 971de63a2SWilliam 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>; 35b9d7cbacSWilliam A. Kennington III class IfAddr 36b9d7cbacSWilliam A. Kennington III { 37b9d7cbacSWilliam A. Kennington III private: 38b9d7cbacSWilliam A. Kennington III InAddrAny addr; 39b9d7cbacSWilliam A. Kennington III uint8_t pfx; 40b9d7cbacSWilliam A. Kennington III 41b9d7cbacSWilliam A. Kennington III static void invalidPfx(uint8_t pfx); 42b9d7cbacSWilliam A. Kennington III 43b9d7cbacSWilliam A. Kennington III public: 44b9d7cbacSWilliam A. Kennington III constexpr IfAddr() : addr({}), pfx(0) 45b9d7cbacSWilliam A. Kennington III { 46b9d7cbacSWilliam A. Kennington III } 47b9d7cbacSWilliam A. Kennington III 48b9d7cbacSWilliam A. Kennington III constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx) 49b9d7cbacSWilliam A. Kennington III { 50b9d7cbacSWilliam A. Kennington III std::visit( 51b9d7cbacSWilliam A. Kennington III [pfx](auto v) { 52b9d7cbacSWilliam A. Kennington III if (sizeof(v) * 8 < pfx) 53b9d7cbacSWilliam A. Kennington III { 54b9d7cbacSWilliam A. Kennington III invalidPfx(pfx); 55b9d7cbacSWilliam A. Kennington III } 56b9d7cbacSWilliam A. Kennington III }, 57b9d7cbacSWilliam A. Kennington III addr); 58b9d7cbacSWilliam A. Kennington III } 59b9d7cbacSWilliam A. Kennington III 60b9d7cbacSWilliam A. Kennington III constexpr auto getAddr() const 61b9d7cbacSWilliam A. Kennington III { 62b9d7cbacSWilliam A. Kennington III return addr; 63b9d7cbacSWilliam A. Kennington III } 64b9d7cbacSWilliam A. Kennington III 65b9d7cbacSWilliam A. Kennington III constexpr auto getPfx() const 66b9d7cbacSWilliam A. Kennington III { 67b9d7cbacSWilliam A. Kennington III return pfx; 68b9d7cbacSWilliam A. Kennington III } 69b9d7cbacSWilliam A. Kennington III 70b9d7cbacSWilliam A. Kennington III constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept 71b9d7cbacSWilliam A. Kennington III { 72b9d7cbacSWilliam A. Kennington III return addr == rhs.addr && pfx == rhs.pfx; 73b9d7cbacSWilliam A. Kennington III } 74b9d7cbacSWilliam A. Kennington III }; 751bbe3d1eSWilliam A. Kennington III 761bbe3d1eSWilliam A. Kennington III using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>; 771bbe3d1eSWilliam A. Kennington III 78dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 79dd9ef815SWilliam A. Kennington III { 80dd9ef815SWilliam A. Kennington III using is_transparent = void; 81dd9ef815SWilliam A. Kennington III }; 82dd9ef815SWilliam A. Kennington III template <typename V> 83dd9ef815SWilliam A. Kennington III using string_umap = 84dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 8596444795SWilliam A. Kennington III using string_uset = 8696444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 87dd9ef815SWilliam A. Kennington III 883e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 89991a8e81SWilliam A. Kennington III { 90991a8e81SWilliam A. Kennington III return 0; 91991a8e81SWilliam A. Kennington III } 92991a8e81SWilliam A. Kennington III 93991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 94becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept 95991a8e81SWilliam A. Kennington III { 96991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 97991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 98991a8e81SWilliam A. Kennington III } 99991a8e81SWilliam A. Kennington III 100bb0eaccbSWilliam A. Kennington III namespace detail 101bb0eaccbSWilliam A. Kennington III { 102bb0eaccbSWilliam A. Kennington III 10371de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)> 10471de63a2SWilliam A. Kennington III struct BswapAlign 10571de63a2SWilliam A. Kennington III { 10671de63a2SWilliam A. Kennington III using type = T; 10771de63a2SWilliam A. Kennington III }; 10871de63a2SWilliam A. Kennington III 10971de63a2SWilliam A. Kennington III template <typename T> 11071de63a2SWilliam A. Kennington III struct BswapAlign<T, 2> 11171de63a2SWilliam A. Kennington III { 11271de63a2SWilliam A. Kennington III using type alignas(uint16_t) = T; 11371de63a2SWilliam A. Kennington III }; 11471de63a2SWilliam A. Kennington III 11571de63a2SWilliam A. Kennington III template <typename T> 11671de63a2SWilliam A. Kennington III struct BswapAlign<T, 4> 11771de63a2SWilliam A. Kennington III { 11871de63a2SWilliam A. Kennington III using type alignas(uint32_t) = T; 11971de63a2SWilliam A. Kennington III }; 12071de63a2SWilliam A. Kennington III 12171de63a2SWilliam A. Kennington III template <typename T> 12271de63a2SWilliam A. Kennington III struct BswapAlign<T, 8> 12371de63a2SWilliam A. Kennington III { 12471de63a2SWilliam A. Kennington III using type alignas(uint64_t) = T; 12571de63a2SWilliam A. Kennington III }; 12671de63a2SWilliam A. Kennington III 12771de63a2SWilliam A. Kennington III template <typename T> 12871de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept 12971de63a2SWilliam A. Kennington III { 13071de63a2SWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>); 13171de63a2SWilliam A. Kennington III if constexpr (sizeof(T) == 2) 13271de63a2SWilliam A. Kennington III { 13371de63a2SWilliam A. Kennington III reinterpret_cast<uint16_t&>(n) = 13471de63a2SWilliam A. Kennington III __builtin_bswap16(reinterpret_cast<uint16_t&>(n)); 13571de63a2SWilliam A. Kennington III } 13671de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 4) 13771de63a2SWilliam A. Kennington III { 13871de63a2SWilliam A. Kennington III reinterpret_cast<uint32_t&>(n) = 13971de63a2SWilliam A. Kennington III __builtin_bswap32(reinterpret_cast<uint32_t&>(n)); 14071de63a2SWilliam A. Kennington III } 14171de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 8) 14271de63a2SWilliam A. Kennington III { 14371de63a2SWilliam A. Kennington III reinterpret_cast<uint64_t&>(n) = 14471de63a2SWilliam A. Kennington III __builtin_bswap64(reinterpret_cast<uint64_t&>(n)); 14571de63a2SWilliam A. Kennington III } 14671de63a2SWilliam A. Kennington III else 14771de63a2SWilliam A. Kennington III { 14871de63a2SWilliam A. Kennington III auto b = reinterpret_cast<std::byte*>(&n); 14971de63a2SWilliam A. Kennington III std::reverse(b, b + sizeof(n)); 15071de63a2SWilliam A. Kennington III } 15171de63a2SWilliam A. Kennington III return n; 15271de63a2SWilliam A. Kennington III } 15371de63a2SWilliam A. Kennington III 15471de63a2SWilliam A. Kennington III } // namespace detail 15571de63a2SWilliam A. Kennington III 15671de63a2SWilliam A. Kennington III template <typename T> 15771de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept 15871de63a2SWilliam A. Kennington III { 15971de63a2SWilliam A. Kennington III return detail::bswapInt<T>(n); 16071de63a2SWilliam A. Kennington III } 16171de63a2SWilliam A. Kennington III 16271de63a2SWilliam A. Kennington III template <typename T> 16371de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept 16471de63a2SWilliam A. Kennington III { 16571de63a2SWilliam A. Kennington III if constexpr (std::endian::native == std::endian::big) 16671de63a2SWilliam A. Kennington III { 16771de63a2SWilliam A. Kennington III return n; 16871de63a2SWilliam A. Kennington III } 16971de63a2SWilliam A. Kennington III else if constexpr (std::endian::native == std::endian::little) 17071de63a2SWilliam A. Kennington III { 17171de63a2SWilliam A. Kennington III return bswap(n); 17271de63a2SWilliam A. Kennington III } 17371de63a2SWilliam A. Kennington III else 17471de63a2SWilliam A. Kennington III { 17571de63a2SWilliam A. Kennington III static_assert(std::is_same_v<T, void>); 17671de63a2SWilliam A. Kennington III } 17771de63a2SWilliam A. Kennington III } 17871de63a2SWilliam A. Kennington III 17971de63a2SWilliam A. Kennington III template <typename T> 18071de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept 18171de63a2SWilliam A. Kennington III { 18271de63a2SWilliam A. Kennington III return hton(n); 18371de63a2SWilliam A. Kennington III } 18471de63a2SWilliam A. Kennington III 18571de63a2SWilliam A. Kennington III namespace detail 18671de63a2SWilliam A. Kennington III { 187238ef992SWilliam A. Kennington III inline constexpr auto charLookup = []() { 188238ef992SWilliam A. Kennington III std::array<int8_t, 256> ret; 189238ef992SWilliam A. Kennington III std::fill(ret.begin(), ret.end(), -1); 190238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 191238ef992SWilliam A. Kennington III { 192238ef992SWilliam A. Kennington III ret[i + '0'] = i; 193238ef992SWilliam A. Kennington III } 194238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 195238ef992SWilliam A. Kennington III { 196238ef992SWilliam A. Kennington III ret[i + 'A'] = i + 10; 197238ef992SWilliam A. Kennington III ret[i + 'a'] = i + 10; 198238ef992SWilliam A. Kennington III } 199238ef992SWilliam A. Kennington III return ret; 200238ef992SWilliam A. Kennington III }(); 201238ef992SWilliam A. Kennington III } 202238ef992SWilliam A. Kennington III 203238ef992SWilliam A. Kennington III template <typename T, uint8_t base> 204238ef992SWilliam A. Kennington III struct DecodeInt 205238ef992SWilliam A. Kennington III { 206238ef992SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 207238ef992SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 208238ef992SWilliam A. Kennington III 209238ef992SWilliam A. Kennington III constexpr T operator()(std::string_view str) const 210238ef992SWilliam A. Kennington III { 211238ef992SWilliam A. Kennington III if (str.empty()) 212238ef992SWilliam A. Kennington III { 213238ef992SWilliam A. Kennington III throw std::invalid_argument("Empty Str"); 214238ef992SWilliam A. Kennington III } 215238ef992SWilliam A. Kennington III constexpr auto max = std::numeric_limits<T>::max(); 216238ef992SWilliam A. Kennington III auto ret = 217238ef992SWilliam A. Kennington III std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) { 218238ef992SWilliam A. Kennington III auto v = detail::charLookup[c]; 219238ef992SWilliam A. Kennington III if (v < 0 || v >= base) 220238ef992SWilliam A. Kennington III { 221238ef992SWilliam A. Kennington III throw std::invalid_argument("Invalid numeral"); 222238ef992SWilliam A. Kennington III } 223238ef992SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 224238ef992SWilliam A. Kennington III { 225238ef992SWilliam A. Kennington III constexpr auto shift = std::countr_zero(base); 226238ef992SWilliam A. Kennington III constexpr auto maxshift = max >> shift; 227238ef992SWilliam A. Kennington III if (r > maxshift) 228238ef992SWilliam A. Kennington III { 229238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 230238ef992SWilliam A. Kennington III } 231238ef992SWilliam A. Kennington III return (r << shift) | v; 232238ef992SWilliam A. Kennington III } 233238ef992SWilliam A. Kennington III else 234238ef992SWilliam A. Kennington III { 235238ef992SWilliam A. Kennington III constexpr auto maxbase = max / base; 236238ef992SWilliam A. Kennington III if (r > maxbase) 237238ef992SWilliam A. Kennington III { 238238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 239238ef992SWilliam A. Kennington III } 240238ef992SWilliam A. Kennington III r *= base; 241238ef992SWilliam A. Kennington III if (max - v < r) 242238ef992SWilliam A. Kennington III { 243238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 244238ef992SWilliam A. Kennington III } 245238ef992SWilliam A. Kennington III return r + v; 246238ef992SWilliam A. Kennington III } 247238ef992SWilliam A. Kennington III }); 248238ef992SWilliam A. Kennington III return ret; 249238ef992SWilliam A. Kennington III } 250238ef992SWilliam A. Kennington III }; 251238ef992SWilliam A. Kennington III 252b01d08fdSWilliam A. Kennington III template <typename T> 253b01d08fdSWilliam A. Kennington III struct ToAddr 254b01d08fdSWilliam A. Kennington III { 255b01d08fdSWilliam A. Kennington III }; 256b01d08fdSWilliam A. Kennington III 257b01d08fdSWilliam A. Kennington III template <> 258b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr> 259b01d08fdSWilliam A. Kennington III { 260b01d08fdSWilliam A. Kennington III constexpr ether_addr operator()(std::string_view str) const 261b01d08fdSWilliam A. Kennington III { 262b01d08fdSWilliam A. Kennington III constexpr DecodeInt<uint8_t, 16> di; 263b01d08fdSWilliam A. Kennington III ether_addr ret; 264b01d08fdSWilliam A. Kennington III if (str.size() == 12 && str.find(":") == str.npos) 265b01d08fdSWilliam A. Kennington III { 266b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 267b01d08fdSWilliam A. Kennington III { 268b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(i * 2, 2)); 269b01d08fdSWilliam A. Kennington III } 270b01d08fdSWilliam A. Kennington III } 271b01d08fdSWilliam A. Kennington III else 272b01d08fdSWilliam A. Kennington III { 273b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 5; ++i) 274b01d08fdSWilliam A. Kennington III { 275b01d08fdSWilliam A. Kennington III auto loc = str.find(":"); 276b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(0, loc)); 277b01d08fdSWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 278b01d08fdSWilliam A. Kennington III if (str.empty()) 279b01d08fdSWilliam A. Kennington III { 280b01d08fdSWilliam A. Kennington III throw std::invalid_argument("Missing mac data"); 281b01d08fdSWilliam A. Kennington III } 282b01d08fdSWilliam A. Kennington III } 283b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[5] = di(str); 284b01d08fdSWilliam A. Kennington III } 285b01d08fdSWilliam A. Kennington III return ret; 286b01d08fdSWilliam A. Kennington III } 287b01d08fdSWilliam A. Kennington III }; 288b01d08fdSWilliam A. Kennington III 289*df1178e0SWilliam A. Kennington III template <> 290*df1178e0SWilliam A. Kennington III struct ToAddr<in_addr> 291*df1178e0SWilliam A. Kennington III { 292*df1178e0SWilliam A. Kennington III constexpr in_addr operator()(std::string_view str) const 293*df1178e0SWilliam A. Kennington III { 294*df1178e0SWilliam A. Kennington III constexpr DecodeInt<uint8_t, 10> di; 295*df1178e0SWilliam A. Kennington III uint32_t addr = {}; 296*df1178e0SWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 297*df1178e0SWilliam A. Kennington III { 298*df1178e0SWilliam A. Kennington III auto loc = str.find("."); 299*df1178e0SWilliam A. Kennington III addr |= di(str.substr(0, loc)); 300*df1178e0SWilliam A. Kennington III addr <<= 8; 301*df1178e0SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 302*df1178e0SWilliam A. Kennington III if (str.empty()) 303*df1178e0SWilliam A. Kennington III { 304*df1178e0SWilliam A. Kennington III throw std::invalid_argument("Missing addr data"); 305*df1178e0SWilliam A. Kennington III } 306*df1178e0SWilliam A. Kennington III } 307*df1178e0SWilliam A. Kennington III addr |= di(str); 308*df1178e0SWilliam A. Kennington III return {hton(addr)}; 309*df1178e0SWilliam A. Kennington III } 310*df1178e0SWilliam A. Kennington III }; 311*df1178e0SWilliam A. Kennington III 312238ef992SWilliam A. Kennington III namespace detail 313238ef992SWilliam A. Kennington III { 31471de63a2SWilliam A. Kennington III 315bb0eaccbSWilliam A. Kennington III template <typename T> 316bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 317bb0eaccbSWilliam A. Kennington III { 318bb0eaccbSWilliam A. Kennington III return false; 319bb0eaccbSWilliam A. Kennington III } 320bb0eaccbSWilliam A. Kennington III 321bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 322bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 323bb0eaccbSWilliam A. Kennington III { 324bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 325bb0eaccbSWilliam A. Kennington III } 326bb0eaccbSWilliam A. Kennington III 327bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 328bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 329bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 330bb0eaccbSWilliam A. Kennington III { 331bb0eaccbSWilliam A. Kennington III return std::visit( 332bb0eaccbSWilliam A. Kennington III [t](auto v) { 333bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 334bb0eaccbSWilliam A. Kennington III { 335bb0eaccbSWilliam A. Kennington III return v == t; 336bb0eaccbSWilliam A. Kennington III } 337bb0eaccbSWilliam A. Kennington III else 338bb0eaccbSWilliam A. Kennington III { 339bb0eaccbSWilliam A. Kennington III return false; 340bb0eaccbSWilliam A. Kennington III } 341bb0eaccbSWilliam A. Kennington III }, 342bb0eaccbSWilliam A. Kennington III v); 343bb0eaccbSWilliam A. Kennington III } 344bb0eaccbSWilliam A. Kennington III 345bb0eaccbSWilliam A. Kennington III template <typename T> 346bb0eaccbSWilliam A. Kennington III struct AddrBufMaker 347bb0eaccbSWilliam A. Kennington III { 348bb0eaccbSWilliam A. Kennington III }; 349bb0eaccbSWilliam A. Kennington III 350bb0eaccbSWilliam A. Kennington III template <> 351bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<ether_addr> 352bb0eaccbSWilliam A. Kennington III { 353bb0eaccbSWilliam A. Kennington III public: 354bb0eaccbSWilliam A. Kennington III std::string_view operator()(ether_addr val) noexcept; 355bb0eaccbSWilliam A. Kennington III 356bb0eaccbSWilliam A. Kennington III private: 357bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf; 358bb0eaccbSWilliam A. Kennington III }; 359bb0eaccbSWilliam A. Kennington III 360bb0eaccbSWilliam A. Kennington III template <> 361bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in_addr> 362bb0eaccbSWilliam A. Kennington III { 363bb0eaccbSWilliam A. Kennington III public: 364bb0eaccbSWilliam A. Kennington III std::string_view operator()(in_addr val) noexcept; 365bb0eaccbSWilliam A. Kennington III 366bb0eaccbSWilliam A. Kennington III private: 367bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf; 368bb0eaccbSWilliam A. Kennington III }; 369bb0eaccbSWilliam A. Kennington III 370bb0eaccbSWilliam A. Kennington III template <> 371bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in6_addr> 372bb0eaccbSWilliam A. Kennington III { 373bb0eaccbSWilliam A. Kennington III public: 374bb0eaccbSWilliam A. Kennington III std::string_view operator()(in6_addr val) noexcept; 375bb0eaccbSWilliam A. Kennington III 376bb0eaccbSWilliam A. Kennington III private: 377bb0eaccbSWilliam A. Kennington III std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf; 378bb0eaccbSWilliam A. Kennington III }; 379bb0eaccbSWilliam A. Kennington III 380bb0eaccbSWilliam A. Kennington III template <typename BufMaker> 381bb0eaccbSWilliam A. Kennington III struct FormatFromBuf 382bb0eaccbSWilliam A. Kennington III { 383bb0eaccbSWilliam A. Kennington III private: 384bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 385bb0eaccbSWilliam A. Kennington III 386bb0eaccbSWilliam A. Kennington III public: 387bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 388bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 389bb0eaccbSWilliam A. Kennington III { 390bb0eaccbSWilliam A. Kennington III return ctx.begin(); 391bb0eaccbSWilliam A. Kennington III } 392bb0eaccbSWilliam A. Kennington III 393bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 394bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 395bb0eaccbSWilliam A. Kennington III { 396bb0eaccbSWilliam A. Kennington III return formatter.format(BufMaker{}(v), ctx); 397bb0eaccbSWilliam A. Kennington III } 398bb0eaccbSWilliam A. Kennington III }; 399bb0eaccbSWilliam A. Kennington III } // namespace detail 4001bbe3d1eSWilliam A. Kennington III } // namespace network 4011bbe3d1eSWilliam A. Kennington III } // namespace phosphor 4023e471c5fSWilliam A. Kennington III 4033e471c5fSWilliam A. Kennington III template <typename... Ts> 4043e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 4053e471c5fSWilliam A. Kennington III { 4063e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 4073e471c5fSWilliam A. Kennington III { 4083e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 4093e471c5fSWilliam A. Kennington III } 4103e471c5fSWilliam A. Kennington III }; 411bb0eaccbSWilliam A. Kennington III 412653114fcSWilliam A. Kennington III template <> 413653114fcSWilliam A. Kennington III struct std::hash<in_addr> 414653114fcSWilliam A. Kennington III { 415653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 416653114fcSWilliam A. Kennington III }; 417653114fcSWilliam A. Kennington III 418653114fcSWilliam A. Kennington III template <> 419653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 420653114fcSWilliam A. Kennington III { 421653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 422653114fcSWilliam A. Kennington III }; 423653114fcSWilliam A. Kennington III 424b9d7cbacSWilliam A. Kennington III template <> 425b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr> 426b9d7cbacSWilliam A. Kennington III { 427b9d7cbacSWilliam A. Kennington III std::size_t operator()(phosphor::network::IfAddr addr) const noexcept; 428b9d7cbacSWilliam A. Kennington III }; 429b9d7cbacSWilliam A. Kennington III 430bb0eaccbSWilliam A. Kennington III namespace fmt 431bb0eaccbSWilliam A. Kennington III { 432bb0eaccbSWilliam A. Kennington III template <> 433bb0eaccbSWilliam A. Kennington III struct formatter<ether_addr> 434bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 435bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<ether_addr>> 436bb0eaccbSWilliam A. Kennington III { 437bb0eaccbSWilliam A. Kennington III }; 438bb0eaccbSWilliam A. Kennington III template <> 439bb0eaccbSWilliam A. Kennington III struct formatter<in_addr> 440bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 441bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in_addr>> 442bb0eaccbSWilliam A. Kennington III { 443bb0eaccbSWilliam A. Kennington III }; 444bb0eaccbSWilliam A. Kennington III template <> 445bb0eaccbSWilliam A. Kennington III struct formatter<in6_addr> 446bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 447bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in6_addr>> 448bb0eaccbSWilliam A. Kennington III { 449bb0eaccbSWilliam A. Kennington III }; 450bb0eaccbSWilliam A. Kennington III template <> 451bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny> 452bb0eaccbSWilliam A. Kennington III { 453bb0eaccbSWilliam A. Kennington III private: 454bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 455bb0eaccbSWilliam A. Kennington III 456bb0eaccbSWilliam A. Kennington III public: 457bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 458bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 459bb0eaccbSWilliam A. Kennington III { 460bb0eaccbSWilliam A. Kennington III return ctx.begin(); 461bb0eaccbSWilliam A. Kennington III } 462bb0eaccbSWilliam A. Kennington III 463bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 464bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 465bb0eaccbSWilliam A. Kennington III { 466bb0eaccbSWilliam A. Kennington III return std::visit( 467bb0eaccbSWilliam A. Kennington III [&](auto v) { 468bb0eaccbSWilliam A. Kennington III auto abm = 469bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<decltype(v)>{}; 470bb0eaccbSWilliam A. Kennington III return formatter.format(abm(v), ctx); 471bb0eaccbSWilliam A. Kennington III }, 472bb0eaccbSWilliam A. Kennington III v); 473bb0eaccbSWilliam A. Kennington III } 474bb0eaccbSWilliam A. Kennington III }; 475b9d7cbacSWilliam A. Kennington III template <> 476b9d7cbacSWilliam A. Kennington III struct formatter<phosphor::network::IfAddr> 477b9d7cbacSWilliam A. Kennington III { 478b9d7cbacSWilliam A. Kennington III private: 479b9d7cbacSWilliam A. Kennington III fmt::formatter<phosphor::network::InAddrAny> addrF; 480b9d7cbacSWilliam A. Kennington III fmt::formatter<char> strF; 481b9d7cbacSWilliam A. Kennington III fmt::formatter<uint8_t> numF; 482b9d7cbacSWilliam A. Kennington III 483b9d7cbacSWilliam A. Kennington III public: 484b9d7cbacSWilliam A. Kennington III template <typename ParseContext> 485b9d7cbacSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 486b9d7cbacSWilliam A. Kennington III { 487b9d7cbacSWilliam A. Kennington III return ctx.begin(); 488b9d7cbacSWilliam A. Kennington III } 489b9d7cbacSWilliam A. Kennington III 490b9d7cbacSWilliam A. Kennington III template <typename FormatContext> 491b9d7cbacSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 492b9d7cbacSWilliam A. Kennington III { 493b9d7cbacSWilliam A. Kennington III addrF.format(v.getAddr(), ctx); 494b9d7cbacSWilliam A. Kennington III strF.format('/', ctx); 495b9d7cbacSWilliam A. Kennington III return numF.format(v.getPfx(), ctx); 496b9d7cbacSWilliam A. Kennington III } 497b9d7cbacSWilliam A. Kennington III }; 498bb0eaccbSWilliam A. Kennington III } // namespace fmt 499bb0eaccbSWilliam A. Kennington III 500bb0eaccbSWilliam A. Kennington III namespace std 501bb0eaccbSWilliam A. Kennington III { 502bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 503bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 504bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 505bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 506b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value); 507bb0eaccbSWilliam A. Kennington III } // namespace std 508bb0eaccbSWilliam A. Kennington III 509bb0eaccbSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 510bb0eaccbSWilliam A. Kennington III { 511bb0eaccbSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 512bb0eaccbSWilliam A. Kennington III rhs.ether_addr_octet); 513bb0eaccbSWilliam A. Kennington III } 514bb0eaccbSWilliam A. Kennington III 515bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 516bb0eaccbSWilliam A. Kennington III { 517bb0eaccbSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 518bb0eaccbSWilliam A. Kennington III } 519bb0eaccbSWilliam A. Kennington III 520bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 521bb0eaccbSWilliam A. Kennington III { 522bb0eaccbSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 523bb0eaccbSWilliam A. Kennington III } 524bb0eaccbSWilliam A. Kennington III 525bb0eaccbSWilliam A. Kennington III template <typename T> 526bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 527bb0eaccbSWilliam A. Kennington III bool> 528bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 529bb0eaccbSWilliam A. Kennington III { 530bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 531bb0eaccbSWilliam A. Kennington III } 532bb0eaccbSWilliam A. Kennington III 53386eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 534bb0eaccbSWilliam A. Kennington III { 535bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v); 536bb0eaccbSWilliam A. Kennington III } 537bb0eaccbSWilliam A. Kennington III 53886eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 539bb0eaccbSWilliam A. Kennington III { 540bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v); 541bb0eaccbSWilliam A. Kennington III } 542bb0eaccbSWilliam A. Kennington III 54386eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 544bb0eaccbSWilliam A. Kennington III { 545bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v); 546bb0eaccbSWilliam A. Kennington III } 547bb0eaccbSWilliam A. Kennington III 54886eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 549bb0eaccbSWilliam A. Kennington III { 550bb0eaccbSWilliam A. Kennington III return os << std::visit( 551bb0eaccbSWilliam A. Kennington III [](auto v) { 552bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::AddrBufMaker< 553bb0eaccbSWilliam A. Kennington III decltype(v)>{}(v); 554bb0eaccbSWilliam A. Kennington III }, 555bb0eaccbSWilliam A. Kennington III v); 556bb0eaccbSWilliam A. Kennington III } 557b9d7cbacSWilliam A. Kennington III 558b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v) 559b9d7cbacSWilliam A. Kennington III { 560b9d7cbacSWilliam A. Kennington III return os << v.getAddr() << "/" << std::dec << int{v.getPfx()}; 561b9d7cbacSWilliam A. Kennington III } 562