blob: 4515211a2d3702c39fabafa786a897b21b78bd9f [file] [log] [blame]
Ratan Gupta82549cc2017-04-21 08:45:23 +05301#pragma once
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07002#include <fmt/core.h>
3#include <net/ethernet.h>
William A. Kennington III0d7ce482019-01-30 17:14:23 -08004#include <netinet/in.h>
Ratan Gupta3681a502017-06-17 19:20:04 +05305
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07006#include <algorithm>
7#include <array>
Patrick Venture189d44e2018-07-09 12:30:59 -07008#include <chrono>
William A. Kennington III71de63a2022-11-08 10:50:54 -08009#include <numeric>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070010#include <sdeventplus/clock.hpp>
11#include <sdeventplus/utility/timer.hpp>
Patrick Venture189d44e2018-07-09 12:30:59 -070012#include <string>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070013#include <string_view>
14#include <type_traits>
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070015#include <unordered_map>
Willy Tuf7dce2e2022-10-07 05:48:08 +000016#include <unordered_set>
William A. Kennington III0d7ce482019-01-30 17:14:23 -080017#include <variant>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053018
Ratan Gupta82549cc2017-04-21 08:45:23 +053019namespace phosphor
20{
21namespace network
22{
Ratan Guptae05083a2017-09-16 07:12:11 +053023
24using namespace std::chrono_literals;
Ratan Gupta16f12882017-09-22 18:26:11 +053025
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080026// wait for three seconds before reloading systemd-networkd
27constexpr auto reloadTimeout = 3s;
Ratan Gupta16f12882017-09-22 18:26:11 +053028
William A. Kennington IIId41db382021-11-09 20:42:29 -080029// refresh the objets after four seconds as network
30// configuration takes 3-4 sec to reconfigure at most.
31constexpr auto refreshTimeout = 4s;
Ratan Guptae05083a2017-09-16 07:12:11 +053032
William A. Kennington III0d7ce482019-01-30 17:14:23 -080033// Byte representations for common address types in network byte order
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070034using InAddrAny = std::variant<in_addr, in6_addr>;
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -080035class IfAddr
36{
37 private:
38 InAddrAny addr;
39 uint8_t pfx;
40
41 static void invalidPfx(uint8_t pfx);
42
43 public:
44 constexpr IfAddr() : addr({}), pfx(0)
45 {
46 }
47
48 constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx)
49 {
50 std::visit(
51 [pfx](auto v) {
52 if (sizeof(v) * 8 < pfx)
53 {
54 invalidPfx(pfx);
55 }
56 },
57 addr);
58 }
59
60 constexpr auto getAddr() const
61 {
62 return addr;
63 }
64
65 constexpr auto getPfx() const
66 {
67 return pfx;
68 }
69
70 constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept
71 {
72 return addr == rhs.addr && pfx == rhs.pfx;
73 }
74};
William A. Kennington III0d7ce482019-01-30 17:14:23 -080075
William A. Kennington III3a70fa22018-09-20 18:48:20 -070076using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
77
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070078struct string_hash : public std::hash<std::string_view>
79{
80 using is_transparent = void;
81};
82template <typename V>
83using string_umap =
84 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -070085using string_uset =
86 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070087
William A. Kennington III3e471c52022-10-27 19:46:07 -070088constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -070089{
90 return 0;
91}
92
93template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -070094constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -070095{
96 const std::size_t seed = hash_multi(args...);
97 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
98}
99
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700100namespace detail
101{
102
William A. Kennington III71de63a2022-11-08 10:50:54 -0800103template <typename T, uint8_t size = sizeof(T)>
104struct BswapAlign
105{
106 using type = T;
107};
108
109template <typename T>
110struct BswapAlign<T, 2>
111{
112 using type alignas(uint16_t) = T;
113};
114
115template <typename T>
116struct BswapAlign<T, 4>
117{
118 using type alignas(uint32_t) = T;
119};
120
121template <typename T>
122struct BswapAlign<T, 8>
123{
124 using type alignas(uint64_t) = T;
125};
126
127template <typename T>
128constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
129{
130 static_assert(std::is_trivially_copyable_v<T>);
131 if constexpr (sizeof(T) == 2)
132 {
133 reinterpret_cast<uint16_t&>(n) =
134 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
135 }
136 else if constexpr (sizeof(T) == 4)
137 {
138 reinterpret_cast<uint32_t&>(n) =
139 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
140 }
141 else if constexpr (sizeof(T) == 8)
142 {
143 reinterpret_cast<uint64_t&>(n) =
144 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
145 }
146 else
147 {
148 auto b = reinterpret_cast<std::byte*>(&n);
149 std::reverse(b, b + sizeof(n));
150 }
151 return n;
152}
153
154} // namespace detail
155
156template <typename T>
157constexpr T bswap(T n) noexcept
158{
159 return detail::bswapInt<T>(n);
160}
161
162template <typename T>
163constexpr T hton(T n) noexcept
164{
165 if constexpr (std::endian::native == std::endian::big)
166 {
167 return n;
168 }
169 else if constexpr (std::endian::native == std::endian::little)
170 {
171 return bswap(n);
172 }
173 else
174 {
175 static_assert(std::is_same_v<T, void>);
176 }
177}
178
179template <typename T>
180constexpr T ntoh(T n) noexcept
181{
182 return hton(n);
183}
184
185namespace detail
186{
William A. Kennington III238ef992022-11-03 12:47:49 -0700187inline constexpr auto charLookup = []() {
188 std::array<int8_t, 256> ret;
189 std::fill(ret.begin(), ret.end(), -1);
190 for (int8_t i = 0; i < 10; ++i)
191 {
192 ret[i + '0'] = i;
193 }
194 for (int8_t i = 0; i < 26; ++i)
195 {
196 ret[i + 'A'] = i + 10;
197 ret[i + 'a'] = i + 10;
198 }
199 return ret;
200}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700201inline constexpr auto intLookup = []() {
202 std::array<char, 36> ret;
203 for (int8_t i = 0; i < 10; ++i)
204 {
205 ret[i] = i + '0';
206 }
207 for (int8_t i = 0; i < 26; ++i)
208 {
209 ret[i + 10] = i + 'a';
210 }
211 return ret;
212}();
213} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700214
215template <typename T, uint8_t base>
216struct DecodeInt
217{
218 static_assert(base > 1 && base <= 36);
219 static_assert(std::is_unsigned_v<T>);
220
221 constexpr T operator()(std::string_view str) const
222 {
223 if (str.empty())
224 {
225 throw std::invalid_argument("Empty Str");
226 }
227 constexpr auto max = std::numeric_limits<T>::max();
228 auto ret =
229 std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
230 auto v = detail::charLookup[c];
231 if (v < 0 || v >= base)
232 {
233 throw std::invalid_argument("Invalid numeral");
234 }
235 if constexpr (std::popcount(base) == 1)
236 {
237 constexpr auto shift = std::countr_zero(base);
238 constexpr auto maxshift = max >> shift;
239 if (r > maxshift)
240 {
241 throw std::overflow_error("Integer Decode");
242 }
243 return (r << shift) | v;
244 }
245 else
246 {
247 constexpr auto maxbase = max / base;
248 if (r > maxbase)
249 {
250 throw std::overflow_error("Integer Decode");
251 }
252 r *= base;
253 if (max - v < r)
254 {
255 throw std::overflow_error("Integer Decode");
256 }
257 return r + v;
258 }
259 });
260 return ret;
261 }
262};
263
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700264template <typename T, uint8_t base>
265struct EncodeInt
266{
267 static_assert(base > 1 && base <= 36);
268 static_assert(std::is_unsigned_v<T>);
269
270 static constexpr uint8_t buf_size = []() {
271 T v = std::numeric_limits<T>::max();
272 uint8_t i = 0;
273 for (; v != 0; ++i)
274 {
275 v /= base;
276 }
277 return i;
278 }();
279 using buf_type = std::array<char, buf_size>;
280
281 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
282 {
283 uint8_t i = 0;
284 do
285 {
286 if constexpr (std::popcount(base) == 1)
287 {
288 buf[i++] = detail::intLookup[v & 0xf];
289 v >>= 4;
290 }
291 else
292 {
293 buf[i++] = detail::intLookup[v % base];
294 v /= base;
295 }
296 } while (v > 0);
297 return i;
298 }
299
300 constexpr char* operator()(char* buf, T v) const noexcept
301 {
302 uint8_t i = reverseFill(buf, v);
303 std::reverse(buf, buf + i);
304 return buf + i;
305 }
306
307 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
308 {
309 uint8_t i = reverseFill(buf, v);
310 auto end = buf + std::max(i, min_width);
311 std::fill(buf + i, end, '0');
312 std::reverse(buf, end);
313 return end;
314 }
315};
316
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700317template <typename T>
318struct ToAddr
319{
320};
321
322template <>
323struct ToAddr<ether_addr>
324{
325 constexpr ether_addr operator()(std::string_view str) const
326 {
327 constexpr DecodeInt<uint8_t, 16> di;
328 ether_addr ret;
329 if (str.size() == 12 && str.find(":") == str.npos)
330 {
331 for (size_t i = 0; i < 6; ++i)
332 {
333 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
334 }
335 }
336 else
337 {
338 for (size_t i = 0; i < 5; ++i)
339 {
340 auto loc = str.find(":");
341 ret.ether_addr_octet[i] = di(str.substr(0, loc));
342 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
343 if (str.empty())
344 {
345 throw std::invalid_argument("Missing mac data");
346 }
347 }
348 ret.ether_addr_octet[5] = di(str);
349 }
350 return ret;
351 }
352};
353
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700354template <>
355struct ToAddr<in_addr>
356{
357 constexpr in_addr operator()(std::string_view str) const
358 {
359 constexpr DecodeInt<uint8_t, 10> di;
360 uint32_t addr = {};
361 for (size_t i = 0; i < 3; ++i)
362 {
363 auto loc = str.find(".");
364 addr |= di(str.substr(0, loc));
365 addr <<= 8;
366 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
367 if (str.empty())
368 {
369 throw std::invalid_argument("Missing addr data");
370 }
371 }
372 addr |= di(str);
373 return {hton(addr)};
374 }
375};
376
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700377template <>
378struct ToAddr<in6_addr>
379{
380 constexpr in6_addr operator()(std::string_view str) const
381 {
382 constexpr DecodeInt<uint16_t, 16> di;
383 in6_addr ret = {};
384 size_t i = 0;
385 while (i < 8)
386 {
387 auto loc = str.find(':');
388 if (i == 6 && loc == str.npos)
389 {
390 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
391 return ret;
392 }
393 if (loc != 0 && !str.empty())
394 {
395 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
396 }
397 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
398 {
399 str.remove_prefix(loc + 2);
400 break;
401 }
402 else if (str.empty())
403 {
404 throw std::invalid_argument("IPv6 Data");
405 }
406 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
407 }
408 if (str.starts_with(':'))
409 {
410 throw std::invalid_argument("Extra separator");
411 }
412 size_t j = 7;
413 if (!str.empty() && i < 6 && str.find('.') != str.npos)
414 {
415 auto loc = str.rfind(':');
416 ret.s6_addr32[3] =
417 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
418 .s_addr;
419 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
420 j -= 2;
421 }
422 while (!str.empty() && j > i)
423 {
424 auto loc = str.rfind(':');
425 ret.s6_addr16[j--] =
426 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
427 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
428 }
429 if (!str.empty())
430 {
431 throw std::invalid_argument("Too much data");
432 }
433 return ret;
434 }
435};
436
William A. Kennington IIIead71982022-11-04 02:18:10 -0700437template <>
438struct ToAddr<InAddrAny>
439{
440 constexpr InAddrAny operator()(std::string_view str) const
441 {
442 if (str.find(':') == str.npos)
443 {
444 return ToAddr<in_addr>{}(str);
445 }
446 return ToAddr<in6_addr>{}(str);
447 }
448};
449
450template <>
451struct ToAddr<IfAddr>
452{
453 constexpr IfAddr operator()(std::string_view str) const
454 {
455 auto pos = str.rfind('/');
456 if (pos == str.npos)
457 {
458 throw std::invalid_argument("Invalid IfAddr");
459 }
460 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
461 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
462 }
463};
464
William A. Kennington III55bdc362022-11-04 17:57:21 -0700465template <typename T>
466struct ToStr
467{
468};
469
470template <>
471struct ToStr<char>
472{
473 static constexpr uint8_t buf_size = 1;
474 using buf_type = std::array<char, buf_size>;
475
476 constexpr char* operator()(char* buf, char v) const noexcept
477 {
478 buf[0] = v;
479 return buf + 1;
480 }
481};
482
483template <>
484struct ToStr<ether_addr>
485{
486 // 6 octets * 2 hex chars + 5 separators
487 static constexpr uint8_t buf_size = 17;
488 using buf_type = std::array<char, buf_size>;
489
490 constexpr char* operator()(char* buf, ether_addr v) const noexcept
491 {
492 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
493 {
494 *ptr = ':';
495 }
496 for (size_t i = 0; i < 6; ++i)
497 {
498 char* tmp = buf + i * 3;
499 uint8_t byte = v.ether_addr_octet[i];
500 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
501 }
502 return buf + buf_size;
503 }
504};
505
506template <>
507struct ToStr<in_addr>
508{
509 // 4 octets * 3 dec chars + 3 separators
510 static constexpr uint8_t buf_size = 15;
511 using buf_type = std::array<char, buf_size>;
512
513 constexpr char* operator()(char* buf, in_addr v) const noexcept
514 {
515 auto n = bswap(ntoh(v.s_addr));
516 for (size_t i = 0; i < 3; ++i)
517 {
518 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
519 n >>= 8;
520 }
521 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
522 }
523};
524
525template <>
526struct ToStr<in6_addr>
527{
528 // 8 hextets * 4 hex chars + 7 separators
529 static constexpr uint8_t buf_size = 39;
530 using buf_type = std::array<char, buf_size>;
531
532 constexpr char* operator()(char* buf, in6_addr v) const noexcept
533 {
534 // IPv4 in IPv6 Addr
535 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
536 v.s6_addr32[2] == hton(uint32_t(0xffff)))
537 {
538 constexpr auto prefix = std::string_view("::ffff:");
539 return ToStr<in_addr>{}(
540 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
541 }
542
543 size_t skip_start = 0;
544 size_t skip_size = 0;
545 {
546 size_t new_start = 0;
547 size_t new_size = 0;
548 for (size_t i = 0; i < 9; ++i)
549 {
550 if (i < 8 && v.s6_addr16[i] == 0)
551 {
552 if (new_start + new_size == i)
553 {
554 new_size++;
555 }
556 else
557 {
558 new_start = i;
559 new_size = 1;
560 }
561 }
562 else if (new_start + new_size == i && new_size > skip_size)
563 {
564 skip_start = new_start;
565 skip_size = new_size;
566 }
567 }
568 }
569 for (size_t i = 0; i < 8; ++i)
570 {
571 if (i == skip_start && skip_size > 1)
572 {
573 if (i == 0)
574 {
575 *(buf++) = ':';
576 }
577 *(buf++) = ':';
578 i += skip_size - 1;
579 continue;
580 }
581 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
582 if (i < 7)
583 {
584 *(buf++) = ':';
585 }
586 }
587 return buf;
588 }
589};
590
591template <>
592struct ToStr<InAddrAny>
593{
594 // IPv6 is the bigger of the addrs
595 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
596 using buf_type = std::array<char, buf_size>;
597
598 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
599 {
600 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
601 v);
602 }
603};
604
605template <>
606struct ToStr<IfAddr>
607{
608 // InAddrAny + sep + 3 prefix chars
609 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
610 using buf_type = std::array<char, buf_size>;
611
612 constexpr char* operator()(char* buf, IfAddr v) const noexcept
613 {
614 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
615 buf = ToStr<char>{}(buf, '/');
616 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
617 }
618};
619
William A. Kennington III238ef992022-11-03 12:47:49 -0700620namespace detail
621{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800622
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700623template <typename T>
624constexpr bool vcontains() noexcept
625{
626 return false;
627}
628
629template <typename T, typename V, typename... Vs>
630constexpr bool vcontains() noexcept
631{
632 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
633}
634
635template <typename T, typename... Types>
636constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
637 veq(T t, std::variant<Types...> v) noexcept
638{
639 return std::visit(
640 [t](auto v) {
641 if constexpr (std::is_same_v<T, decltype(v)>)
642 {
643 return v == t;
644 }
645 else
646 {
647 return false;
648 }
649 },
650 v);
651}
652
653template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700654struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700655{
656 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700657 constexpr std::string_view operator()(T v) noexcept
658 {
659 return {buf.data(), ToStr<T>{}(buf.data(), v)};
660 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700661
662 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700663 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700664};
665
William A. Kennington III55bdc362022-11-04 17:57:21 -0700666template <typename T>
667struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700668{
669 private:
670 fmt::formatter<std::string_view> formatter;
671
672 public:
673 template <typename ParseContext>
674 constexpr auto parse(ParseContext& ctx)
675 {
676 return ctx.begin();
677 }
678
679 template <typename FormatContext>
680 auto format(auto v, FormatContext& ctx) const
681 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700682 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700683 }
684};
685} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500686} // namespace network
687} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700688
689template <typename... Ts>
690struct std::hash<std::tuple<Ts...>>
691{
692 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
693 {
694 return std::apply(phosphor::network::hash_multi<Ts...>, t);
695 }
696};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700697
William A. Kennington III653114f2022-11-01 22:34:04 -0700698template <>
699struct std::hash<in_addr>
700{
701 std::size_t operator()(in_addr addr) const noexcept;
702};
703
704template <>
705struct std::hash<in6_addr>
706{
707 std::size_t operator()(in6_addr addr) const noexcept;
708};
709
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800710template <>
711struct std::hash<phosphor::network::IfAddr>
712{
713 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
714};
715
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700716namespace fmt
717{
718template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700719struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700720{
721};
722template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700723struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700724{
725};
726template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700727struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700728{
729};
730template <>
731struct formatter<phosphor::network::InAddrAny>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700732 : phosphor::network::detail::Format<phosphor::network::InAddrAny>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700733{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700734};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800735template <>
736struct formatter<phosphor::network::IfAddr>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700737 : phosphor::network::detail::Format<phosphor::network::IfAddr>
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800738{
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800739};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700740} // namespace fmt
741
742namespace std
743{
744string to_string(ether_addr value);
745string to_string(in_addr value);
746string to_string(in6_addr value);
747string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800748string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700749} // namespace std
750
751constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
752{
753 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
754 rhs.ether_addr_octet);
755}
756
757constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
758{
759 return lhs.s_addr == rhs.s_addr;
760}
761
762constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
763{
764 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
765}
766
767template <typename T>
768constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
769 bool>
770 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
771{
772 return phosphor::network::detail::veq(rhs, lhs);
773}
774
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700775auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700776{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700777 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700778}
779
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700780auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700781{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700782 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700783}
784
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700785auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700786{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700787 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700788}
789
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700790auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700791{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700792 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
793 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700794}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800795
796auto& operator<<(auto& os, phosphor::network::IfAddr v)
797{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700798 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
799 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800800}