blob: ba4ee1ac247ffefca53a5380005cd6eb1dc66a2e [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:
Patrick Williams89d734b2023-05-10 07:50:25 -050049 constexpr IfAddr() : addr({}), pfx(0) {}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -080050
51 constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx)
52 {
53 std::visit(
54 [pfx](auto v) {
Patrick Williams89d734b2023-05-10 07:50:25 -050055 if (sizeof(v) * 8 < pfx)
56 {
57 invalidPfx(pfx);
58 }
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -080059 },
60 addr);
61 }
62
63 constexpr auto getAddr() const
64 {
65 return addr;
66 }
67
68 constexpr auto getPfx() const
69 {
70 return pfx;
71 }
72
73 constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept
74 {
75 return addr == rhs.addr && pfx == rhs.pfx;
76 }
77};
William A. Kennington III0d7ce482019-01-30 17:14:23 -080078
William A. Kennington III454a0de2022-11-12 01:01:04 -080079/** @class InterfaceInfo
80 * @brief Information about interfaces from the kernel
81 */
82struct InterfaceInfo
83{
84 unsigned idx;
85 unsigned flags;
86 std::optional<std::string> name = std::nullopt;
87 std::optional<ether_addr> mac = std::nullopt;
88 std::optional<unsigned> mtu = std::nullopt;
89 std::optional<unsigned> parent_idx = std::nullopt;
90 std::optional<std::string> kind = std::nullopt;
91 std::optional<uint16_t> vlan_id = std::nullopt;
92
93 constexpr bool operator==(const InterfaceInfo& rhs) const noexcept
94 {
95 return idx == rhs.idx && flags == rhs.flags && name == rhs.name &&
96 mac == rhs.mac && mtu == rhs.mtu &&
97 parent_idx == rhs.parent_idx && kind == rhs.kind &&
98 vlan_id == rhs.vlan_id;
99 }
100};
101
William A. Kennington III6a923632022-11-06 18:17:33 -0800102/** @class AddressInfo
103 * @brief Information about a addresses from the kernel
104 */
105struct AddressInfo
106{
107 unsigned ifidx;
108 IfAddr ifaddr;
109 uint8_t scope;
110 uint32_t flags;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800111
112 constexpr bool operator==(const AddressInfo& rhs) const noexcept
113 {
114 return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr &&
115 scope == rhs.scope && flags == rhs.flags;
116 }
William A. Kennington III6a923632022-11-06 18:17:33 -0800117};
118
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800119/** @class NeighborInfo
120 * @brief Information about a neighbor from the kernel
121 */
122struct NeighborInfo
123{
124 unsigned ifidx;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800125 uint16_t state;
William A. Kennington IIId3615142022-11-12 01:28:33 -0800126 std::optional<InAddrAny> addr;
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800127 std::optional<ether_addr> mac;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800128
129 constexpr bool operator==(const NeighborInfo& rhs) const noexcept
130 {
131 return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr &&
132 mac == rhs.mac;
133 }
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800134};
135
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700136struct string_hash : public std::hash<std::string_view>
137{
138 using is_transparent = void;
139};
140template <typename V>
141using string_umap =
142 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -0700143using string_uset =
144 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700145
William A. Kennington III3e471c52022-10-27 19:46:07 -0700146constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700147{
148 return 0;
149}
150
151template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700152constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700153{
154 const std::size_t seed = hash_multi(args...);
155 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
156}
157
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700158namespace detail
159{
160
William A. Kennington III71de63a2022-11-08 10:50:54 -0800161template <typename T, uint8_t size = sizeof(T)>
162struct BswapAlign
163{
164 using type = T;
165};
166
167template <typename T>
168struct BswapAlign<T, 2>
169{
170 using type alignas(uint16_t) = T;
171};
172
173template <typename T>
174struct BswapAlign<T, 4>
175{
176 using type alignas(uint32_t) = T;
177};
178
179template <typename T>
180struct BswapAlign<T, 8>
181{
182 using type alignas(uint64_t) = T;
183};
184
185template <typename T>
186constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
187{
188 static_assert(std::is_trivially_copyable_v<T>);
189 if constexpr (sizeof(T) == 2)
190 {
191 reinterpret_cast<uint16_t&>(n) =
192 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
193 }
194 else if constexpr (sizeof(T) == 4)
195 {
196 reinterpret_cast<uint32_t&>(n) =
197 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
198 }
199 else if constexpr (sizeof(T) == 8)
200 {
201 reinterpret_cast<uint64_t&>(n) =
202 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
203 }
204 else
205 {
206 auto b = reinterpret_cast<std::byte*>(&n);
207 std::reverse(b, b + sizeof(n));
208 }
209 return n;
210}
211
212} // namespace detail
213
214template <typename T>
215constexpr T bswap(T n) noexcept
216{
217 return detail::bswapInt<T>(n);
218}
219
220template <typename T>
221constexpr T hton(T n) noexcept
222{
223 if constexpr (std::endian::native == std::endian::big)
224 {
225 return n;
226 }
227 else if constexpr (std::endian::native == std::endian::little)
228 {
229 return bswap(n);
230 }
231 else
232 {
233 static_assert(std::is_same_v<T, void>);
234 }
235}
236
237template <typename T>
238constexpr T ntoh(T n) noexcept
239{
240 return hton(n);
241}
242
243namespace detail
244{
William A. Kennington III238ef992022-11-03 12:47:49 -0700245inline constexpr auto charLookup = []() {
246 std::array<int8_t, 256> ret;
247 std::fill(ret.begin(), ret.end(), -1);
248 for (int8_t i = 0; i < 10; ++i)
249 {
250 ret[i + '0'] = i;
251 }
252 for (int8_t i = 0; i < 26; ++i)
253 {
254 ret[i + 'A'] = i + 10;
255 ret[i + 'a'] = i + 10;
256 }
257 return ret;
258}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700259inline constexpr auto intLookup = []() {
260 std::array<char, 36> ret;
261 for (int8_t i = 0; i < 10; ++i)
262 {
263 ret[i] = i + '0';
264 }
265 for (int8_t i = 0; i < 26; ++i)
266 {
267 ret[i + 10] = i + 'a';
268 }
269 return ret;
270}();
271} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700272
273template <typename T, uint8_t base>
274struct DecodeInt
275{
276 static_assert(base > 1 && base <= 36);
277 static_assert(std::is_unsigned_v<T>);
278
279 constexpr T operator()(std::string_view str) const
280 {
281 if (str.empty())
282 {
283 throw std::invalid_argument("Empty Str");
284 }
285 constexpr auto max = std::numeric_limits<T>::max();
Patrick Williams89d734b2023-05-10 07:50:25 -0500286 auto ret = std::accumulate(str.begin(), str.end(), T{},
287 [&](T r, char c) {
288 auto v = detail::charLookup[c];
289 if (v < 0 || v >= base)
290 {
291 throw std::invalid_argument("Invalid numeral");
292 }
293 if constexpr (std::popcount(base) == 1)
294 {
295 constexpr auto shift = std::countr_zero(base);
296 constexpr auto maxshift = max >> shift;
297 if (r > maxshift)
William A. Kennington III238ef992022-11-03 12:47:49 -0700298 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500299 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700300 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500301 return (r << shift) | v;
302 }
303 else
304 {
305 constexpr auto maxbase = max / base;
306 if (r > maxbase)
William A. Kennington III238ef992022-11-03 12:47:49 -0700307 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500308 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700309 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500310 r *= base;
311 if (max - v < r)
William A. Kennington III238ef992022-11-03 12:47:49 -0700312 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500313 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700314 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500315 return r + v;
316 }
317 });
William A. Kennington III238ef992022-11-03 12:47:49 -0700318 return ret;
319 }
320};
321
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700322template <typename T, uint8_t base>
323struct EncodeInt
324{
325 static_assert(base > 1 && base <= 36);
326 static_assert(std::is_unsigned_v<T>);
327
328 static constexpr uint8_t buf_size = []() {
329 T v = std::numeric_limits<T>::max();
330 uint8_t i = 0;
331 for (; v != 0; ++i)
332 {
333 v /= base;
334 }
335 return i;
336 }();
337 using buf_type = std::array<char, buf_size>;
338
339 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
340 {
341 uint8_t i = 0;
342 do
343 {
344 if constexpr (std::popcount(base) == 1)
345 {
346 buf[i++] = detail::intLookup[v & 0xf];
347 v >>= 4;
348 }
349 else
350 {
351 buf[i++] = detail::intLookup[v % base];
352 v /= base;
353 }
354 } while (v > 0);
355 return i;
356 }
357
358 constexpr char* operator()(char* buf, T v) const noexcept
359 {
360 uint8_t i = reverseFill(buf, v);
361 std::reverse(buf, buf + i);
362 return buf + i;
363 }
364
365 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
366 {
367 uint8_t i = reverseFill(buf, v);
368 auto end = buf + std::max(i, min_width);
369 std::fill(buf + i, end, '0');
370 std::reverse(buf, end);
371 return end;
372 }
373};
374
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700375template <typename T>
376struct ToAddr
Patrick Williams89d734b2023-05-10 07:50:25 -0500377{};
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700378
379template <>
380struct ToAddr<ether_addr>
381{
382 constexpr ether_addr operator()(std::string_view str) const
383 {
384 constexpr DecodeInt<uint8_t, 16> di;
385 ether_addr ret;
386 if (str.size() == 12 && str.find(":") == str.npos)
387 {
388 for (size_t i = 0; i < 6; ++i)
389 {
390 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
391 }
392 }
393 else
394 {
395 for (size_t i = 0; i < 5; ++i)
396 {
397 auto loc = str.find(":");
398 ret.ether_addr_octet[i] = di(str.substr(0, loc));
399 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
400 if (str.empty())
401 {
402 throw std::invalid_argument("Missing mac data");
403 }
404 }
405 ret.ether_addr_octet[5] = di(str);
406 }
407 return ret;
408 }
409};
410
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700411template <>
412struct ToAddr<in_addr>
413{
414 constexpr in_addr operator()(std::string_view str) const
415 {
416 constexpr DecodeInt<uint8_t, 10> di;
417 uint32_t addr = {};
418 for (size_t i = 0; i < 3; ++i)
419 {
420 auto loc = str.find(".");
421 addr |= di(str.substr(0, loc));
422 addr <<= 8;
423 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
424 if (str.empty())
425 {
426 throw std::invalid_argument("Missing addr data");
427 }
428 }
429 addr |= di(str);
430 return {hton(addr)};
431 }
432};
433
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700434template <>
435struct ToAddr<in6_addr>
436{
437 constexpr in6_addr operator()(std::string_view str) const
438 {
439 constexpr DecodeInt<uint16_t, 16> di;
440 in6_addr ret = {};
441 size_t i = 0;
442 while (i < 8)
443 {
444 auto loc = str.find(':');
445 if (i == 6 && loc == str.npos)
446 {
447 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
448 return ret;
449 }
450 if (loc != 0 && !str.empty())
451 {
452 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
453 }
454 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
455 {
456 str.remove_prefix(loc + 2);
457 break;
458 }
459 else if (str.empty())
460 {
461 throw std::invalid_argument("IPv6 Data");
462 }
463 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
464 }
465 if (str.starts_with(':'))
466 {
467 throw std::invalid_argument("Extra separator");
468 }
469 size_t j = 7;
470 if (!str.empty() && i < 6 && str.find('.') != str.npos)
471 {
472 auto loc = str.rfind(':');
473 ret.s6_addr32[3] =
474 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
475 .s_addr;
476 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
477 j -= 2;
478 }
479 while (!str.empty() && j > i)
480 {
481 auto loc = str.rfind(':');
482 ret.s6_addr16[j--] =
483 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
484 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
485 }
486 if (!str.empty())
487 {
488 throw std::invalid_argument("Too much data");
489 }
490 return ret;
491 }
492};
493
William A. Kennington IIIead71982022-11-04 02:18:10 -0700494template <>
495struct ToAddr<InAddrAny>
496{
497 constexpr InAddrAny operator()(std::string_view str) const
498 {
499 if (str.find(':') == str.npos)
500 {
501 return ToAddr<in_addr>{}(str);
502 }
503 return ToAddr<in6_addr>{}(str);
504 }
505};
506
507template <>
508struct ToAddr<IfAddr>
509{
510 constexpr IfAddr operator()(std::string_view str) const
511 {
512 auto pos = str.rfind('/');
513 if (pos == str.npos)
514 {
515 throw std::invalid_argument("Invalid IfAddr");
516 }
517 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
518 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
519 }
520};
521
William A. Kennington III55bdc362022-11-04 17:57:21 -0700522template <typename T>
523struct ToStr
Patrick Williams89d734b2023-05-10 07:50:25 -0500524{};
William A. Kennington III55bdc362022-11-04 17:57:21 -0700525
526template <>
527struct ToStr<char>
528{
529 static constexpr uint8_t buf_size = 1;
530 using buf_type = std::array<char, buf_size>;
531
532 constexpr char* operator()(char* buf, char v) const noexcept
533 {
534 buf[0] = v;
535 return buf + 1;
536 }
537};
538
539template <>
540struct ToStr<ether_addr>
541{
542 // 6 octets * 2 hex chars + 5 separators
543 static constexpr uint8_t buf_size = 17;
544 using buf_type = std::array<char, buf_size>;
545
546 constexpr char* operator()(char* buf, ether_addr v) const noexcept
547 {
548 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
549 {
550 *ptr = ':';
551 }
552 for (size_t i = 0; i < 6; ++i)
553 {
554 char* tmp = buf + i * 3;
555 uint8_t byte = v.ether_addr_octet[i];
556 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
557 }
558 return buf + buf_size;
559 }
560};
561
562template <>
563struct ToStr<in_addr>
564{
565 // 4 octets * 3 dec chars + 3 separators
566 static constexpr uint8_t buf_size = 15;
567 using buf_type = std::array<char, buf_size>;
568
569 constexpr char* operator()(char* buf, in_addr v) const noexcept
570 {
571 auto n = bswap(ntoh(v.s_addr));
572 for (size_t i = 0; i < 3; ++i)
573 {
574 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
575 n >>= 8;
576 }
577 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
578 }
579};
580
581template <>
582struct ToStr<in6_addr>
583{
584 // 8 hextets * 4 hex chars + 7 separators
585 static constexpr uint8_t buf_size = 39;
586 using buf_type = std::array<char, buf_size>;
587
588 constexpr char* operator()(char* buf, in6_addr v) const noexcept
589 {
590 // IPv4 in IPv6 Addr
591 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
592 v.s6_addr32[2] == hton(uint32_t(0xffff)))
593 {
594 constexpr auto prefix = std::string_view("::ffff:");
595 return ToStr<in_addr>{}(
596 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
597 }
598
599 size_t skip_start = 0;
600 size_t skip_size = 0;
601 {
602 size_t new_start = 0;
603 size_t new_size = 0;
604 for (size_t i = 0; i < 9; ++i)
605 {
606 if (i < 8 && v.s6_addr16[i] == 0)
607 {
608 if (new_start + new_size == i)
609 {
610 new_size++;
611 }
612 else
613 {
614 new_start = i;
615 new_size = 1;
616 }
617 }
618 else if (new_start + new_size == i && new_size > skip_size)
619 {
620 skip_start = new_start;
621 skip_size = new_size;
622 }
623 }
624 }
625 for (size_t i = 0; i < 8; ++i)
626 {
627 if (i == skip_start && skip_size > 1)
628 {
629 if (i == 0)
630 {
631 *(buf++) = ':';
632 }
633 *(buf++) = ':';
634 i += skip_size - 1;
635 continue;
636 }
637 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
638 if (i < 7)
639 {
640 *(buf++) = ':';
641 }
642 }
643 return buf;
644 }
645};
646
647template <>
648struct ToStr<InAddrAny>
649{
650 // IPv6 is the bigger of the addrs
651 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
652 using buf_type = std::array<char, buf_size>;
653
654 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
655 {
656 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
657 v);
658 }
659};
660
661template <>
662struct ToStr<IfAddr>
663{
664 // InAddrAny + sep + 3 prefix chars
665 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
666 using buf_type = std::array<char, buf_size>;
667
668 constexpr char* operator()(char* buf, IfAddr v) const noexcept
669 {
670 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
671 buf = ToStr<char>{}(buf, '/');
672 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
673 }
674};
675
William A. Kennington III238ef992022-11-03 12:47:49 -0700676namespace detail
677{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800678
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700679template <typename T>
680constexpr bool vcontains() noexcept
681{
682 return false;
683}
684
685template <typename T, typename V, typename... Vs>
686constexpr bool vcontains() noexcept
687{
688 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
689}
690
691template <typename T, typename... Types>
692constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
693 veq(T t, std::variant<Types...> v) noexcept
694{
695 return std::visit(
696 [t](auto v) {
Patrick Williams89d734b2023-05-10 07:50:25 -0500697 if constexpr (std::is_same_v<T, decltype(v)>)
698 {
699 return v == t;
700 }
701 else
702 {
703 return false;
704 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700705 },
706 v);
707}
708
709template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700710struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700711{
712 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700713 constexpr std::string_view operator()(T v) noexcept
714 {
715 return {buf.data(), ToStr<T>{}(buf.data(), v)};
716 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700717
718 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700719 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700720};
721
William A. Kennington III55bdc362022-11-04 17:57:21 -0700722template <typename T>
723struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700724{
725 private:
726 fmt::formatter<std::string_view> formatter;
727
728 public:
729 template <typename ParseContext>
730 constexpr auto parse(ParseContext& ctx)
731 {
732 return ctx.begin();
733 }
734
735 template <typename FormatContext>
736 auto format(auto v, FormatContext& ctx) const
737 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700738 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700739 }
740};
741} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500742} // namespace network
743} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700744
745template <typename... Ts>
746struct std::hash<std::tuple<Ts...>>
747{
748 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
749 {
750 return std::apply(phosphor::network::hash_multi<Ts...>, t);
751 }
752};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700753
William A. Kennington III653114f2022-11-01 22:34:04 -0700754template <>
755struct std::hash<in_addr>
756{
757 std::size_t operator()(in_addr addr) const noexcept;
758};
759
760template <>
761struct std::hash<in6_addr>
762{
763 std::size_t operator()(in6_addr addr) const noexcept;
764};
765
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800766template <>
767struct std::hash<phosphor::network::IfAddr>
768{
769 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
770};
771
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700772namespace fmt
773{
774template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700775struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500776{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700777template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700778struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500779{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700780template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700781struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500782{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700783template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500784struct formatter<phosphor::network::InAddrAny> :
785 phosphor::network::detail::Format<phosphor::network::InAddrAny>
786{};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800787template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500788struct formatter<phosphor::network::IfAddr> :
789 phosphor::network::detail::Format<phosphor::network::IfAddr>
790{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700791} // namespace fmt
792
793namespace std
794{
795string to_string(ether_addr value);
796string to_string(in_addr value);
797string to_string(in6_addr value);
798string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800799string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700800} // namespace std
801
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700802template <typename T>
803constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
804 bool>
805 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
806{
807 return phosphor::network::detail::veq(rhs, lhs);
808}
809
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700810auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700811{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700812 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700813}
814
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700815auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700816{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700817 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700818}
819
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700820auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700821{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700822 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700823}
824
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700825auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700826{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700827 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
828 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700829}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800830
831auto& operator<<(auto& os, phosphor::network::IfAddr v)
832{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700833 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
834 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800835}
William A. Kennington III13d665c2022-11-15 20:34:40 -0800836
837namespace phosphor::network
838{
839
840/** @brief Contains all of the object information about the interface */
841struct AllIntfInfo
842{
843 InterfaceInfo intf;
844 std::optional<in_addr> defgw4 = std::nullopt;
845 std::optional<in6_addr> defgw6 = std::nullopt;
846 std::unordered_map<IfAddr, AddressInfo> addrs = {};
847 std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
848};
849
850} // namespace phosphor::network