blob: 6351b242951d71e14e0733a01c419e3f22e78ea0 [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{
William A. Kennington III9c441fd2023-02-24 13:40:01 -080084 unsigned short type;
William A. Kennington III454a0de2022-11-12 01:01:04 -080085 unsigned idx;
86 unsigned flags;
87 std::optional<std::string> name = std::nullopt;
88 std::optional<ether_addr> mac = std::nullopt;
89 std::optional<unsigned> mtu = std::nullopt;
90 std::optional<unsigned> parent_idx = std::nullopt;
91 std::optional<std::string> kind = std::nullopt;
92 std::optional<uint16_t> vlan_id = std::nullopt;
93
94 constexpr bool operator==(const InterfaceInfo& rhs) const noexcept
95 {
96 return idx == rhs.idx && flags == rhs.flags && name == rhs.name &&
97 mac == rhs.mac && mtu == rhs.mtu &&
98 parent_idx == rhs.parent_idx && kind == rhs.kind &&
99 vlan_id == rhs.vlan_id;
100 }
101};
102
William A. Kennington III6a923632022-11-06 18:17:33 -0800103/** @class AddressInfo
104 * @brief Information about a addresses from the kernel
105 */
106struct AddressInfo
107{
108 unsigned ifidx;
109 IfAddr ifaddr;
110 uint8_t scope;
111 uint32_t flags;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800112
113 constexpr bool operator==(const AddressInfo& rhs) const noexcept
114 {
115 return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr &&
116 scope == rhs.scope && flags == rhs.flags;
117 }
William A. Kennington III6a923632022-11-06 18:17:33 -0800118};
119
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800120/** @class NeighborInfo
121 * @brief Information about a neighbor from the kernel
122 */
123struct NeighborInfo
124{
125 unsigned ifidx;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800126 uint16_t state;
William A. Kennington IIId3615142022-11-12 01:28:33 -0800127 std::optional<InAddrAny> addr;
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800128 std::optional<ether_addr> mac;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800129
130 constexpr bool operator==(const NeighborInfo& rhs) const noexcept
131 {
132 return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr &&
133 mac == rhs.mac;
134 }
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800135};
136
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700137struct string_hash : public std::hash<std::string_view>
138{
139 using is_transparent = void;
140};
141template <typename V>
142using string_umap =
143 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -0700144using string_uset =
145 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700146
William A. Kennington III3e471c52022-10-27 19:46:07 -0700147constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700148{
149 return 0;
150}
151
152template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700153constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700154{
155 const std::size_t seed = hash_multi(args...);
156 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
157}
158
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700159namespace detail
160{
161
William A. Kennington III71de63a2022-11-08 10:50:54 -0800162template <typename T, uint8_t size = sizeof(T)>
163struct BswapAlign
164{
165 using type = T;
166};
167
168template <typename T>
169struct BswapAlign<T, 2>
170{
171 using type alignas(uint16_t) = T;
172};
173
174template <typename T>
175struct BswapAlign<T, 4>
176{
177 using type alignas(uint32_t) = T;
178};
179
180template <typename T>
181struct BswapAlign<T, 8>
182{
183 using type alignas(uint64_t) = T;
184};
185
186template <typename T>
187constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
188{
189 static_assert(std::is_trivially_copyable_v<T>);
190 if constexpr (sizeof(T) == 2)
191 {
192 reinterpret_cast<uint16_t&>(n) =
193 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
194 }
195 else if constexpr (sizeof(T) == 4)
196 {
197 reinterpret_cast<uint32_t&>(n) =
198 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
199 }
200 else if constexpr (sizeof(T) == 8)
201 {
202 reinterpret_cast<uint64_t&>(n) =
203 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
204 }
205 else
206 {
207 auto b = reinterpret_cast<std::byte*>(&n);
208 std::reverse(b, b + sizeof(n));
209 }
210 return n;
211}
212
213} // namespace detail
214
215template <typename T>
216constexpr T bswap(T n) noexcept
217{
218 return detail::bswapInt<T>(n);
219}
220
221template <typename T>
222constexpr T hton(T n) noexcept
223{
224 if constexpr (std::endian::native == std::endian::big)
225 {
226 return n;
227 }
228 else if constexpr (std::endian::native == std::endian::little)
229 {
230 return bswap(n);
231 }
232 else
233 {
234 static_assert(std::is_same_v<T, void>);
235 }
236}
237
238template <typename T>
239constexpr T ntoh(T n) noexcept
240{
241 return hton(n);
242}
243
244namespace detail
245{
William A. Kennington III238ef992022-11-03 12:47:49 -0700246inline constexpr auto charLookup = []() {
247 std::array<int8_t, 256> ret;
248 std::fill(ret.begin(), ret.end(), -1);
249 for (int8_t i = 0; i < 10; ++i)
250 {
251 ret[i + '0'] = i;
252 }
253 for (int8_t i = 0; i < 26; ++i)
254 {
255 ret[i + 'A'] = i + 10;
256 ret[i + 'a'] = i + 10;
257 }
258 return ret;
259}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700260inline constexpr auto intLookup = []() {
261 std::array<char, 36> ret;
262 for (int8_t i = 0; i < 10; ++i)
263 {
264 ret[i] = i + '0';
265 }
266 for (int8_t i = 0; i < 26; ++i)
267 {
268 ret[i + 10] = i + 'a';
269 }
270 return ret;
271}();
272} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700273
274template <typename T, uint8_t base>
275struct DecodeInt
276{
277 static_assert(base > 1 && base <= 36);
278 static_assert(std::is_unsigned_v<T>);
279
280 constexpr T operator()(std::string_view str) const
281 {
282 if (str.empty())
283 {
284 throw std::invalid_argument("Empty Str");
285 }
286 constexpr auto max = std::numeric_limits<T>::max();
Patrick Williams89d734b2023-05-10 07:50:25 -0500287 auto ret = std::accumulate(str.begin(), str.end(), T{},
288 [&](T r, char c) {
289 auto v = detail::charLookup[c];
290 if (v < 0 || v >= base)
291 {
292 throw std::invalid_argument("Invalid numeral");
293 }
294 if constexpr (std::popcount(base) == 1)
295 {
296 constexpr auto shift = std::countr_zero(base);
297 constexpr auto maxshift = max >> shift;
298 if (r > maxshift)
William A. Kennington III238ef992022-11-03 12:47:49 -0700299 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500300 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700301 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500302 return (r << shift) | v;
303 }
304 else
305 {
306 constexpr auto maxbase = max / base;
307 if (r > maxbase)
William A. Kennington III238ef992022-11-03 12:47:49 -0700308 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500309 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700310 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500311 r *= base;
312 if (max - v < r)
William A. Kennington III238ef992022-11-03 12:47:49 -0700313 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500314 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700315 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500316 return r + v;
317 }
318 });
William A. Kennington III238ef992022-11-03 12:47:49 -0700319 return ret;
320 }
321};
322
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700323template <typename T, uint8_t base>
324struct EncodeInt
325{
326 static_assert(base > 1 && base <= 36);
327 static_assert(std::is_unsigned_v<T>);
328
329 static constexpr uint8_t buf_size = []() {
330 T v = std::numeric_limits<T>::max();
331 uint8_t i = 0;
332 for (; v != 0; ++i)
333 {
334 v /= base;
335 }
336 return i;
337 }();
338 using buf_type = std::array<char, buf_size>;
339
340 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
341 {
342 uint8_t i = 0;
343 do
344 {
345 if constexpr (std::popcount(base) == 1)
346 {
347 buf[i++] = detail::intLookup[v & 0xf];
348 v >>= 4;
349 }
350 else
351 {
352 buf[i++] = detail::intLookup[v % base];
353 v /= base;
354 }
355 } while (v > 0);
356 return i;
357 }
358
359 constexpr char* operator()(char* buf, T v) const noexcept
360 {
361 uint8_t i = reverseFill(buf, v);
362 std::reverse(buf, buf + i);
363 return buf + i;
364 }
365
366 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
367 {
368 uint8_t i = reverseFill(buf, v);
369 auto end = buf + std::max(i, min_width);
370 std::fill(buf + i, end, '0');
371 std::reverse(buf, end);
372 return end;
373 }
374};
375
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700376template <typename T>
377struct ToAddr
Patrick Williams89d734b2023-05-10 07:50:25 -0500378{};
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700379
380template <>
381struct ToAddr<ether_addr>
382{
383 constexpr ether_addr operator()(std::string_view str) const
384 {
385 constexpr DecodeInt<uint8_t, 16> di;
386 ether_addr ret;
387 if (str.size() == 12 && str.find(":") == str.npos)
388 {
389 for (size_t i = 0; i < 6; ++i)
390 {
391 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
392 }
393 }
394 else
395 {
396 for (size_t i = 0; i < 5; ++i)
397 {
398 auto loc = str.find(":");
399 ret.ether_addr_octet[i] = di(str.substr(0, loc));
400 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
401 if (str.empty())
402 {
403 throw std::invalid_argument("Missing mac data");
404 }
405 }
406 ret.ether_addr_octet[5] = di(str);
407 }
408 return ret;
409 }
410};
411
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700412template <>
413struct ToAddr<in_addr>
414{
415 constexpr in_addr operator()(std::string_view str) const
416 {
417 constexpr DecodeInt<uint8_t, 10> di;
418 uint32_t addr = {};
419 for (size_t i = 0; i < 3; ++i)
420 {
421 auto loc = str.find(".");
422 addr |= di(str.substr(0, loc));
423 addr <<= 8;
424 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
425 if (str.empty())
426 {
427 throw std::invalid_argument("Missing addr data");
428 }
429 }
430 addr |= di(str);
431 return {hton(addr)};
432 }
433};
434
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700435template <>
436struct ToAddr<in6_addr>
437{
438 constexpr in6_addr operator()(std::string_view str) const
439 {
440 constexpr DecodeInt<uint16_t, 16> di;
441 in6_addr ret = {};
442 size_t i = 0;
443 while (i < 8)
444 {
445 auto loc = str.find(':');
446 if (i == 6 && loc == str.npos)
447 {
448 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
449 return ret;
450 }
451 if (loc != 0 && !str.empty())
452 {
453 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
454 }
455 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
456 {
457 str.remove_prefix(loc + 2);
458 break;
459 }
460 else if (str.empty())
461 {
462 throw std::invalid_argument("IPv6 Data");
463 }
464 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
465 }
466 if (str.starts_with(':'))
467 {
468 throw std::invalid_argument("Extra separator");
469 }
470 size_t j = 7;
471 if (!str.empty() && i < 6 && str.find('.') != str.npos)
472 {
473 auto loc = str.rfind(':');
474 ret.s6_addr32[3] =
475 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
476 .s_addr;
477 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
478 j -= 2;
479 }
480 while (!str.empty() && j > i)
481 {
482 auto loc = str.rfind(':');
483 ret.s6_addr16[j--] =
484 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
485 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
486 }
487 if (!str.empty())
488 {
489 throw std::invalid_argument("Too much data");
490 }
491 return ret;
492 }
493};
494
William A. Kennington IIIead71982022-11-04 02:18:10 -0700495template <>
496struct ToAddr<InAddrAny>
497{
498 constexpr InAddrAny operator()(std::string_view str) const
499 {
500 if (str.find(':') == str.npos)
501 {
502 return ToAddr<in_addr>{}(str);
503 }
504 return ToAddr<in6_addr>{}(str);
505 }
506};
507
508template <>
509struct ToAddr<IfAddr>
510{
511 constexpr IfAddr operator()(std::string_view str) const
512 {
513 auto pos = str.rfind('/');
514 if (pos == str.npos)
515 {
516 throw std::invalid_argument("Invalid IfAddr");
517 }
518 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
519 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
520 }
521};
522
William A. Kennington III55bdc362022-11-04 17:57:21 -0700523template <typename T>
524struct ToStr
Patrick Williams89d734b2023-05-10 07:50:25 -0500525{};
William A. Kennington III55bdc362022-11-04 17:57:21 -0700526
527template <>
528struct ToStr<char>
529{
530 static constexpr uint8_t buf_size = 1;
531 using buf_type = std::array<char, buf_size>;
532
533 constexpr char* operator()(char* buf, char v) const noexcept
534 {
535 buf[0] = v;
536 return buf + 1;
537 }
538};
539
540template <>
541struct ToStr<ether_addr>
542{
543 // 6 octets * 2 hex chars + 5 separators
544 static constexpr uint8_t buf_size = 17;
545 using buf_type = std::array<char, buf_size>;
546
547 constexpr char* operator()(char* buf, ether_addr v) const noexcept
548 {
549 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
550 {
551 *ptr = ':';
552 }
553 for (size_t i = 0; i < 6; ++i)
554 {
555 char* tmp = buf + i * 3;
556 uint8_t byte = v.ether_addr_octet[i];
557 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
558 }
559 return buf + buf_size;
560 }
561};
562
563template <>
564struct ToStr<in_addr>
565{
566 // 4 octets * 3 dec chars + 3 separators
567 static constexpr uint8_t buf_size = 15;
568 using buf_type = std::array<char, buf_size>;
569
570 constexpr char* operator()(char* buf, in_addr v) const noexcept
571 {
572 auto n = bswap(ntoh(v.s_addr));
573 for (size_t i = 0; i < 3; ++i)
574 {
575 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
576 n >>= 8;
577 }
578 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
579 }
580};
581
582template <>
583struct ToStr<in6_addr>
584{
585 // 8 hextets * 4 hex chars + 7 separators
586 static constexpr uint8_t buf_size = 39;
587 using buf_type = std::array<char, buf_size>;
588
589 constexpr char* operator()(char* buf, in6_addr v) const noexcept
590 {
591 // IPv4 in IPv6 Addr
592 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
593 v.s6_addr32[2] == hton(uint32_t(0xffff)))
594 {
595 constexpr auto prefix = std::string_view("::ffff:");
596 return ToStr<in_addr>{}(
597 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
598 }
599
600 size_t skip_start = 0;
601 size_t skip_size = 0;
602 {
603 size_t new_start = 0;
604 size_t new_size = 0;
605 for (size_t i = 0; i < 9; ++i)
606 {
607 if (i < 8 && v.s6_addr16[i] == 0)
608 {
609 if (new_start + new_size == i)
610 {
611 new_size++;
612 }
613 else
614 {
615 new_start = i;
616 new_size = 1;
617 }
618 }
619 else if (new_start + new_size == i && new_size > skip_size)
620 {
621 skip_start = new_start;
622 skip_size = new_size;
623 }
624 }
625 }
626 for (size_t i = 0; i < 8; ++i)
627 {
628 if (i == skip_start && skip_size > 1)
629 {
630 if (i == 0)
631 {
632 *(buf++) = ':';
633 }
634 *(buf++) = ':';
635 i += skip_size - 1;
636 continue;
637 }
638 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
639 if (i < 7)
640 {
641 *(buf++) = ':';
642 }
643 }
644 return buf;
645 }
646};
647
648template <>
649struct ToStr<InAddrAny>
650{
651 // IPv6 is the bigger of the addrs
652 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
653 using buf_type = std::array<char, buf_size>;
654
655 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
656 {
657 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
658 v);
659 }
660};
661
662template <>
663struct ToStr<IfAddr>
664{
665 // InAddrAny + sep + 3 prefix chars
666 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
667 using buf_type = std::array<char, buf_size>;
668
669 constexpr char* operator()(char* buf, IfAddr v) const noexcept
670 {
671 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
672 buf = ToStr<char>{}(buf, '/');
673 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
674 }
675};
676
William A. Kennington III238ef992022-11-03 12:47:49 -0700677namespace detail
678{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800679
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700680template <typename T>
681constexpr bool vcontains() noexcept
682{
683 return false;
684}
685
686template <typename T, typename V, typename... Vs>
687constexpr bool vcontains() noexcept
688{
689 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
690}
691
692template <typename T, typename... Types>
693constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
694 veq(T t, std::variant<Types...> v) noexcept
695{
696 return std::visit(
697 [t](auto v) {
Patrick Williams89d734b2023-05-10 07:50:25 -0500698 if constexpr (std::is_same_v<T, decltype(v)>)
699 {
700 return v == t;
701 }
702 else
703 {
704 return false;
705 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700706 },
707 v);
708}
709
710template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700711struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700712{
713 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700714 constexpr std::string_view operator()(T v) noexcept
715 {
716 return {buf.data(), ToStr<T>{}(buf.data(), v)};
717 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700718
719 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700720 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700721};
722
William A. Kennington III55bdc362022-11-04 17:57:21 -0700723template <typename T>
724struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700725{
726 private:
727 fmt::formatter<std::string_view> formatter;
728
729 public:
730 template <typename ParseContext>
731 constexpr auto parse(ParseContext& ctx)
732 {
733 return ctx.begin();
734 }
735
736 template <typename FormatContext>
737 auto format(auto v, FormatContext& ctx) const
738 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700739 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700740 }
741};
742} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500743} // namespace network
744} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700745
746template <typename... Ts>
747struct std::hash<std::tuple<Ts...>>
748{
749 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
750 {
751 return std::apply(phosphor::network::hash_multi<Ts...>, t);
752 }
753};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700754
William A. Kennington III653114f2022-11-01 22:34:04 -0700755template <>
756struct std::hash<in_addr>
757{
758 std::size_t operator()(in_addr addr) const noexcept;
759};
760
761template <>
762struct std::hash<in6_addr>
763{
764 std::size_t operator()(in6_addr addr) const noexcept;
765};
766
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800767template <>
768struct std::hash<phosphor::network::IfAddr>
769{
770 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
771};
772
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700773namespace fmt
774{
775template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700776struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500777{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700778template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700779struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500780{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700781template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700782struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500783{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700784template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500785struct formatter<phosphor::network::InAddrAny> :
786 phosphor::network::detail::Format<phosphor::network::InAddrAny>
787{};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800788template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500789struct formatter<phosphor::network::IfAddr> :
790 phosphor::network::detail::Format<phosphor::network::IfAddr>
791{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700792} // namespace fmt
793
794namespace std
795{
796string to_string(ether_addr value);
797string to_string(in_addr value);
798string to_string(in6_addr value);
799string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800800string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700801} // namespace std
802
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700803template <typename T>
804constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
805 bool>
806 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
807{
808 return phosphor::network::detail::veq(rhs, lhs);
809}
810
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700811auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700812{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700813 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700814}
815
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700816auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700817{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700818 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700819}
820
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700821auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700822{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700823 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700824}
825
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700826auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700827{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700828 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
829 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700830}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800831
832auto& operator<<(auto& os, phosphor::network::IfAddr v)
833{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700834 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
835 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800836}
William A. Kennington III13d665c2022-11-15 20:34:40 -0800837
838namespace phosphor::network
839{
840
841/** @brief Contains all of the object information about the interface */
842struct AllIntfInfo
843{
844 InterfaceInfo intf;
845 std::optional<in_addr> defgw4 = std::nullopt;
846 std::optional<in6_addr> defgw6 = std::nullopt;
847 std::unordered_map<IfAddr, AddressInfo> addrs = {};
848 std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
849};
850
851} // namespace phosphor::network