blob: 8d1daf4e3e95955522dc7f1c4125e0db086b4ae5 [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>
William A. Kennington III71de63a2022-11-08 10:50:54 -08008#include <numeric>
William A. Kennington IIIde70ccf2022-11-20 17:18:01 -08009#include <optional>
Patrick Venture189d44e2018-07-09 12:30:59 -070010#include <string>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070011#include <string_view>
12#include <type_traits>
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070013#include <unordered_map>
Willy Tuf7dce2e2022-10-07 05:48:08 +000014#include <unordered_set>
William A. Kennington III0d7ce482019-01-30 17:14:23 -080015#include <variant>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053016
William A. Kennington III454a0de2022-11-12 01:01:04 -080017constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
18{
19 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
20 rhs.ether_addr_octet);
21}
22
23constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
24{
25 return lhs.s_addr == rhs.s_addr;
26}
27
28constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
29{
30 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
31}
32
Ratan Gupta82549cc2017-04-21 08:45:23 +053033namespace phosphor
34{
35namespace network
36{
Ratan Guptae05083a2017-09-16 07:12:11 +053037
William A. Kennington III0d7ce482019-01-30 17:14:23 -080038// Byte representations for common address types in network byte order
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070039using InAddrAny = std::variant<in_addr, in6_addr>;
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -080040class IfAddr
41{
42 private:
43 InAddrAny addr;
44 uint8_t pfx;
45
46 static void invalidPfx(uint8_t pfx);
47
48 public:
49 constexpr IfAddr() : addr({}), pfx(0)
50 {
51 }
52
53 constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx)
54 {
55 std::visit(
56 [pfx](auto v) {
57 if (sizeof(v) * 8 < pfx)
58 {
59 invalidPfx(pfx);
60 }
61 },
62 addr);
63 }
64
65 constexpr auto getAddr() const
66 {
67 return addr;
68 }
69
70 constexpr auto getPfx() const
71 {
72 return pfx;
73 }
74
75 constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept
76 {
77 return addr == rhs.addr && pfx == rhs.pfx;
78 }
79};
William A. Kennington III0d7ce482019-01-30 17:14:23 -080080
William A. Kennington III454a0de2022-11-12 01:01:04 -080081/** @class InterfaceInfo
82 * @brief Information about interfaces from the kernel
83 */
84struct InterfaceInfo
85{
86 unsigned idx;
87 unsigned flags;
88 std::optional<std::string> name = std::nullopt;
89 std::optional<ether_addr> mac = std::nullopt;
90 std::optional<unsigned> mtu = std::nullopt;
91 std::optional<unsigned> parent_idx = std::nullopt;
92 std::optional<std::string> kind = std::nullopt;
93 std::optional<uint16_t> vlan_id = std::nullopt;
94
95 constexpr bool operator==(const InterfaceInfo& rhs) const noexcept
96 {
97 return idx == rhs.idx && flags == rhs.flags && name == rhs.name &&
98 mac == rhs.mac && mtu == rhs.mtu &&
99 parent_idx == rhs.parent_idx && kind == rhs.kind &&
100 vlan_id == rhs.vlan_id;
101 }
102};
103
William A. Kennington III6a923632022-11-06 18:17:33 -0800104/** @class AddressInfo
105 * @brief Information about a addresses from the kernel
106 */
107struct AddressInfo
108{
109 unsigned ifidx;
110 IfAddr ifaddr;
111 uint8_t scope;
112 uint32_t flags;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800113
114 constexpr bool operator==(const AddressInfo& rhs) const noexcept
115 {
116 return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr &&
117 scope == rhs.scope && flags == rhs.flags;
118 }
William A. Kennington III6a923632022-11-06 18:17:33 -0800119};
120
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800121/** @class NeighborInfo
122 * @brief Information about a neighbor from the kernel
123 */
124struct NeighborInfo
125{
126 unsigned ifidx;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800127 uint16_t state;
William A. Kennington IIId3615142022-11-12 01:28:33 -0800128 std::optional<InAddrAny> addr;
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800129 std::optional<ether_addr> mac;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800130
131 constexpr bool operator==(const NeighborInfo& rhs) const noexcept
132 {
133 return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr &&
134 mac == rhs.mac;
135 }
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800136};
137
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700138struct string_hash : public std::hash<std::string_view>
139{
140 using is_transparent = void;
141};
142template <typename V>
143using string_umap =
144 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -0700145using string_uset =
146 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700147
William A. Kennington III3e471c52022-10-27 19:46:07 -0700148constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700149{
150 return 0;
151}
152
153template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700154constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700155{
156 const std::size_t seed = hash_multi(args...);
157 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
158}
159
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700160namespace detail
161{
162
William A. Kennington III71de63a2022-11-08 10:50:54 -0800163template <typename T, uint8_t size = sizeof(T)>
164struct BswapAlign
165{
166 using type = T;
167};
168
169template <typename T>
170struct BswapAlign<T, 2>
171{
172 using type alignas(uint16_t) = T;
173};
174
175template <typename T>
176struct BswapAlign<T, 4>
177{
178 using type alignas(uint32_t) = T;
179};
180
181template <typename T>
182struct BswapAlign<T, 8>
183{
184 using type alignas(uint64_t) = T;
185};
186
187template <typename T>
188constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
189{
190 static_assert(std::is_trivially_copyable_v<T>);
191 if constexpr (sizeof(T) == 2)
192 {
193 reinterpret_cast<uint16_t&>(n) =
194 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
195 }
196 else if constexpr (sizeof(T) == 4)
197 {
198 reinterpret_cast<uint32_t&>(n) =
199 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
200 }
201 else if constexpr (sizeof(T) == 8)
202 {
203 reinterpret_cast<uint64_t&>(n) =
204 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
205 }
206 else
207 {
208 auto b = reinterpret_cast<std::byte*>(&n);
209 std::reverse(b, b + sizeof(n));
210 }
211 return n;
212}
213
214} // namespace detail
215
216template <typename T>
217constexpr T bswap(T n) noexcept
218{
219 return detail::bswapInt<T>(n);
220}
221
222template <typename T>
223constexpr T hton(T n) noexcept
224{
225 if constexpr (std::endian::native == std::endian::big)
226 {
227 return n;
228 }
229 else if constexpr (std::endian::native == std::endian::little)
230 {
231 return bswap(n);
232 }
233 else
234 {
235 static_assert(std::is_same_v<T, void>);
236 }
237}
238
239template <typename T>
240constexpr T ntoh(T n) noexcept
241{
242 return hton(n);
243}
244
245namespace detail
246{
William A. Kennington III238ef992022-11-03 12:47:49 -0700247inline constexpr auto charLookup = []() {
248 std::array<int8_t, 256> ret;
249 std::fill(ret.begin(), ret.end(), -1);
250 for (int8_t i = 0; i < 10; ++i)
251 {
252 ret[i + '0'] = i;
253 }
254 for (int8_t i = 0; i < 26; ++i)
255 {
256 ret[i + 'A'] = i + 10;
257 ret[i + 'a'] = i + 10;
258 }
259 return ret;
260}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700261inline constexpr auto intLookup = []() {
262 std::array<char, 36> ret;
263 for (int8_t i = 0; i < 10; ++i)
264 {
265 ret[i] = i + '0';
266 }
267 for (int8_t i = 0; i < 26; ++i)
268 {
269 ret[i + 10] = i + 'a';
270 }
271 return ret;
272}();
273} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700274
275template <typename T, uint8_t base>
276struct DecodeInt
277{
278 static_assert(base > 1 && base <= 36);
279 static_assert(std::is_unsigned_v<T>);
280
281 constexpr T operator()(std::string_view str) const
282 {
283 if (str.empty())
284 {
285 throw std::invalid_argument("Empty Str");
286 }
287 constexpr auto max = std::numeric_limits<T>::max();
288 auto ret =
289 std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
290 auto v = detail::charLookup[c];
291 if (v < 0 || v >= base)
292 {
293 throw std::invalid_argument("Invalid numeral");
294 }
295 if constexpr (std::popcount(base) == 1)
296 {
297 constexpr auto shift = std::countr_zero(base);
298 constexpr auto maxshift = max >> shift;
299 if (r > maxshift)
300 {
301 throw std::overflow_error("Integer Decode");
302 }
303 return (r << shift) | v;
304 }
305 else
306 {
307 constexpr auto maxbase = max / base;
308 if (r > maxbase)
309 {
310 throw std::overflow_error("Integer Decode");
311 }
312 r *= base;
313 if (max - v < r)
314 {
315 throw std::overflow_error("Integer Decode");
316 }
317 return r + v;
318 }
319 });
320 return ret;
321 }
322};
323
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700324template <typename T, uint8_t base>
325struct EncodeInt
326{
327 static_assert(base > 1 && base <= 36);
328 static_assert(std::is_unsigned_v<T>);
329
330 static constexpr uint8_t buf_size = []() {
331 T v = std::numeric_limits<T>::max();
332 uint8_t i = 0;
333 for (; v != 0; ++i)
334 {
335 v /= base;
336 }
337 return i;
338 }();
339 using buf_type = std::array<char, buf_size>;
340
341 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
342 {
343 uint8_t i = 0;
344 do
345 {
346 if constexpr (std::popcount(base) == 1)
347 {
348 buf[i++] = detail::intLookup[v & 0xf];
349 v >>= 4;
350 }
351 else
352 {
353 buf[i++] = detail::intLookup[v % base];
354 v /= base;
355 }
356 } while (v > 0);
357 return i;
358 }
359
360 constexpr char* operator()(char* buf, T v) const noexcept
361 {
362 uint8_t i = reverseFill(buf, v);
363 std::reverse(buf, buf + i);
364 return buf + i;
365 }
366
367 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
368 {
369 uint8_t i = reverseFill(buf, v);
370 auto end = buf + std::max(i, min_width);
371 std::fill(buf + i, end, '0');
372 std::reverse(buf, end);
373 return end;
374 }
375};
376
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700377template <typename T>
378struct ToAddr
379{
380};
381
382template <>
383struct ToAddr<ether_addr>
384{
385 constexpr ether_addr operator()(std::string_view str) const
386 {
387 constexpr DecodeInt<uint8_t, 16> di;
388 ether_addr ret;
389 if (str.size() == 12 && str.find(":") == str.npos)
390 {
391 for (size_t i = 0; i < 6; ++i)
392 {
393 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
394 }
395 }
396 else
397 {
398 for (size_t i = 0; i < 5; ++i)
399 {
400 auto loc = str.find(":");
401 ret.ether_addr_octet[i] = di(str.substr(0, loc));
402 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
403 if (str.empty())
404 {
405 throw std::invalid_argument("Missing mac data");
406 }
407 }
408 ret.ether_addr_octet[5] = di(str);
409 }
410 return ret;
411 }
412};
413
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700414template <>
415struct ToAddr<in_addr>
416{
417 constexpr in_addr operator()(std::string_view str) const
418 {
419 constexpr DecodeInt<uint8_t, 10> di;
420 uint32_t addr = {};
421 for (size_t i = 0; i < 3; ++i)
422 {
423 auto loc = str.find(".");
424 addr |= di(str.substr(0, loc));
425 addr <<= 8;
426 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
427 if (str.empty())
428 {
429 throw std::invalid_argument("Missing addr data");
430 }
431 }
432 addr |= di(str);
433 return {hton(addr)};
434 }
435};
436
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700437template <>
438struct ToAddr<in6_addr>
439{
440 constexpr in6_addr operator()(std::string_view str) const
441 {
442 constexpr DecodeInt<uint16_t, 16> di;
443 in6_addr ret = {};
444 size_t i = 0;
445 while (i < 8)
446 {
447 auto loc = str.find(':');
448 if (i == 6 && loc == str.npos)
449 {
450 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
451 return ret;
452 }
453 if (loc != 0 && !str.empty())
454 {
455 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
456 }
457 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
458 {
459 str.remove_prefix(loc + 2);
460 break;
461 }
462 else if (str.empty())
463 {
464 throw std::invalid_argument("IPv6 Data");
465 }
466 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
467 }
468 if (str.starts_with(':'))
469 {
470 throw std::invalid_argument("Extra separator");
471 }
472 size_t j = 7;
473 if (!str.empty() && i < 6 && str.find('.') != str.npos)
474 {
475 auto loc = str.rfind(':');
476 ret.s6_addr32[3] =
477 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
478 .s_addr;
479 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
480 j -= 2;
481 }
482 while (!str.empty() && j > i)
483 {
484 auto loc = str.rfind(':');
485 ret.s6_addr16[j--] =
486 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
487 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
488 }
489 if (!str.empty())
490 {
491 throw std::invalid_argument("Too much data");
492 }
493 return ret;
494 }
495};
496
William A. Kennington IIIead71982022-11-04 02:18:10 -0700497template <>
498struct ToAddr<InAddrAny>
499{
500 constexpr InAddrAny operator()(std::string_view str) const
501 {
502 if (str.find(':') == str.npos)
503 {
504 return ToAddr<in_addr>{}(str);
505 }
506 return ToAddr<in6_addr>{}(str);
507 }
508};
509
510template <>
511struct ToAddr<IfAddr>
512{
513 constexpr IfAddr operator()(std::string_view str) const
514 {
515 auto pos = str.rfind('/');
516 if (pos == str.npos)
517 {
518 throw std::invalid_argument("Invalid IfAddr");
519 }
520 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
521 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
522 }
523};
524
William A. Kennington III55bdc362022-11-04 17:57:21 -0700525template <typename T>
526struct ToStr
527{
528};
529
530template <>
531struct ToStr<char>
532{
533 static constexpr uint8_t buf_size = 1;
534 using buf_type = std::array<char, buf_size>;
535
536 constexpr char* operator()(char* buf, char v) const noexcept
537 {
538 buf[0] = v;
539 return buf + 1;
540 }
541};
542
543template <>
544struct ToStr<ether_addr>
545{
546 // 6 octets * 2 hex chars + 5 separators
547 static constexpr uint8_t buf_size = 17;
548 using buf_type = std::array<char, buf_size>;
549
550 constexpr char* operator()(char* buf, ether_addr v) const noexcept
551 {
552 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
553 {
554 *ptr = ':';
555 }
556 for (size_t i = 0; i < 6; ++i)
557 {
558 char* tmp = buf + i * 3;
559 uint8_t byte = v.ether_addr_octet[i];
560 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
561 }
562 return buf + buf_size;
563 }
564};
565
566template <>
567struct ToStr<in_addr>
568{
569 // 4 octets * 3 dec chars + 3 separators
570 static constexpr uint8_t buf_size = 15;
571 using buf_type = std::array<char, buf_size>;
572
573 constexpr char* operator()(char* buf, in_addr v) const noexcept
574 {
575 auto n = bswap(ntoh(v.s_addr));
576 for (size_t i = 0; i < 3; ++i)
577 {
578 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
579 n >>= 8;
580 }
581 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
582 }
583};
584
585template <>
586struct ToStr<in6_addr>
587{
588 // 8 hextets * 4 hex chars + 7 separators
589 static constexpr uint8_t buf_size = 39;
590 using buf_type = std::array<char, buf_size>;
591
592 constexpr char* operator()(char* buf, in6_addr v) const noexcept
593 {
594 // IPv4 in IPv6 Addr
595 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
596 v.s6_addr32[2] == hton(uint32_t(0xffff)))
597 {
598 constexpr auto prefix = std::string_view("::ffff:");
599 return ToStr<in_addr>{}(
600 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
601 }
602
603 size_t skip_start = 0;
604 size_t skip_size = 0;
605 {
606 size_t new_start = 0;
607 size_t new_size = 0;
608 for (size_t i = 0; i < 9; ++i)
609 {
610 if (i < 8 && v.s6_addr16[i] == 0)
611 {
612 if (new_start + new_size == i)
613 {
614 new_size++;
615 }
616 else
617 {
618 new_start = i;
619 new_size = 1;
620 }
621 }
622 else if (new_start + new_size == i && new_size > skip_size)
623 {
624 skip_start = new_start;
625 skip_size = new_size;
626 }
627 }
628 }
629 for (size_t i = 0; i < 8; ++i)
630 {
631 if (i == skip_start && skip_size > 1)
632 {
633 if (i == 0)
634 {
635 *(buf++) = ':';
636 }
637 *(buf++) = ':';
638 i += skip_size - 1;
639 continue;
640 }
641 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
642 if (i < 7)
643 {
644 *(buf++) = ':';
645 }
646 }
647 return buf;
648 }
649};
650
651template <>
652struct ToStr<InAddrAny>
653{
654 // IPv6 is the bigger of the addrs
655 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
656 using buf_type = std::array<char, buf_size>;
657
658 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
659 {
660 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
661 v);
662 }
663};
664
665template <>
666struct ToStr<IfAddr>
667{
668 // InAddrAny + sep + 3 prefix chars
669 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
670 using buf_type = std::array<char, buf_size>;
671
672 constexpr char* operator()(char* buf, IfAddr v) const noexcept
673 {
674 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
675 buf = ToStr<char>{}(buf, '/');
676 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
677 }
678};
679
William A. Kennington III238ef992022-11-03 12:47:49 -0700680namespace detail
681{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800682
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700683template <typename T>
684constexpr bool vcontains() noexcept
685{
686 return false;
687}
688
689template <typename T, typename V, typename... Vs>
690constexpr bool vcontains() noexcept
691{
692 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
693}
694
695template <typename T, typename... Types>
696constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
697 veq(T t, std::variant<Types...> v) noexcept
698{
699 return std::visit(
700 [t](auto v) {
701 if constexpr (std::is_same_v<T, decltype(v)>)
702 {
703 return v == t;
704 }
705 else
706 {
707 return false;
708 }
709 },
710 v);
711}
712
713template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700714struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700715{
716 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700717 constexpr std::string_view operator()(T v) noexcept
718 {
719 return {buf.data(), ToStr<T>{}(buf.data(), v)};
720 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700721
722 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700723 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700724};
725
William A. Kennington III55bdc362022-11-04 17:57:21 -0700726template <typename T>
727struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700728{
729 private:
730 fmt::formatter<std::string_view> formatter;
731
732 public:
733 template <typename ParseContext>
734 constexpr auto parse(ParseContext& ctx)
735 {
736 return ctx.begin();
737 }
738
739 template <typename FormatContext>
740 auto format(auto v, FormatContext& ctx) const
741 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700742 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700743 }
744};
745} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500746} // namespace network
747} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700748
749template <typename... Ts>
750struct std::hash<std::tuple<Ts...>>
751{
752 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
753 {
754 return std::apply(phosphor::network::hash_multi<Ts...>, t);
755 }
756};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700757
William A. Kennington III653114f2022-11-01 22:34:04 -0700758template <>
759struct std::hash<in_addr>
760{
761 std::size_t operator()(in_addr addr) const noexcept;
762};
763
764template <>
765struct std::hash<in6_addr>
766{
767 std::size_t operator()(in6_addr addr) const noexcept;
768};
769
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800770template <>
771struct std::hash<phosphor::network::IfAddr>
772{
773 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
774};
775
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700776namespace fmt
777{
778template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700779struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700780{
781};
782template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700783struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700784{
785};
786template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700787struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700788{
789};
790template <>
791struct formatter<phosphor::network::InAddrAny>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700792 : phosphor::network::detail::Format<phosphor::network::InAddrAny>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700793{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700794};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800795template <>
796struct formatter<phosphor::network::IfAddr>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700797 : phosphor::network::detail::Format<phosphor::network::IfAddr>
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800798{
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800799};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700800} // namespace fmt
801
802namespace std
803{
804string to_string(ether_addr value);
805string to_string(in_addr value);
806string to_string(in6_addr value);
807string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800808string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700809} // namespace std
810
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700811template <typename T>
812constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
813 bool>
814 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
815{
816 return phosphor::network::detail::veq(rhs, lhs);
817}
818
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700819auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700820{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700821 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700822}
823
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700824auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700825{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700826 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700827}
828
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700829auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700830{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700831 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700832}
833
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700834auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700835{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700836 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
837 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700838}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800839
840auto& operator<<(auto& os, phosphor::network::IfAddr v)
841{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700842 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
843 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800844}
William A. Kennington III13d665c2022-11-15 20:34:40 -0800845
846namespace phosphor::network
847{
848
849/** @brief Contains all of the object information about the interface */
850struct AllIntfInfo
851{
852 InterfaceInfo intf;
853 std::optional<in_addr> defgw4 = std::nullopt;
854 std::optional<in6_addr> defgw6 = std::nullopt;
855 std::unordered_map<IfAddr, AddressInfo> addrs = {};
856 std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
857};
858
859} // namespace phosphor::network