xref: /openbmc/phosphor-networkd/src/types.hpp (revision dd7c7b34)
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 }();
201*dd7c7b34SWilliam A. Kennington III inline constexpr auto intLookup = []() {
202*dd7c7b34SWilliam A. Kennington III     std::array<char, 36> ret;
203*dd7c7b34SWilliam A. Kennington III     for (int8_t i = 0; i < 10; ++i)
204*dd7c7b34SWilliam A. Kennington III     {
205*dd7c7b34SWilliam A. Kennington III         ret[i] = i + '0';
206238ef992SWilliam A. Kennington III     }
207*dd7c7b34SWilliam A. Kennington III     for (int8_t i = 0; i < 26; ++i)
208*dd7c7b34SWilliam A. Kennington III     {
209*dd7c7b34SWilliam A. Kennington III         ret[i + 10] = i + 'a';
210*dd7c7b34SWilliam A. Kennington III     }
211*dd7c7b34SWilliam A. Kennington III     return ret;
212*dd7c7b34SWilliam A. Kennington III }();
213*dd7c7b34SWilliam A. Kennington III } // namespace detail
214238ef992SWilliam A. Kennington III 
215238ef992SWilliam A. Kennington III template <typename T, uint8_t base>
216238ef992SWilliam A. Kennington III struct DecodeInt
217238ef992SWilliam A. Kennington III {
218238ef992SWilliam A. Kennington III     static_assert(base > 1 && base <= 36);
219238ef992SWilliam A. Kennington III     static_assert(std::is_unsigned_v<T>);
220238ef992SWilliam A. Kennington III 
221238ef992SWilliam A. Kennington III     constexpr T operator()(std::string_view str) const
222238ef992SWilliam A. Kennington III     {
223238ef992SWilliam A. Kennington III         if (str.empty())
224238ef992SWilliam A. Kennington III         {
225238ef992SWilliam A. Kennington III             throw std::invalid_argument("Empty Str");
226238ef992SWilliam A. Kennington III         }
227238ef992SWilliam A. Kennington III         constexpr auto max = std::numeric_limits<T>::max();
228238ef992SWilliam A. Kennington III         auto ret =
229238ef992SWilliam A. Kennington III             std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
230238ef992SWilliam A. Kennington III                 auto v = detail::charLookup[c];
231238ef992SWilliam A. Kennington III                 if (v < 0 || v >= base)
232238ef992SWilliam A. Kennington III                 {
233238ef992SWilliam A. Kennington III                     throw std::invalid_argument("Invalid numeral");
234238ef992SWilliam A. Kennington III                 }
235238ef992SWilliam A. Kennington III                 if constexpr (std::popcount(base) == 1)
236238ef992SWilliam A. Kennington III                 {
237238ef992SWilliam A. Kennington III                     constexpr auto shift = std::countr_zero(base);
238238ef992SWilliam A. Kennington III                     constexpr auto maxshift = max >> shift;
239238ef992SWilliam A. Kennington III                     if (r > maxshift)
240238ef992SWilliam A. Kennington III                     {
241238ef992SWilliam A. Kennington III                         throw std::overflow_error("Integer Decode");
242238ef992SWilliam A. Kennington III                     }
243238ef992SWilliam A. Kennington III                     return (r << shift) | v;
244238ef992SWilliam A. Kennington III                 }
245238ef992SWilliam A. Kennington III                 else
246238ef992SWilliam A. Kennington III                 {
247238ef992SWilliam A. Kennington III                     constexpr auto maxbase = max / base;
248238ef992SWilliam A. Kennington III                     if (r > maxbase)
249238ef992SWilliam A. Kennington III                     {
250238ef992SWilliam A. Kennington III                         throw std::overflow_error("Integer Decode");
251238ef992SWilliam A. Kennington III                     }
252238ef992SWilliam A. Kennington III                     r *= base;
253238ef992SWilliam A. Kennington III                     if (max - v < r)
254238ef992SWilliam A. Kennington III                     {
255238ef992SWilliam A. Kennington III                         throw std::overflow_error("Integer Decode");
256238ef992SWilliam A. Kennington III                     }
257238ef992SWilliam A. Kennington III                     return r + v;
258238ef992SWilliam A. Kennington III                 }
259238ef992SWilliam A. Kennington III             });
260238ef992SWilliam A. Kennington III         return ret;
261238ef992SWilliam A. Kennington III     }
262238ef992SWilliam A. Kennington III };
263238ef992SWilliam A. Kennington III 
264*dd7c7b34SWilliam A. Kennington III template <typename T, uint8_t base>
265*dd7c7b34SWilliam A. Kennington III struct EncodeInt
266*dd7c7b34SWilliam A. Kennington III {
267*dd7c7b34SWilliam A. Kennington III     static_assert(base > 1 && base <= 36);
268*dd7c7b34SWilliam A. Kennington III     static_assert(std::is_unsigned_v<T>);
269*dd7c7b34SWilliam A. Kennington III 
270*dd7c7b34SWilliam A. Kennington III     static constexpr uint8_t buf_size = []() {
271*dd7c7b34SWilliam A. Kennington III         T v = std::numeric_limits<T>::max();
272*dd7c7b34SWilliam A. Kennington III         uint8_t i = 0;
273*dd7c7b34SWilliam A. Kennington III         for (; v != 0; ++i)
274*dd7c7b34SWilliam A. Kennington III         {
275*dd7c7b34SWilliam A. Kennington III             v /= base;
276*dd7c7b34SWilliam A. Kennington III         }
277*dd7c7b34SWilliam A. Kennington III         return i;
278*dd7c7b34SWilliam A. Kennington III     }();
279*dd7c7b34SWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
280*dd7c7b34SWilliam A. Kennington III 
281*dd7c7b34SWilliam A. Kennington III     constexpr uint8_t reverseFill(char* buf, T v) const noexcept
282*dd7c7b34SWilliam A. Kennington III     {
283*dd7c7b34SWilliam A. Kennington III         uint8_t i = 0;
284*dd7c7b34SWilliam A. Kennington III         do
285*dd7c7b34SWilliam A. Kennington III         {
286*dd7c7b34SWilliam A. Kennington III             if constexpr (std::popcount(base) == 1)
287*dd7c7b34SWilliam A. Kennington III             {
288*dd7c7b34SWilliam A. Kennington III                 buf[i++] = detail::intLookup[v & 0xf];
289*dd7c7b34SWilliam A. Kennington III                 v >>= 4;
290*dd7c7b34SWilliam A. Kennington III             }
291*dd7c7b34SWilliam A. Kennington III             else
292*dd7c7b34SWilliam A. Kennington III             {
293*dd7c7b34SWilliam A. Kennington III                 buf[i++] = detail::intLookup[v % base];
294*dd7c7b34SWilliam A. Kennington III                 v /= base;
295*dd7c7b34SWilliam A. Kennington III             }
296*dd7c7b34SWilliam A. Kennington III         } while (v > 0);
297*dd7c7b34SWilliam A. Kennington III         return i;
298*dd7c7b34SWilliam A. Kennington III     }
299*dd7c7b34SWilliam A. Kennington III 
300*dd7c7b34SWilliam A. Kennington III     constexpr char* operator()(char* buf, T v) const noexcept
301*dd7c7b34SWilliam A. Kennington III     {
302*dd7c7b34SWilliam A. Kennington III         uint8_t i = reverseFill(buf, v);
303*dd7c7b34SWilliam A. Kennington III         std::reverse(buf, buf + i);
304*dd7c7b34SWilliam A. Kennington III         return buf + i;
305*dd7c7b34SWilliam A. Kennington III     }
306*dd7c7b34SWilliam A. Kennington III 
307*dd7c7b34SWilliam A. Kennington III     constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
308*dd7c7b34SWilliam A. Kennington III     {
309*dd7c7b34SWilliam A. Kennington III         uint8_t i = reverseFill(buf, v);
310*dd7c7b34SWilliam A. Kennington III         auto end = buf + std::max(i, min_width);
311*dd7c7b34SWilliam A. Kennington III         std::fill(buf + i, end, '0');
312*dd7c7b34SWilliam A. Kennington III         std::reverse(buf, end);
313*dd7c7b34SWilliam A. Kennington III         return end;
314*dd7c7b34SWilliam A. Kennington III     }
315*dd7c7b34SWilliam A. Kennington III };
316*dd7c7b34SWilliam A. Kennington III 
317b01d08fdSWilliam A. Kennington III template <typename T>
318b01d08fdSWilliam A. Kennington III struct ToAddr
319b01d08fdSWilliam A. Kennington III {
320b01d08fdSWilliam A. Kennington III };
321b01d08fdSWilliam A. Kennington III 
322b01d08fdSWilliam A. Kennington III template <>
323b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr>
324b01d08fdSWilliam A. Kennington III {
325b01d08fdSWilliam A. Kennington III     constexpr ether_addr operator()(std::string_view str) const
326b01d08fdSWilliam A. Kennington III     {
327b01d08fdSWilliam A. Kennington III         constexpr DecodeInt<uint8_t, 16> di;
328b01d08fdSWilliam A. Kennington III         ether_addr ret;
329b01d08fdSWilliam A. Kennington III         if (str.size() == 12 && str.find(":") == str.npos)
330b01d08fdSWilliam A. Kennington III         {
331b01d08fdSWilliam A. Kennington III             for (size_t i = 0; i < 6; ++i)
332b01d08fdSWilliam A. Kennington III             {
333b01d08fdSWilliam A. Kennington III                 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
334b01d08fdSWilliam A. Kennington III             }
335b01d08fdSWilliam A. Kennington III         }
336b01d08fdSWilliam A. Kennington III         else
337b01d08fdSWilliam A. Kennington III         {
338b01d08fdSWilliam A. Kennington III             for (size_t i = 0; i < 5; ++i)
339b01d08fdSWilliam A. Kennington III             {
340b01d08fdSWilliam A. Kennington III                 auto loc = str.find(":");
341b01d08fdSWilliam A. Kennington III                 ret.ether_addr_octet[i] = di(str.substr(0, loc));
342b01d08fdSWilliam A. Kennington III                 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
343b01d08fdSWilliam A. Kennington III                 if (str.empty())
344b01d08fdSWilliam A. Kennington III                 {
345b01d08fdSWilliam A. Kennington III                     throw std::invalid_argument("Missing mac data");
346b01d08fdSWilliam A. Kennington III                 }
347b01d08fdSWilliam A. Kennington III             }
348b01d08fdSWilliam A. Kennington III             ret.ether_addr_octet[5] = di(str);
349b01d08fdSWilliam A. Kennington III         }
350b01d08fdSWilliam A. Kennington III         return ret;
351b01d08fdSWilliam A. Kennington III     }
352b01d08fdSWilliam A. Kennington III };
353b01d08fdSWilliam A. Kennington III 
354df1178e0SWilliam A. Kennington III template <>
355df1178e0SWilliam A. Kennington III struct ToAddr<in_addr>
356df1178e0SWilliam A. Kennington III {
357df1178e0SWilliam A. Kennington III     constexpr in_addr operator()(std::string_view str) const
358df1178e0SWilliam A. Kennington III     {
359df1178e0SWilliam A. Kennington III         constexpr DecodeInt<uint8_t, 10> di;
360df1178e0SWilliam A. Kennington III         uint32_t addr = {};
361df1178e0SWilliam A. Kennington III         for (size_t i = 0; i < 3; ++i)
362df1178e0SWilliam A. Kennington III         {
363df1178e0SWilliam A. Kennington III             auto loc = str.find(".");
364df1178e0SWilliam A. Kennington III             addr |= di(str.substr(0, loc));
365df1178e0SWilliam A. Kennington III             addr <<= 8;
366df1178e0SWilliam A. Kennington III             str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
367df1178e0SWilliam A. Kennington III             if (str.empty())
368df1178e0SWilliam A. Kennington III             {
369df1178e0SWilliam A. Kennington III                 throw std::invalid_argument("Missing addr data");
370df1178e0SWilliam A. Kennington III             }
371df1178e0SWilliam A. Kennington III         }
372df1178e0SWilliam A. Kennington III         addr |= di(str);
373df1178e0SWilliam A. Kennington III         return {hton(addr)};
374df1178e0SWilliam A. Kennington III     }
375df1178e0SWilliam A. Kennington III };
376df1178e0SWilliam A. Kennington III 
377ec496a86SWilliam A. Kennington III template <>
378ec496a86SWilliam A. Kennington III struct ToAddr<in6_addr>
379ec496a86SWilliam A. Kennington III {
380ec496a86SWilliam A. Kennington III     constexpr in6_addr operator()(std::string_view str) const
381ec496a86SWilliam A. Kennington III     {
382ec496a86SWilliam A. Kennington III         constexpr DecodeInt<uint16_t, 16> di;
383ec496a86SWilliam A. Kennington III         in6_addr ret = {};
384ec496a86SWilliam A. Kennington III         size_t i = 0;
385ec496a86SWilliam A. Kennington III         while (i < 8)
386ec496a86SWilliam A. Kennington III         {
387ec496a86SWilliam A. Kennington III             auto loc = str.find(':');
388ec496a86SWilliam A. Kennington III             if (i == 6 && loc == str.npos)
389ec496a86SWilliam A. Kennington III             {
390ec496a86SWilliam A. Kennington III                 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
391ec496a86SWilliam A. Kennington III                 return ret;
392ec496a86SWilliam A. Kennington III             }
393ec496a86SWilliam A. Kennington III             if (loc != 0 && !str.empty())
394ec496a86SWilliam A. Kennington III             {
395ec496a86SWilliam A. Kennington III                 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
396ec496a86SWilliam A. Kennington III             }
397ec496a86SWilliam A. Kennington III             if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
398ec496a86SWilliam A. Kennington III             {
399ec496a86SWilliam A. Kennington III                 str.remove_prefix(loc + 2);
400ec496a86SWilliam A. Kennington III                 break;
401ec496a86SWilliam A. Kennington III             }
402ec496a86SWilliam A. Kennington III             else if (str.empty())
403ec496a86SWilliam A. Kennington III             {
404ec496a86SWilliam A. Kennington III                 throw std::invalid_argument("IPv6 Data");
405ec496a86SWilliam A. Kennington III             }
406ec496a86SWilliam A. Kennington III             str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
407ec496a86SWilliam A. Kennington III         }
408ec496a86SWilliam A. Kennington III         if (str.starts_with(':'))
409ec496a86SWilliam A. Kennington III         {
410ec496a86SWilliam A. Kennington III             throw std::invalid_argument("Extra separator");
411ec496a86SWilliam A. Kennington III         }
412ec496a86SWilliam A. Kennington III         size_t j = 7;
413ec496a86SWilliam A. Kennington III         if (!str.empty() && i < 6 && str.find('.') != str.npos)
414ec496a86SWilliam A. Kennington III         {
415ec496a86SWilliam A. Kennington III             auto loc = str.rfind(':');
416ec496a86SWilliam A. Kennington III             ret.s6_addr32[3] =
417ec496a86SWilliam A. Kennington III                 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
418ec496a86SWilliam A. Kennington III                     .s_addr;
419ec496a86SWilliam A. Kennington III             str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
420ec496a86SWilliam A. Kennington III             j -= 2;
421ec496a86SWilliam A. Kennington III         }
422ec496a86SWilliam A. Kennington III         while (!str.empty() && j > i)
423ec496a86SWilliam A. Kennington III         {
424ec496a86SWilliam A. Kennington III             auto loc = str.rfind(':');
425ec496a86SWilliam A. Kennington III             ret.s6_addr16[j--] =
426ec496a86SWilliam A. Kennington III                 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
427ec496a86SWilliam A. Kennington III             str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
428ec496a86SWilliam A. Kennington III         }
429ec496a86SWilliam A. Kennington III         if (!str.empty())
430ec496a86SWilliam A. Kennington III         {
431ec496a86SWilliam A. Kennington III             throw std::invalid_argument("Too much data");
432ec496a86SWilliam A. Kennington III         }
433ec496a86SWilliam A. Kennington III         return ret;
434ec496a86SWilliam A. Kennington III     }
435ec496a86SWilliam A. Kennington III };
436ec496a86SWilliam A. Kennington III 
437ead7198cSWilliam A. Kennington III template <>
438ead7198cSWilliam A. Kennington III struct ToAddr<InAddrAny>
439ead7198cSWilliam A. Kennington III {
440ead7198cSWilliam A. Kennington III     constexpr InAddrAny operator()(std::string_view str) const
441ead7198cSWilliam A. Kennington III     {
442ead7198cSWilliam A. Kennington III         if (str.find(':') == str.npos)
443ead7198cSWilliam A. Kennington III         {
444ead7198cSWilliam A. Kennington III             return ToAddr<in_addr>{}(str);
445ead7198cSWilliam A. Kennington III         }
446ead7198cSWilliam A. Kennington III         return ToAddr<in6_addr>{}(str);
447ead7198cSWilliam A. Kennington III     }
448ead7198cSWilliam A. Kennington III };
449ead7198cSWilliam A. Kennington III 
450ead7198cSWilliam A. Kennington III template <>
451ead7198cSWilliam A. Kennington III struct ToAddr<IfAddr>
452ead7198cSWilliam A. Kennington III {
453ead7198cSWilliam A. Kennington III     constexpr IfAddr operator()(std::string_view str) const
454ead7198cSWilliam A. Kennington III     {
455ead7198cSWilliam A. Kennington III         auto pos = str.rfind('/');
456ead7198cSWilliam A. Kennington III         if (pos == str.npos)
457ead7198cSWilliam A. Kennington III         {
458ead7198cSWilliam A. Kennington III             throw std::invalid_argument("Invalid IfAddr");
459ead7198cSWilliam A. Kennington III         }
460ead7198cSWilliam A. Kennington III         return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
461ead7198cSWilliam A. Kennington III                 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
462ead7198cSWilliam A. Kennington III     }
463ead7198cSWilliam A. Kennington III };
464ead7198cSWilliam A. Kennington III 
465238ef992SWilliam A. Kennington III namespace detail
466238ef992SWilliam A. Kennington III {
46771de63a2SWilliam A. Kennington III 
468bb0eaccbSWilliam A. Kennington III template <typename T>
469bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept
470bb0eaccbSWilliam A. Kennington III {
471bb0eaccbSWilliam A. Kennington III     return false;
472bb0eaccbSWilliam A. Kennington III }
473bb0eaccbSWilliam A. Kennington III 
474bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs>
475bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept
476bb0eaccbSWilliam A. Kennington III {
477bb0eaccbSWilliam A. Kennington III     return vcontains<T, Vs...>() || std::is_same_v<T, V>;
478bb0eaccbSWilliam A. Kennington III }
479bb0eaccbSWilliam A. Kennington III 
480bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types>
481bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
482bb0eaccbSWilliam A. Kennington III     veq(T t, std::variant<Types...> v) noexcept
483bb0eaccbSWilliam A. Kennington III {
484bb0eaccbSWilliam A. Kennington III     return std::visit(
485bb0eaccbSWilliam A. Kennington III         [t](auto v) {
486bb0eaccbSWilliam A. Kennington III             if constexpr (std::is_same_v<T, decltype(v)>)
487bb0eaccbSWilliam A. Kennington III             {
488bb0eaccbSWilliam A. Kennington III                 return v == t;
489bb0eaccbSWilliam A. Kennington III             }
490bb0eaccbSWilliam A. Kennington III             else
491bb0eaccbSWilliam A. Kennington III             {
492bb0eaccbSWilliam A. Kennington III                 return false;
493bb0eaccbSWilliam A. Kennington III             }
494bb0eaccbSWilliam A. Kennington III         },
495bb0eaccbSWilliam A. Kennington III         v);
496bb0eaccbSWilliam A. Kennington III }
497bb0eaccbSWilliam A. Kennington III 
498bb0eaccbSWilliam A. Kennington III template <typename T>
499bb0eaccbSWilliam A. Kennington III struct AddrBufMaker
500bb0eaccbSWilliam A. Kennington III {
501bb0eaccbSWilliam A. Kennington III };
502bb0eaccbSWilliam A. Kennington III 
503bb0eaccbSWilliam A. Kennington III template <>
504bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<ether_addr>
505bb0eaccbSWilliam A. Kennington III {
506bb0eaccbSWilliam A. Kennington III   public:
507bb0eaccbSWilliam A. Kennington III     std::string_view operator()(ether_addr val) noexcept;
508bb0eaccbSWilliam A. Kennington III 
509bb0eaccbSWilliam A. Kennington III   private:
510bb0eaccbSWilliam A. Kennington III     std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf;
511bb0eaccbSWilliam A. Kennington III };
512bb0eaccbSWilliam A. Kennington III 
513bb0eaccbSWilliam A. Kennington III template <>
514bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in_addr>
515bb0eaccbSWilliam A. Kennington III {
516bb0eaccbSWilliam A. Kennington III   public:
517bb0eaccbSWilliam A. Kennington III     std::string_view operator()(in_addr val) noexcept;
518bb0eaccbSWilliam A. Kennington III 
519bb0eaccbSWilliam A. Kennington III   private:
520bb0eaccbSWilliam A. Kennington III     std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf;
521bb0eaccbSWilliam A. Kennington III };
522bb0eaccbSWilliam A. Kennington III 
523bb0eaccbSWilliam A. Kennington III template <>
524bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in6_addr>
525bb0eaccbSWilliam A. Kennington III {
526bb0eaccbSWilliam A. Kennington III   public:
527bb0eaccbSWilliam A. Kennington III     std::string_view operator()(in6_addr val) noexcept;
528bb0eaccbSWilliam A. Kennington III 
529bb0eaccbSWilliam A. Kennington III   private:
530bb0eaccbSWilliam A. Kennington III     std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf;
531bb0eaccbSWilliam A. Kennington III };
532bb0eaccbSWilliam A. Kennington III 
533bb0eaccbSWilliam A. Kennington III template <typename BufMaker>
534bb0eaccbSWilliam A. Kennington III struct FormatFromBuf
535bb0eaccbSWilliam A. Kennington III {
536bb0eaccbSWilliam A. Kennington III   private:
537bb0eaccbSWilliam A. Kennington III     fmt::formatter<std::string_view> formatter;
538bb0eaccbSWilliam A. Kennington III 
539bb0eaccbSWilliam A. Kennington III   public:
540bb0eaccbSWilliam A. Kennington III     template <typename ParseContext>
541bb0eaccbSWilliam A. Kennington III     constexpr auto parse(ParseContext& ctx)
542bb0eaccbSWilliam A. Kennington III     {
543bb0eaccbSWilliam A. Kennington III         return ctx.begin();
544bb0eaccbSWilliam A. Kennington III     }
545bb0eaccbSWilliam A. Kennington III 
546bb0eaccbSWilliam A. Kennington III     template <typename FormatContext>
547bb0eaccbSWilliam A. Kennington III     auto format(auto v, FormatContext& ctx) const
548bb0eaccbSWilliam A. Kennington III     {
549bb0eaccbSWilliam A. Kennington III         return formatter.format(BufMaker{}(v), ctx);
550bb0eaccbSWilliam A. Kennington III     }
551bb0eaccbSWilliam A. Kennington III };
552bb0eaccbSWilliam A. Kennington III } // namespace detail
5531bbe3d1eSWilliam A. Kennington III } // namespace network
5541bbe3d1eSWilliam A. Kennington III } // namespace phosphor
5553e471c5fSWilliam A. Kennington III 
5563e471c5fSWilliam A. Kennington III template <typename... Ts>
5573e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>>
5583e471c5fSWilliam A. Kennington III {
5593e471c5fSWilliam A. Kennington III     constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
5603e471c5fSWilliam A. Kennington III     {
5613e471c5fSWilliam A. Kennington III         return std::apply(phosphor::network::hash_multi<Ts...>, t);
5623e471c5fSWilliam A. Kennington III     }
5633e471c5fSWilliam A. Kennington III };
564bb0eaccbSWilliam A. Kennington III 
565653114fcSWilliam A. Kennington III template <>
566653114fcSWilliam A. Kennington III struct std::hash<in_addr>
567653114fcSWilliam A. Kennington III {
568653114fcSWilliam A. Kennington III     std::size_t operator()(in_addr addr) const noexcept;
569653114fcSWilliam A. Kennington III };
570653114fcSWilliam A. Kennington III 
571653114fcSWilliam A. Kennington III template <>
572653114fcSWilliam A. Kennington III struct std::hash<in6_addr>
573653114fcSWilliam A. Kennington III {
574653114fcSWilliam A. Kennington III     std::size_t operator()(in6_addr addr) const noexcept;
575653114fcSWilliam A. Kennington III };
576653114fcSWilliam A. Kennington III 
577b9d7cbacSWilliam A. Kennington III template <>
578b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr>
579b9d7cbacSWilliam A. Kennington III {
580b9d7cbacSWilliam A. Kennington III     std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
581b9d7cbacSWilliam A. Kennington III };
582b9d7cbacSWilliam A. Kennington III 
583bb0eaccbSWilliam A. Kennington III namespace fmt
584bb0eaccbSWilliam A. Kennington III {
585bb0eaccbSWilliam A. Kennington III template <>
586bb0eaccbSWilliam A. Kennington III struct formatter<ether_addr>
587bb0eaccbSWilliam A. Kennington III     : phosphor::network::detail::FormatFromBuf<
588bb0eaccbSWilliam A. Kennington III           phosphor::network::detail::AddrBufMaker<ether_addr>>
589bb0eaccbSWilliam A. Kennington III {
590bb0eaccbSWilliam A. Kennington III };
591bb0eaccbSWilliam A. Kennington III template <>
592bb0eaccbSWilliam A. Kennington III struct formatter<in_addr>
593bb0eaccbSWilliam A. Kennington III     : phosphor::network::detail::FormatFromBuf<
594bb0eaccbSWilliam A. Kennington III           phosphor::network::detail::AddrBufMaker<in_addr>>
595bb0eaccbSWilliam A. Kennington III {
596bb0eaccbSWilliam A. Kennington III };
597bb0eaccbSWilliam A. Kennington III template <>
598bb0eaccbSWilliam A. Kennington III struct formatter<in6_addr>
599bb0eaccbSWilliam A. Kennington III     : phosphor::network::detail::FormatFromBuf<
600bb0eaccbSWilliam A. Kennington III           phosphor::network::detail::AddrBufMaker<in6_addr>>
601bb0eaccbSWilliam A. Kennington III {
602bb0eaccbSWilliam A. Kennington III };
603bb0eaccbSWilliam A. Kennington III template <>
604bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny>
605bb0eaccbSWilliam A. Kennington III {
606bb0eaccbSWilliam A. Kennington III   private:
607bb0eaccbSWilliam A. Kennington III     fmt::formatter<std::string_view> formatter;
608bb0eaccbSWilliam A. Kennington III 
609bb0eaccbSWilliam A. Kennington III   public:
610bb0eaccbSWilliam A. Kennington III     template <typename ParseContext>
611bb0eaccbSWilliam A. Kennington III     constexpr auto parse(ParseContext& ctx)
612bb0eaccbSWilliam A. Kennington III     {
613bb0eaccbSWilliam A. Kennington III         return ctx.begin();
614bb0eaccbSWilliam A. Kennington III     }
615bb0eaccbSWilliam A. Kennington III 
616bb0eaccbSWilliam A. Kennington III     template <typename FormatContext>
617bb0eaccbSWilliam A. Kennington III     auto format(auto v, FormatContext& ctx) const
618bb0eaccbSWilliam A. Kennington III     {
619bb0eaccbSWilliam A. Kennington III         return std::visit(
620bb0eaccbSWilliam A. Kennington III             [&](auto v) {
621bb0eaccbSWilliam A. Kennington III                 auto abm =
622bb0eaccbSWilliam A. Kennington III                     phosphor::network::detail::AddrBufMaker<decltype(v)>{};
623bb0eaccbSWilliam A. Kennington III                 return formatter.format(abm(v), ctx);
624bb0eaccbSWilliam A. Kennington III             },
625bb0eaccbSWilliam A. Kennington III             v);
626bb0eaccbSWilliam A. Kennington III     }
627bb0eaccbSWilliam A. Kennington III };
628b9d7cbacSWilliam A. Kennington III template <>
629b9d7cbacSWilliam A. Kennington III struct formatter<phosphor::network::IfAddr>
630b9d7cbacSWilliam A. Kennington III {
631b9d7cbacSWilliam A. Kennington III   private:
632b9d7cbacSWilliam A. Kennington III     fmt::formatter<phosphor::network::InAddrAny> addrF;
633b9d7cbacSWilliam A. Kennington III     fmt::formatter<char> strF;
634b9d7cbacSWilliam A. Kennington III     fmt::formatter<uint8_t> numF;
635b9d7cbacSWilliam A. Kennington III 
636b9d7cbacSWilliam A. Kennington III   public:
637b9d7cbacSWilliam A. Kennington III     template <typename ParseContext>
638b9d7cbacSWilliam A. Kennington III     constexpr auto parse(ParseContext& ctx)
639b9d7cbacSWilliam A. Kennington III     {
640b9d7cbacSWilliam A. Kennington III         return ctx.begin();
641b9d7cbacSWilliam A. Kennington III     }
642b9d7cbacSWilliam A. Kennington III 
643b9d7cbacSWilliam A. Kennington III     template <typename FormatContext>
644b9d7cbacSWilliam A. Kennington III     auto format(auto v, FormatContext& ctx) const
645b9d7cbacSWilliam A. Kennington III     {
646b9d7cbacSWilliam A. Kennington III         addrF.format(v.getAddr(), ctx);
647b9d7cbacSWilliam A. Kennington III         strF.format('/', ctx);
648b9d7cbacSWilliam A. Kennington III         return numF.format(v.getPfx(), ctx);
649b9d7cbacSWilliam A. Kennington III     }
650b9d7cbacSWilliam A. Kennington III };
651bb0eaccbSWilliam A. Kennington III } // namespace fmt
652bb0eaccbSWilliam A. Kennington III 
653bb0eaccbSWilliam A. Kennington III namespace std
654bb0eaccbSWilliam A. Kennington III {
655bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value);
656bb0eaccbSWilliam A. Kennington III string to_string(in_addr value);
657bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value);
658bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value);
659b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value);
660bb0eaccbSWilliam A. Kennington III } // namespace std
661bb0eaccbSWilliam A. Kennington III 
662bb0eaccbSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
663bb0eaccbSWilliam A. Kennington III {
664bb0eaccbSWilliam A. Kennington III     return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
665bb0eaccbSWilliam A. Kennington III                       rhs.ether_addr_octet);
666bb0eaccbSWilliam A. Kennington III }
667bb0eaccbSWilliam A. Kennington III 
668bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
669bb0eaccbSWilliam A. Kennington III {
670bb0eaccbSWilliam A. Kennington III     return lhs.s_addr == rhs.s_addr;
671bb0eaccbSWilliam A. Kennington III }
672bb0eaccbSWilliam A. Kennington III 
673bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
674bb0eaccbSWilliam A. Kennington III {
675bb0eaccbSWilliam A. Kennington III     return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
676bb0eaccbSWilliam A. Kennington III }
677bb0eaccbSWilliam A. Kennington III 
678bb0eaccbSWilliam A. Kennington III template <typename T>
679bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
680bb0eaccbSWilliam A. Kennington III                            bool>
681bb0eaccbSWilliam A. Kennington III     operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
682bb0eaccbSWilliam A. Kennington III {
683bb0eaccbSWilliam A. Kennington III     return phosphor::network::detail::veq(rhs, lhs);
684bb0eaccbSWilliam A. Kennington III }
685bb0eaccbSWilliam A. Kennington III 
68686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v)
687bb0eaccbSWilliam A. Kennington III {
688bb0eaccbSWilliam A. Kennington III     return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v);
689bb0eaccbSWilliam A. Kennington III }
690bb0eaccbSWilliam A. Kennington III 
69186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v)
692bb0eaccbSWilliam A. Kennington III {
693bb0eaccbSWilliam A. Kennington III     return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v);
694bb0eaccbSWilliam A. Kennington III }
695bb0eaccbSWilliam A. Kennington III 
69686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v)
697bb0eaccbSWilliam A. Kennington III {
698bb0eaccbSWilliam A. Kennington III     return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v);
699bb0eaccbSWilliam A. Kennington III }
700bb0eaccbSWilliam A. Kennington III 
70186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v)
702bb0eaccbSWilliam A. Kennington III {
703bb0eaccbSWilliam A. Kennington III     return os << std::visit(
704bb0eaccbSWilliam A. Kennington III                [](auto v) {
705bb0eaccbSWilliam A. Kennington III                    return phosphor::network::detail::AddrBufMaker<
706bb0eaccbSWilliam A. Kennington III                        decltype(v)>{}(v);
707bb0eaccbSWilliam A. Kennington III                },
708bb0eaccbSWilliam A. Kennington III                v);
709bb0eaccbSWilliam A. Kennington III }
710b9d7cbacSWilliam A. Kennington III 
711b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v)
712b9d7cbacSWilliam A. Kennington III {
713b9d7cbacSWilliam A. Kennington III     return os << v.getAddr() << "/" << std::dec << int{v.getPfx()};
714b9d7cbacSWilliam A. Kennington III }
715