blob: bdb431d2400d6df4fa189254a50924048ba170e3 [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 IIIa8426902022-11-07 15:37:41 -080089/** @class NeighborInfo
90 * @brief Information about a neighbor from the kernel
91 */
92struct NeighborInfo
93{
94 unsigned ifidx;
95 InAddrAny addr;
96 std::optional<ether_addr> mac;
97 uint16_t state;
98};
99
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700100struct string_hash : public std::hash<std::string_view>
101{
102 using is_transparent = void;
103};
104template <typename V>
105using string_umap =
106 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -0700107using string_uset =
108 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700109
William A. Kennington III3e471c52022-10-27 19:46:07 -0700110constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700111{
112 return 0;
113}
114
115template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700116constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700117{
118 const std::size_t seed = hash_multi(args...);
119 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
120}
121
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700122namespace detail
123{
124
William A. Kennington III71de63a2022-11-08 10:50:54 -0800125template <typename T, uint8_t size = sizeof(T)>
126struct BswapAlign
127{
128 using type = T;
129};
130
131template <typename T>
132struct BswapAlign<T, 2>
133{
134 using type alignas(uint16_t) = T;
135};
136
137template <typename T>
138struct BswapAlign<T, 4>
139{
140 using type alignas(uint32_t) = T;
141};
142
143template <typename T>
144struct BswapAlign<T, 8>
145{
146 using type alignas(uint64_t) = T;
147};
148
149template <typename T>
150constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
151{
152 static_assert(std::is_trivially_copyable_v<T>);
153 if constexpr (sizeof(T) == 2)
154 {
155 reinterpret_cast<uint16_t&>(n) =
156 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
157 }
158 else if constexpr (sizeof(T) == 4)
159 {
160 reinterpret_cast<uint32_t&>(n) =
161 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
162 }
163 else if constexpr (sizeof(T) == 8)
164 {
165 reinterpret_cast<uint64_t&>(n) =
166 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
167 }
168 else
169 {
170 auto b = reinterpret_cast<std::byte*>(&n);
171 std::reverse(b, b + sizeof(n));
172 }
173 return n;
174}
175
176} // namespace detail
177
178template <typename T>
179constexpr T bswap(T n) noexcept
180{
181 return detail::bswapInt<T>(n);
182}
183
184template <typename T>
185constexpr T hton(T n) noexcept
186{
187 if constexpr (std::endian::native == std::endian::big)
188 {
189 return n;
190 }
191 else if constexpr (std::endian::native == std::endian::little)
192 {
193 return bswap(n);
194 }
195 else
196 {
197 static_assert(std::is_same_v<T, void>);
198 }
199}
200
201template <typename T>
202constexpr T ntoh(T n) noexcept
203{
204 return hton(n);
205}
206
207namespace detail
208{
William A. Kennington III238ef992022-11-03 12:47:49 -0700209inline constexpr auto charLookup = []() {
210 std::array<int8_t, 256> ret;
211 std::fill(ret.begin(), ret.end(), -1);
212 for (int8_t i = 0; i < 10; ++i)
213 {
214 ret[i + '0'] = i;
215 }
216 for (int8_t i = 0; i < 26; ++i)
217 {
218 ret[i + 'A'] = i + 10;
219 ret[i + 'a'] = i + 10;
220 }
221 return ret;
222}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700223inline constexpr auto intLookup = []() {
224 std::array<char, 36> ret;
225 for (int8_t i = 0; i < 10; ++i)
226 {
227 ret[i] = i + '0';
228 }
229 for (int8_t i = 0; i < 26; ++i)
230 {
231 ret[i + 10] = i + 'a';
232 }
233 return ret;
234}();
235} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700236
237template <typename T, uint8_t base>
238struct DecodeInt
239{
240 static_assert(base > 1 && base <= 36);
241 static_assert(std::is_unsigned_v<T>);
242
243 constexpr T operator()(std::string_view str) const
244 {
245 if (str.empty())
246 {
247 throw std::invalid_argument("Empty Str");
248 }
249 constexpr auto max = std::numeric_limits<T>::max();
250 auto ret =
251 std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
252 auto v = detail::charLookup[c];
253 if (v < 0 || v >= base)
254 {
255 throw std::invalid_argument("Invalid numeral");
256 }
257 if constexpr (std::popcount(base) == 1)
258 {
259 constexpr auto shift = std::countr_zero(base);
260 constexpr auto maxshift = max >> shift;
261 if (r > maxshift)
262 {
263 throw std::overflow_error("Integer Decode");
264 }
265 return (r << shift) | v;
266 }
267 else
268 {
269 constexpr auto maxbase = max / base;
270 if (r > maxbase)
271 {
272 throw std::overflow_error("Integer Decode");
273 }
274 r *= base;
275 if (max - v < r)
276 {
277 throw std::overflow_error("Integer Decode");
278 }
279 return r + v;
280 }
281 });
282 return ret;
283 }
284};
285
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700286template <typename T, uint8_t base>
287struct EncodeInt
288{
289 static_assert(base > 1 && base <= 36);
290 static_assert(std::is_unsigned_v<T>);
291
292 static constexpr uint8_t buf_size = []() {
293 T v = std::numeric_limits<T>::max();
294 uint8_t i = 0;
295 for (; v != 0; ++i)
296 {
297 v /= base;
298 }
299 return i;
300 }();
301 using buf_type = std::array<char, buf_size>;
302
303 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
304 {
305 uint8_t i = 0;
306 do
307 {
308 if constexpr (std::popcount(base) == 1)
309 {
310 buf[i++] = detail::intLookup[v & 0xf];
311 v >>= 4;
312 }
313 else
314 {
315 buf[i++] = detail::intLookup[v % base];
316 v /= base;
317 }
318 } while (v > 0);
319 return i;
320 }
321
322 constexpr char* operator()(char* buf, T v) const noexcept
323 {
324 uint8_t i = reverseFill(buf, v);
325 std::reverse(buf, buf + i);
326 return buf + i;
327 }
328
329 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
330 {
331 uint8_t i = reverseFill(buf, v);
332 auto end = buf + std::max(i, min_width);
333 std::fill(buf + i, end, '0');
334 std::reverse(buf, end);
335 return end;
336 }
337};
338
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700339template <typename T>
340struct ToAddr
341{
342};
343
344template <>
345struct ToAddr<ether_addr>
346{
347 constexpr ether_addr operator()(std::string_view str) const
348 {
349 constexpr DecodeInt<uint8_t, 16> di;
350 ether_addr ret;
351 if (str.size() == 12 && str.find(":") == str.npos)
352 {
353 for (size_t i = 0; i < 6; ++i)
354 {
355 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
356 }
357 }
358 else
359 {
360 for (size_t i = 0; i < 5; ++i)
361 {
362 auto loc = str.find(":");
363 ret.ether_addr_octet[i] = di(str.substr(0, loc));
364 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
365 if (str.empty())
366 {
367 throw std::invalid_argument("Missing mac data");
368 }
369 }
370 ret.ether_addr_octet[5] = di(str);
371 }
372 return ret;
373 }
374};
375
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700376template <>
377struct ToAddr<in_addr>
378{
379 constexpr in_addr operator()(std::string_view str) const
380 {
381 constexpr DecodeInt<uint8_t, 10> di;
382 uint32_t addr = {};
383 for (size_t i = 0; i < 3; ++i)
384 {
385 auto loc = str.find(".");
386 addr |= di(str.substr(0, loc));
387 addr <<= 8;
388 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
389 if (str.empty())
390 {
391 throw std::invalid_argument("Missing addr data");
392 }
393 }
394 addr |= di(str);
395 return {hton(addr)};
396 }
397};
398
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700399template <>
400struct ToAddr<in6_addr>
401{
402 constexpr in6_addr operator()(std::string_view str) const
403 {
404 constexpr DecodeInt<uint16_t, 16> di;
405 in6_addr ret = {};
406 size_t i = 0;
407 while (i < 8)
408 {
409 auto loc = str.find(':');
410 if (i == 6 && loc == str.npos)
411 {
412 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
413 return ret;
414 }
415 if (loc != 0 && !str.empty())
416 {
417 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
418 }
419 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
420 {
421 str.remove_prefix(loc + 2);
422 break;
423 }
424 else if (str.empty())
425 {
426 throw std::invalid_argument("IPv6 Data");
427 }
428 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
429 }
430 if (str.starts_with(':'))
431 {
432 throw std::invalid_argument("Extra separator");
433 }
434 size_t j = 7;
435 if (!str.empty() && i < 6 && str.find('.') != str.npos)
436 {
437 auto loc = str.rfind(':');
438 ret.s6_addr32[3] =
439 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
440 .s_addr;
441 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
442 j -= 2;
443 }
444 while (!str.empty() && j > i)
445 {
446 auto loc = str.rfind(':');
447 ret.s6_addr16[j--] =
448 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
449 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
450 }
451 if (!str.empty())
452 {
453 throw std::invalid_argument("Too much data");
454 }
455 return ret;
456 }
457};
458
William A. Kennington IIIead71982022-11-04 02:18:10 -0700459template <>
460struct ToAddr<InAddrAny>
461{
462 constexpr InAddrAny operator()(std::string_view str) const
463 {
464 if (str.find(':') == str.npos)
465 {
466 return ToAddr<in_addr>{}(str);
467 }
468 return ToAddr<in6_addr>{}(str);
469 }
470};
471
472template <>
473struct ToAddr<IfAddr>
474{
475 constexpr IfAddr operator()(std::string_view str) const
476 {
477 auto pos = str.rfind('/');
478 if (pos == str.npos)
479 {
480 throw std::invalid_argument("Invalid IfAddr");
481 }
482 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
483 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
484 }
485};
486
William A. Kennington III55bdc362022-11-04 17:57:21 -0700487template <typename T>
488struct ToStr
489{
490};
491
492template <>
493struct ToStr<char>
494{
495 static constexpr uint8_t buf_size = 1;
496 using buf_type = std::array<char, buf_size>;
497
498 constexpr char* operator()(char* buf, char v) const noexcept
499 {
500 buf[0] = v;
501 return buf + 1;
502 }
503};
504
505template <>
506struct ToStr<ether_addr>
507{
508 // 6 octets * 2 hex chars + 5 separators
509 static constexpr uint8_t buf_size = 17;
510 using buf_type = std::array<char, buf_size>;
511
512 constexpr char* operator()(char* buf, ether_addr v) const noexcept
513 {
514 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
515 {
516 *ptr = ':';
517 }
518 for (size_t i = 0; i < 6; ++i)
519 {
520 char* tmp = buf + i * 3;
521 uint8_t byte = v.ether_addr_octet[i];
522 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
523 }
524 return buf + buf_size;
525 }
526};
527
528template <>
529struct ToStr<in_addr>
530{
531 // 4 octets * 3 dec chars + 3 separators
532 static constexpr uint8_t buf_size = 15;
533 using buf_type = std::array<char, buf_size>;
534
535 constexpr char* operator()(char* buf, in_addr v) const noexcept
536 {
537 auto n = bswap(ntoh(v.s_addr));
538 for (size_t i = 0; i < 3; ++i)
539 {
540 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
541 n >>= 8;
542 }
543 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
544 }
545};
546
547template <>
548struct ToStr<in6_addr>
549{
550 // 8 hextets * 4 hex chars + 7 separators
551 static constexpr uint8_t buf_size = 39;
552 using buf_type = std::array<char, buf_size>;
553
554 constexpr char* operator()(char* buf, in6_addr v) const noexcept
555 {
556 // IPv4 in IPv6 Addr
557 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
558 v.s6_addr32[2] == hton(uint32_t(0xffff)))
559 {
560 constexpr auto prefix = std::string_view("::ffff:");
561 return ToStr<in_addr>{}(
562 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
563 }
564
565 size_t skip_start = 0;
566 size_t skip_size = 0;
567 {
568 size_t new_start = 0;
569 size_t new_size = 0;
570 for (size_t i = 0; i < 9; ++i)
571 {
572 if (i < 8 && v.s6_addr16[i] == 0)
573 {
574 if (new_start + new_size == i)
575 {
576 new_size++;
577 }
578 else
579 {
580 new_start = i;
581 new_size = 1;
582 }
583 }
584 else if (new_start + new_size == i && new_size > skip_size)
585 {
586 skip_start = new_start;
587 skip_size = new_size;
588 }
589 }
590 }
591 for (size_t i = 0; i < 8; ++i)
592 {
593 if (i == skip_start && skip_size > 1)
594 {
595 if (i == 0)
596 {
597 *(buf++) = ':';
598 }
599 *(buf++) = ':';
600 i += skip_size - 1;
601 continue;
602 }
603 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
604 if (i < 7)
605 {
606 *(buf++) = ':';
607 }
608 }
609 return buf;
610 }
611};
612
613template <>
614struct ToStr<InAddrAny>
615{
616 // IPv6 is the bigger of the addrs
617 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
618 using buf_type = std::array<char, buf_size>;
619
620 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
621 {
622 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
623 v);
624 }
625};
626
627template <>
628struct ToStr<IfAddr>
629{
630 // InAddrAny + sep + 3 prefix chars
631 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
632 using buf_type = std::array<char, buf_size>;
633
634 constexpr char* operator()(char* buf, IfAddr v) const noexcept
635 {
636 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
637 buf = ToStr<char>{}(buf, '/');
638 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
639 }
640};
641
William A. Kennington III238ef992022-11-03 12:47:49 -0700642namespace detail
643{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800644
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700645template <typename T>
646constexpr bool vcontains() noexcept
647{
648 return false;
649}
650
651template <typename T, typename V, typename... Vs>
652constexpr bool vcontains() noexcept
653{
654 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
655}
656
657template <typename T, typename... Types>
658constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
659 veq(T t, std::variant<Types...> v) noexcept
660{
661 return std::visit(
662 [t](auto v) {
663 if constexpr (std::is_same_v<T, decltype(v)>)
664 {
665 return v == t;
666 }
667 else
668 {
669 return false;
670 }
671 },
672 v);
673}
674
675template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700676struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700677{
678 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700679 constexpr std::string_view operator()(T v) noexcept
680 {
681 return {buf.data(), ToStr<T>{}(buf.data(), v)};
682 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700683
684 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700685 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700686};
687
William A. Kennington III55bdc362022-11-04 17:57:21 -0700688template <typename T>
689struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700690{
691 private:
692 fmt::formatter<std::string_view> formatter;
693
694 public:
695 template <typename ParseContext>
696 constexpr auto parse(ParseContext& ctx)
697 {
698 return ctx.begin();
699 }
700
701 template <typename FormatContext>
702 auto format(auto v, FormatContext& ctx) const
703 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700704 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700705 }
706};
707} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500708} // namespace network
709} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700710
711template <typename... Ts>
712struct std::hash<std::tuple<Ts...>>
713{
714 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
715 {
716 return std::apply(phosphor::network::hash_multi<Ts...>, t);
717 }
718};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700719
William A. Kennington III653114f2022-11-01 22:34:04 -0700720template <>
721struct std::hash<in_addr>
722{
723 std::size_t operator()(in_addr addr) const noexcept;
724};
725
726template <>
727struct std::hash<in6_addr>
728{
729 std::size_t operator()(in6_addr addr) const noexcept;
730};
731
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800732template <>
733struct std::hash<phosphor::network::IfAddr>
734{
735 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
736};
737
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700738namespace fmt
739{
740template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700741struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700742{
743};
744template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700745struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700746{
747};
748template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700749struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700750{
751};
752template <>
753struct formatter<phosphor::network::InAddrAny>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700754 : phosphor::network::detail::Format<phosphor::network::InAddrAny>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700755{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700756};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800757template <>
758struct formatter<phosphor::network::IfAddr>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700759 : phosphor::network::detail::Format<phosphor::network::IfAddr>
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800760{
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800761};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700762} // namespace fmt
763
764namespace std
765{
766string to_string(ether_addr value);
767string to_string(in_addr value);
768string to_string(in6_addr value);
769string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800770string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700771} // namespace std
772
773constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
774{
775 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
776 rhs.ether_addr_octet);
777}
778
779constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
780{
781 return lhs.s_addr == rhs.s_addr;
782}
783
784constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
785{
786 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
787}
788
789template <typename T>
790constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
791 bool>
792 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
793{
794 return phosphor::network::detail::veq(rhs, lhs);
795}
796
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700797auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700798{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700799 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700800}
801
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700802auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700803{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700804 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700805}
806
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700807auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700808{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700809 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700810}
811
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700812auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700813{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700814 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
815 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700816}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800817
818auto& operator<<(auto& os, phosphor::network::IfAddr v)
819{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700820 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
821 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800822}