blob: 8755068921b432520f388c2ebc9541c13a8312b0 [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 III6a923632022-11-06 18:17:33 -080078/** @class AddressInfo
79 * @brief Information about a addresses from the kernel
80 */
81struct AddressInfo
82{
83 unsigned ifidx;
84 IfAddr ifaddr;
85 uint8_t scope;
86 uint32_t flags;
87};
88
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070089struct string_hash : public std::hash<std::string_view>
90{
91 using is_transparent = void;
92};
93template <typename V>
94using string_umap =
95 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -070096using string_uset =
97 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070098
William A. Kennington III3e471c52022-10-27 19:46:07 -070099constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700100{
101 return 0;
102}
103
104template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700105constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700106{
107 const std::size_t seed = hash_multi(args...);
108 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
109}
110
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700111namespace detail
112{
113
William A. Kennington III71de63a2022-11-08 10:50:54 -0800114template <typename T, uint8_t size = sizeof(T)>
115struct BswapAlign
116{
117 using type = T;
118};
119
120template <typename T>
121struct BswapAlign<T, 2>
122{
123 using type alignas(uint16_t) = T;
124};
125
126template <typename T>
127struct BswapAlign<T, 4>
128{
129 using type alignas(uint32_t) = T;
130};
131
132template <typename T>
133struct BswapAlign<T, 8>
134{
135 using type alignas(uint64_t) = T;
136};
137
138template <typename T>
139constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
140{
141 static_assert(std::is_trivially_copyable_v<T>);
142 if constexpr (sizeof(T) == 2)
143 {
144 reinterpret_cast<uint16_t&>(n) =
145 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
146 }
147 else if constexpr (sizeof(T) == 4)
148 {
149 reinterpret_cast<uint32_t&>(n) =
150 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
151 }
152 else if constexpr (sizeof(T) == 8)
153 {
154 reinterpret_cast<uint64_t&>(n) =
155 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
156 }
157 else
158 {
159 auto b = reinterpret_cast<std::byte*>(&n);
160 std::reverse(b, b + sizeof(n));
161 }
162 return n;
163}
164
165} // namespace detail
166
167template <typename T>
168constexpr T bswap(T n) noexcept
169{
170 return detail::bswapInt<T>(n);
171}
172
173template <typename T>
174constexpr T hton(T n) noexcept
175{
176 if constexpr (std::endian::native == std::endian::big)
177 {
178 return n;
179 }
180 else if constexpr (std::endian::native == std::endian::little)
181 {
182 return bswap(n);
183 }
184 else
185 {
186 static_assert(std::is_same_v<T, void>);
187 }
188}
189
190template <typename T>
191constexpr T ntoh(T n) noexcept
192{
193 return hton(n);
194}
195
196namespace detail
197{
William A. Kennington III238ef992022-11-03 12:47:49 -0700198inline constexpr auto charLookup = []() {
199 std::array<int8_t, 256> ret;
200 std::fill(ret.begin(), ret.end(), -1);
201 for (int8_t i = 0; i < 10; ++i)
202 {
203 ret[i + '0'] = i;
204 }
205 for (int8_t i = 0; i < 26; ++i)
206 {
207 ret[i + 'A'] = i + 10;
208 ret[i + 'a'] = i + 10;
209 }
210 return ret;
211}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700212inline constexpr auto intLookup = []() {
213 std::array<char, 36> ret;
214 for (int8_t i = 0; i < 10; ++i)
215 {
216 ret[i] = i + '0';
217 }
218 for (int8_t i = 0; i < 26; ++i)
219 {
220 ret[i + 10] = i + 'a';
221 }
222 return ret;
223}();
224} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700225
226template <typename T, uint8_t base>
227struct DecodeInt
228{
229 static_assert(base > 1 && base <= 36);
230 static_assert(std::is_unsigned_v<T>);
231
232 constexpr T operator()(std::string_view str) const
233 {
234 if (str.empty())
235 {
236 throw std::invalid_argument("Empty Str");
237 }
238 constexpr auto max = std::numeric_limits<T>::max();
239 auto ret =
240 std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
241 auto v = detail::charLookup[c];
242 if (v < 0 || v >= base)
243 {
244 throw std::invalid_argument("Invalid numeral");
245 }
246 if constexpr (std::popcount(base) == 1)
247 {
248 constexpr auto shift = std::countr_zero(base);
249 constexpr auto maxshift = max >> shift;
250 if (r > maxshift)
251 {
252 throw std::overflow_error("Integer Decode");
253 }
254 return (r << shift) | v;
255 }
256 else
257 {
258 constexpr auto maxbase = max / base;
259 if (r > maxbase)
260 {
261 throw std::overflow_error("Integer Decode");
262 }
263 r *= base;
264 if (max - v < r)
265 {
266 throw std::overflow_error("Integer Decode");
267 }
268 return r + v;
269 }
270 });
271 return ret;
272 }
273};
274
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700275template <typename T, uint8_t base>
276struct EncodeInt
277{
278 static_assert(base > 1 && base <= 36);
279 static_assert(std::is_unsigned_v<T>);
280
281 static constexpr uint8_t buf_size = []() {
282 T v = std::numeric_limits<T>::max();
283 uint8_t i = 0;
284 for (; v != 0; ++i)
285 {
286 v /= base;
287 }
288 return i;
289 }();
290 using buf_type = std::array<char, buf_size>;
291
292 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
293 {
294 uint8_t i = 0;
295 do
296 {
297 if constexpr (std::popcount(base) == 1)
298 {
299 buf[i++] = detail::intLookup[v & 0xf];
300 v >>= 4;
301 }
302 else
303 {
304 buf[i++] = detail::intLookup[v % base];
305 v /= base;
306 }
307 } while (v > 0);
308 return i;
309 }
310
311 constexpr char* operator()(char* buf, T v) const noexcept
312 {
313 uint8_t i = reverseFill(buf, v);
314 std::reverse(buf, buf + i);
315 return buf + i;
316 }
317
318 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
319 {
320 uint8_t i = reverseFill(buf, v);
321 auto end = buf + std::max(i, min_width);
322 std::fill(buf + i, end, '0');
323 std::reverse(buf, end);
324 return end;
325 }
326};
327
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700328template <typename T>
329struct ToAddr
330{
331};
332
333template <>
334struct ToAddr<ether_addr>
335{
336 constexpr ether_addr operator()(std::string_view str) const
337 {
338 constexpr DecodeInt<uint8_t, 16> di;
339 ether_addr ret;
340 if (str.size() == 12 && str.find(":") == str.npos)
341 {
342 for (size_t i = 0; i < 6; ++i)
343 {
344 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
345 }
346 }
347 else
348 {
349 for (size_t i = 0; i < 5; ++i)
350 {
351 auto loc = str.find(":");
352 ret.ether_addr_octet[i] = di(str.substr(0, loc));
353 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
354 if (str.empty())
355 {
356 throw std::invalid_argument("Missing mac data");
357 }
358 }
359 ret.ether_addr_octet[5] = di(str);
360 }
361 return ret;
362 }
363};
364
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700365template <>
366struct ToAddr<in_addr>
367{
368 constexpr in_addr operator()(std::string_view str) const
369 {
370 constexpr DecodeInt<uint8_t, 10> di;
371 uint32_t addr = {};
372 for (size_t i = 0; i < 3; ++i)
373 {
374 auto loc = str.find(".");
375 addr |= di(str.substr(0, loc));
376 addr <<= 8;
377 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
378 if (str.empty())
379 {
380 throw std::invalid_argument("Missing addr data");
381 }
382 }
383 addr |= di(str);
384 return {hton(addr)};
385 }
386};
387
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700388template <>
389struct ToAddr<in6_addr>
390{
391 constexpr in6_addr operator()(std::string_view str) const
392 {
393 constexpr DecodeInt<uint16_t, 16> di;
394 in6_addr ret = {};
395 size_t i = 0;
396 while (i < 8)
397 {
398 auto loc = str.find(':');
399 if (i == 6 && loc == str.npos)
400 {
401 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
402 return ret;
403 }
404 if (loc != 0 && !str.empty())
405 {
406 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
407 }
408 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
409 {
410 str.remove_prefix(loc + 2);
411 break;
412 }
413 else if (str.empty())
414 {
415 throw std::invalid_argument("IPv6 Data");
416 }
417 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
418 }
419 if (str.starts_with(':'))
420 {
421 throw std::invalid_argument("Extra separator");
422 }
423 size_t j = 7;
424 if (!str.empty() && i < 6 && str.find('.') != str.npos)
425 {
426 auto loc = str.rfind(':');
427 ret.s6_addr32[3] =
428 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
429 .s_addr;
430 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
431 j -= 2;
432 }
433 while (!str.empty() && j > i)
434 {
435 auto loc = str.rfind(':');
436 ret.s6_addr16[j--] =
437 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
438 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
439 }
440 if (!str.empty())
441 {
442 throw std::invalid_argument("Too much data");
443 }
444 return ret;
445 }
446};
447
William A. Kennington IIIead71982022-11-04 02:18:10 -0700448template <>
449struct ToAddr<InAddrAny>
450{
451 constexpr InAddrAny operator()(std::string_view str) const
452 {
453 if (str.find(':') == str.npos)
454 {
455 return ToAddr<in_addr>{}(str);
456 }
457 return ToAddr<in6_addr>{}(str);
458 }
459};
460
461template <>
462struct ToAddr<IfAddr>
463{
464 constexpr IfAddr operator()(std::string_view str) const
465 {
466 auto pos = str.rfind('/');
467 if (pos == str.npos)
468 {
469 throw std::invalid_argument("Invalid IfAddr");
470 }
471 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
472 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
473 }
474};
475
William A. Kennington III55bdc362022-11-04 17:57:21 -0700476template <typename T>
477struct ToStr
478{
479};
480
481template <>
482struct ToStr<char>
483{
484 static constexpr uint8_t buf_size = 1;
485 using buf_type = std::array<char, buf_size>;
486
487 constexpr char* operator()(char* buf, char v) const noexcept
488 {
489 buf[0] = v;
490 return buf + 1;
491 }
492};
493
494template <>
495struct ToStr<ether_addr>
496{
497 // 6 octets * 2 hex chars + 5 separators
498 static constexpr uint8_t buf_size = 17;
499 using buf_type = std::array<char, buf_size>;
500
501 constexpr char* operator()(char* buf, ether_addr v) const noexcept
502 {
503 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
504 {
505 *ptr = ':';
506 }
507 for (size_t i = 0; i < 6; ++i)
508 {
509 char* tmp = buf + i * 3;
510 uint8_t byte = v.ether_addr_octet[i];
511 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
512 }
513 return buf + buf_size;
514 }
515};
516
517template <>
518struct ToStr<in_addr>
519{
520 // 4 octets * 3 dec chars + 3 separators
521 static constexpr uint8_t buf_size = 15;
522 using buf_type = std::array<char, buf_size>;
523
524 constexpr char* operator()(char* buf, in_addr v) const noexcept
525 {
526 auto n = bswap(ntoh(v.s_addr));
527 for (size_t i = 0; i < 3; ++i)
528 {
529 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
530 n >>= 8;
531 }
532 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
533 }
534};
535
536template <>
537struct ToStr<in6_addr>
538{
539 // 8 hextets * 4 hex chars + 7 separators
540 static constexpr uint8_t buf_size = 39;
541 using buf_type = std::array<char, buf_size>;
542
543 constexpr char* operator()(char* buf, in6_addr v) const noexcept
544 {
545 // IPv4 in IPv6 Addr
546 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
547 v.s6_addr32[2] == hton(uint32_t(0xffff)))
548 {
549 constexpr auto prefix = std::string_view("::ffff:");
550 return ToStr<in_addr>{}(
551 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
552 }
553
554 size_t skip_start = 0;
555 size_t skip_size = 0;
556 {
557 size_t new_start = 0;
558 size_t new_size = 0;
559 for (size_t i = 0; i < 9; ++i)
560 {
561 if (i < 8 && v.s6_addr16[i] == 0)
562 {
563 if (new_start + new_size == i)
564 {
565 new_size++;
566 }
567 else
568 {
569 new_start = i;
570 new_size = 1;
571 }
572 }
573 else if (new_start + new_size == i && new_size > skip_size)
574 {
575 skip_start = new_start;
576 skip_size = new_size;
577 }
578 }
579 }
580 for (size_t i = 0; i < 8; ++i)
581 {
582 if (i == skip_start && skip_size > 1)
583 {
584 if (i == 0)
585 {
586 *(buf++) = ':';
587 }
588 *(buf++) = ':';
589 i += skip_size - 1;
590 continue;
591 }
592 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
593 if (i < 7)
594 {
595 *(buf++) = ':';
596 }
597 }
598 return buf;
599 }
600};
601
602template <>
603struct ToStr<InAddrAny>
604{
605 // IPv6 is the bigger of the addrs
606 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
607 using buf_type = std::array<char, buf_size>;
608
609 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
610 {
611 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
612 v);
613 }
614};
615
616template <>
617struct ToStr<IfAddr>
618{
619 // InAddrAny + sep + 3 prefix chars
620 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
621 using buf_type = std::array<char, buf_size>;
622
623 constexpr char* operator()(char* buf, IfAddr v) const noexcept
624 {
625 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
626 buf = ToStr<char>{}(buf, '/');
627 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
628 }
629};
630
William A. Kennington III238ef992022-11-03 12:47:49 -0700631namespace detail
632{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800633
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700634template <typename T>
635constexpr bool vcontains() noexcept
636{
637 return false;
638}
639
640template <typename T, typename V, typename... Vs>
641constexpr bool vcontains() noexcept
642{
643 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
644}
645
646template <typename T, typename... Types>
647constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
648 veq(T t, std::variant<Types...> v) noexcept
649{
650 return std::visit(
651 [t](auto v) {
652 if constexpr (std::is_same_v<T, decltype(v)>)
653 {
654 return v == t;
655 }
656 else
657 {
658 return false;
659 }
660 },
661 v);
662}
663
664template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700665struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700666{
667 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700668 constexpr std::string_view operator()(T v) noexcept
669 {
670 return {buf.data(), ToStr<T>{}(buf.data(), v)};
671 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700672
673 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700674 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700675};
676
William A. Kennington III55bdc362022-11-04 17:57:21 -0700677template <typename T>
678struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700679{
680 private:
681 fmt::formatter<std::string_view> formatter;
682
683 public:
684 template <typename ParseContext>
685 constexpr auto parse(ParseContext& ctx)
686 {
687 return ctx.begin();
688 }
689
690 template <typename FormatContext>
691 auto format(auto v, FormatContext& ctx) const
692 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700693 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700694 }
695};
696} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500697} // namespace network
698} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700699
700template <typename... Ts>
701struct std::hash<std::tuple<Ts...>>
702{
703 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
704 {
705 return std::apply(phosphor::network::hash_multi<Ts...>, t);
706 }
707};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700708
William A. Kennington III653114f2022-11-01 22:34:04 -0700709template <>
710struct std::hash<in_addr>
711{
712 std::size_t operator()(in_addr addr) const noexcept;
713};
714
715template <>
716struct std::hash<in6_addr>
717{
718 std::size_t operator()(in6_addr addr) const noexcept;
719};
720
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800721template <>
722struct std::hash<phosphor::network::IfAddr>
723{
724 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
725};
726
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700727namespace fmt
728{
729template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700730struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700731{
732};
733template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700734struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700735{
736};
737template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700738struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700739{
740};
741template <>
742struct formatter<phosphor::network::InAddrAny>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700743 : phosphor::network::detail::Format<phosphor::network::InAddrAny>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700744{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700745};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800746template <>
747struct formatter<phosphor::network::IfAddr>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700748 : phosphor::network::detail::Format<phosphor::network::IfAddr>
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800749{
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800750};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700751} // namespace fmt
752
753namespace std
754{
755string to_string(ether_addr value);
756string to_string(in_addr value);
757string to_string(in6_addr value);
758string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800759string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700760} // namespace std
761
762constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
763{
764 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
765 rhs.ether_addr_octet);
766}
767
768constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
769{
770 return lhs.s_addr == rhs.s_addr;
771}
772
773constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
774{
775 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
776}
777
778template <typename T>
779constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
780 bool>
781 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
782{
783 return phosphor::network::detail::veq(rhs, lhs);
784}
785
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700786auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700787{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700788 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700789}
790
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700791auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700792{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700793 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700794}
795
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700796auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700797{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700798 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700799}
800
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700801auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700802{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700803 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
804 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700805}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800806
807auto& operator<<(auto& os, phosphor::network::IfAddr v)
808{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700809 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
810 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800811}