blob: 53a3c89d7f0d37814a5948eda10461949ae1fb5f [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 IIIbb0eacc2022-10-21 15:22:06 -0700137namespace detail
138{
139
William A. Kennington III71de63a2022-11-08 10:50:54 -0800140template <typename T, uint8_t size = sizeof(T)>
141struct BswapAlign
142{
143 using type = T;
144};
145
146template <typename T>
147struct BswapAlign<T, 2>
148{
149 using type alignas(uint16_t) = T;
150};
151
152template <typename T>
153struct BswapAlign<T, 4>
154{
155 using type alignas(uint32_t) = T;
156};
157
158template <typename T>
159struct BswapAlign<T, 8>
160{
161 using type alignas(uint64_t) = T;
162};
163
164template <typename T>
165constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
166{
167 static_assert(std::is_trivially_copyable_v<T>);
168 if constexpr (sizeof(T) == 2)
169 {
170 reinterpret_cast<uint16_t&>(n) =
171 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
172 }
173 else if constexpr (sizeof(T) == 4)
174 {
175 reinterpret_cast<uint32_t&>(n) =
176 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
177 }
178 else if constexpr (sizeof(T) == 8)
179 {
180 reinterpret_cast<uint64_t&>(n) =
181 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
182 }
183 else
184 {
185 auto b = reinterpret_cast<std::byte*>(&n);
186 std::reverse(b, b + sizeof(n));
187 }
188 return n;
189}
190
191} // namespace detail
192
193template <typename T>
194constexpr T bswap(T n) noexcept
195{
196 return detail::bswapInt<T>(n);
197}
198
199template <typename T>
200constexpr T hton(T n) noexcept
201{
202 if constexpr (std::endian::native == std::endian::big)
203 {
204 return n;
205 }
206 else if constexpr (std::endian::native == std::endian::little)
207 {
208 return bswap(n);
209 }
210 else
211 {
212 static_assert(std::is_same_v<T, void>);
213 }
214}
215
216template <typename T>
217constexpr T ntoh(T n) noexcept
218{
219 return hton(n);
220}
221
222namespace detail
223{
William A. Kennington III238ef992022-11-03 12:47:49 -0700224inline constexpr auto charLookup = []() {
225 std::array<int8_t, 256> ret;
226 std::fill(ret.begin(), ret.end(), -1);
227 for (int8_t i = 0; i < 10; ++i)
228 {
229 ret[i + '0'] = i;
230 }
231 for (int8_t i = 0; i < 26; ++i)
232 {
233 ret[i + 'A'] = i + 10;
234 ret[i + 'a'] = i + 10;
235 }
236 return ret;
237}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700238inline constexpr auto intLookup = []() {
239 std::array<char, 36> ret;
240 for (int8_t i = 0; i < 10; ++i)
241 {
242 ret[i] = i + '0';
243 }
244 for (int8_t i = 0; i < 26; ++i)
245 {
246 ret[i + 10] = i + 'a';
247 }
248 return ret;
249}();
250} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700251
252template <typename T, uint8_t base>
253struct DecodeInt
254{
255 static_assert(base > 1 && base <= 36);
256 static_assert(std::is_unsigned_v<T>);
257
258 constexpr T operator()(std::string_view str) const
259 {
260 if (str.empty())
261 {
262 throw std::invalid_argument("Empty Str");
263 }
264 constexpr auto max = std::numeric_limits<T>::max();
Patrick Williams89d734b2023-05-10 07:50:25 -0500265 auto ret = std::accumulate(str.begin(), str.end(), T{},
266 [&](T r, char c) {
267 auto v = detail::charLookup[c];
268 if (v < 0 || v >= base)
269 {
270 throw std::invalid_argument("Invalid numeral");
271 }
272 if constexpr (std::popcount(base) == 1)
273 {
274 constexpr auto shift = std::countr_zero(base);
275 constexpr auto maxshift = max >> shift;
276 if (r > maxshift)
William A. Kennington III238ef992022-11-03 12:47:49 -0700277 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500278 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700279 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500280 return (r << shift) | v;
281 }
282 else
283 {
284 constexpr auto maxbase = max / base;
285 if (r > maxbase)
William A. Kennington III238ef992022-11-03 12:47:49 -0700286 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500287 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700288 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500289 r *= base;
290 if (max - v < r)
William A. Kennington III238ef992022-11-03 12:47:49 -0700291 {
Patrick Williams89d734b2023-05-10 07:50:25 -0500292 throw std::overflow_error("Integer Decode");
William A. Kennington III238ef992022-11-03 12:47:49 -0700293 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500294 return r + v;
295 }
296 });
William A. Kennington III238ef992022-11-03 12:47:49 -0700297 return ret;
298 }
299};
300
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700301template <typename T, uint8_t base>
302struct EncodeInt
303{
304 static_assert(base > 1 && base <= 36);
305 static_assert(std::is_unsigned_v<T>);
306
307 static constexpr uint8_t buf_size = []() {
308 T v = std::numeric_limits<T>::max();
309 uint8_t i = 0;
310 for (; v != 0; ++i)
311 {
312 v /= base;
313 }
314 return i;
315 }();
316 using buf_type = std::array<char, buf_size>;
317
318 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
319 {
320 uint8_t i = 0;
321 do
322 {
323 if constexpr (std::popcount(base) == 1)
324 {
325 buf[i++] = detail::intLookup[v & 0xf];
326 v >>= 4;
327 }
328 else
329 {
330 buf[i++] = detail::intLookup[v % base];
331 v /= base;
332 }
333 } while (v > 0);
334 return i;
335 }
336
337 constexpr char* operator()(char* buf, T v) const noexcept
338 {
339 uint8_t i = reverseFill(buf, v);
340 std::reverse(buf, buf + i);
341 return buf + i;
342 }
343
344 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
345 {
346 uint8_t i = reverseFill(buf, v);
347 auto end = buf + std::max(i, min_width);
348 std::fill(buf + i, end, '0');
349 std::reverse(buf, end);
350 return end;
351 }
352};
353
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700354template <typename T>
355struct ToAddr
Patrick Williams89d734b2023-05-10 07:50:25 -0500356{};
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700357
358template <>
359struct ToAddr<ether_addr>
360{
361 constexpr ether_addr operator()(std::string_view str) const
362 {
363 constexpr DecodeInt<uint8_t, 16> di;
364 ether_addr ret;
365 if (str.size() == 12 && str.find(":") == str.npos)
366 {
367 for (size_t i = 0; i < 6; ++i)
368 {
369 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
370 }
371 }
372 else
373 {
374 for (size_t i = 0; i < 5; ++i)
375 {
376 auto loc = str.find(":");
377 ret.ether_addr_octet[i] = di(str.substr(0, loc));
378 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
379 if (str.empty())
380 {
381 throw std::invalid_argument("Missing mac data");
382 }
383 }
384 ret.ether_addr_octet[5] = di(str);
385 }
386 return ret;
387 }
388};
389
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700390template <>
391struct ToAddr<in_addr>
392{
393 constexpr in_addr operator()(std::string_view str) const
394 {
395 constexpr DecodeInt<uint8_t, 10> di;
396 uint32_t addr = {};
397 for (size_t i = 0; i < 3; ++i)
398 {
399 auto loc = str.find(".");
400 addr |= di(str.substr(0, loc));
401 addr <<= 8;
402 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
403 if (str.empty())
404 {
405 throw std::invalid_argument("Missing addr data");
406 }
407 }
408 addr |= di(str);
409 return {hton(addr)};
410 }
411};
412
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700413template <>
414struct ToAddr<in6_addr>
415{
416 constexpr in6_addr operator()(std::string_view str) const
417 {
418 constexpr DecodeInt<uint16_t, 16> di;
419 in6_addr ret = {};
420 size_t i = 0;
421 while (i < 8)
422 {
423 auto loc = str.find(':');
424 if (i == 6 && loc == str.npos)
425 {
426 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
427 return ret;
428 }
429 if (loc != 0 && !str.empty())
430 {
431 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
432 }
433 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
434 {
435 str.remove_prefix(loc + 2);
436 break;
437 }
438 else if (str.empty())
439 {
440 throw std::invalid_argument("IPv6 Data");
441 }
442 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
443 }
444 if (str.starts_with(':'))
445 {
446 throw std::invalid_argument("Extra separator");
447 }
448 size_t j = 7;
449 if (!str.empty() && i < 6 && str.find('.') != str.npos)
450 {
451 auto loc = str.rfind(':');
452 ret.s6_addr32[3] =
453 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
454 .s_addr;
455 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
456 j -= 2;
457 }
458 while (!str.empty() && j > i)
459 {
460 auto loc = str.rfind(':');
461 ret.s6_addr16[j--] =
462 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
463 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
464 }
465 if (!str.empty())
466 {
467 throw std::invalid_argument("Too much data");
468 }
469 return ret;
470 }
471};
472
William A. Kennington IIIead71982022-11-04 02:18:10 -0700473template <>
474struct ToAddr<InAddrAny>
475{
476 constexpr InAddrAny operator()(std::string_view str) const
477 {
478 if (str.find(':') == str.npos)
479 {
480 return ToAddr<in_addr>{}(str);
481 }
482 return ToAddr<in6_addr>{}(str);
483 }
484};
485
486template <>
487struct ToAddr<IfAddr>
488{
489 constexpr IfAddr operator()(std::string_view str) const
490 {
491 auto pos = str.rfind('/');
492 if (pos == str.npos)
493 {
494 throw std::invalid_argument("Invalid IfAddr");
495 }
496 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
497 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
498 }
499};
500
William A. Kennington III55bdc362022-11-04 17:57:21 -0700501template <typename T>
502struct ToStr
Patrick Williams89d734b2023-05-10 07:50:25 -0500503{};
William A. Kennington III55bdc362022-11-04 17:57:21 -0700504
505template <>
506struct ToStr<char>
507{
508 static constexpr uint8_t buf_size = 1;
509 using buf_type = std::array<char, buf_size>;
510
511 constexpr char* operator()(char* buf, char v) const noexcept
512 {
513 buf[0] = v;
514 return buf + 1;
515 }
516};
517
518template <>
519struct ToStr<ether_addr>
520{
521 // 6 octets * 2 hex chars + 5 separators
522 static constexpr uint8_t buf_size = 17;
523 using buf_type = std::array<char, buf_size>;
524
525 constexpr char* operator()(char* buf, ether_addr v) const noexcept
526 {
527 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
528 {
529 *ptr = ':';
530 }
531 for (size_t i = 0; i < 6; ++i)
532 {
533 char* tmp = buf + i * 3;
534 uint8_t byte = v.ether_addr_octet[i];
535 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
536 }
537 return buf + buf_size;
538 }
539};
540
541template <>
542struct ToStr<in_addr>
543{
544 // 4 octets * 3 dec chars + 3 separators
545 static constexpr uint8_t buf_size = 15;
546 using buf_type = std::array<char, buf_size>;
547
548 constexpr char* operator()(char* buf, in_addr v) const noexcept
549 {
550 auto n = bswap(ntoh(v.s_addr));
551 for (size_t i = 0; i < 3; ++i)
552 {
553 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
554 n >>= 8;
555 }
556 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
557 }
558};
559
560template <>
561struct ToStr<in6_addr>
562{
563 // 8 hextets * 4 hex chars + 7 separators
564 static constexpr uint8_t buf_size = 39;
565 using buf_type = std::array<char, buf_size>;
566
567 constexpr char* operator()(char* buf, in6_addr v) const noexcept
568 {
569 // IPv4 in IPv6 Addr
570 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
571 v.s6_addr32[2] == hton(uint32_t(0xffff)))
572 {
573 constexpr auto prefix = std::string_view("::ffff:");
574 return ToStr<in_addr>{}(
575 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
576 }
577
578 size_t skip_start = 0;
579 size_t skip_size = 0;
580 {
581 size_t new_start = 0;
582 size_t new_size = 0;
583 for (size_t i = 0; i < 9; ++i)
584 {
585 if (i < 8 && v.s6_addr16[i] == 0)
586 {
587 if (new_start + new_size == i)
588 {
589 new_size++;
590 }
591 else
592 {
593 new_start = i;
594 new_size = 1;
595 }
596 }
597 else if (new_start + new_size == i && new_size > skip_size)
598 {
599 skip_start = new_start;
600 skip_size = new_size;
601 }
602 }
603 }
604 for (size_t i = 0; i < 8; ++i)
605 {
606 if (i == skip_start && skip_size > 1)
607 {
608 if (i == 0)
609 {
610 *(buf++) = ':';
611 }
612 *(buf++) = ':';
613 i += skip_size - 1;
614 continue;
615 }
616 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
617 if (i < 7)
618 {
619 *(buf++) = ':';
620 }
621 }
622 return buf;
623 }
624};
625
626template <>
627struct ToStr<InAddrAny>
628{
629 // IPv6 is the bigger of the addrs
630 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
631 using buf_type = std::array<char, buf_size>;
632
633 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
634 {
635 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
636 v);
637 }
638};
639
640template <>
641struct ToStr<IfAddr>
642{
643 // InAddrAny + sep + 3 prefix chars
644 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
645 using buf_type = std::array<char, buf_size>;
646
647 constexpr char* operator()(char* buf, IfAddr v) const noexcept
648 {
649 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
650 buf = ToStr<char>{}(buf, '/');
651 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
652 }
653};
654
William A. Kennington III238ef992022-11-03 12:47:49 -0700655namespace detail
656{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800657
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700658template <typename T>
659constexpr bool vcontains() noexcept
660{
661 return false;
662}
663
664template <typename T, typename V, typename... Vs>
665constexpr bool vcontains() noexcept
666{
667 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
668}
669
670template <typename T, typename... Types>
671constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
672 veq(T t, std::variant<Types...> v) noexcept
673{
674 return std::visit(
675 [t](auto v) {
Patrick Williams89d734b2023-05-10 07:50:25 -0500676 if constexpr (std::is_same_v<T, decltype(v)>)
677 {
678 return v == t;
679 }
680 else
681 {
682 return false;
683 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700684 },
685 v);
686}
687
688template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700689struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700690{
691 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700692 constexpr std::string_view operator()(T v) noexcept
693 {
694 return {buf.data(), ToStr<T>{}(buf.data(), v)};
695 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700696
697 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700698 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700699};
700
William A. Kennington III55bdc362022-11-04 17:57:21 -0700701template <typename T>
702struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700703{
704 private:
705 fmt::formatter<std::string_view> formatter;
706
707 public:
708 template <typename ParseContext>
709 constexpr auto parse(ParseContext& ctx)
710 {
711 return ctx.begin();
712 }
713
714 template <typename FormatContext>
715 auto format(auto v, FormatContext& ctx) const
716 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700717 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700718 }
719};
720} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500721} // namespace network
722} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700723
William A. Kennington III653114f2022-11-01 22:34:04 -0700724template <>
725struct std::hash<in_addr>
726{
727 std::size_t operator()(in_addr addr) const noexcept;
728};
729
730template <>
731struct std::hash<in6_addr>
732{
733 std::size_t operator()(in6_addr addr) const noexcept;
734};
735
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800736template <>
737struct std::hash<phosphor::network::IfAddr>
738{
739 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
740};
741
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700742namespace fmt
743{
744template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700745struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500746{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700747template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700748struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500749{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700750template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700751struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
Patrick Williams89d734b2023-05-10 07:50:25 -0500752{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700753template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500754struct formatter<phosphor::network::InAddrAny> :
755 phosphor::network::detail::Format<phosphor::network::InAddrAny>
756{};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800757template <>
Patrick Williams89d734b2023-05-10 07:50:25 -0500758struct formatter<phosphor::network::IfAddr> :
759 phosphor::network::detail::Format<phosphor::network::IfAddr>
760{};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700761} // namespace fmt
762
763namespace std
764{
765string to_string(ether_addr value);
766string to_string(in_addr value);
767string to_string(in6_addr value);
768string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800769string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700770} // namespace std
771
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700772template <typename T>
773constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
774 bool>
775 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
776{
777 return phosphor::network::detail::veq(rhs, lhs);
778}
779
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700780auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700781{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700782 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700783}
784
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700785auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700786{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700787 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700788}
789
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700790auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700791{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700792 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700793}
794
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700795auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700796{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700797 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
798 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700799}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800800
801auto& operator<<(auto& os, phosphor::network::IfAddr v)
802{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700803 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
804 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800805}
William A. Kennington III13d665c2022-11-15 20:34:40 -0800806
807namespace phosphor::network
808{
809
810/** @brief Contains all of the object information about the interface */
811struct AllIntfInfo
812{
813 InterfaceInfo intf;
814 std::optional<in_addr> defgw4 = std::nullopt;
815 std::optional<in6_addr> defgw6 = std::nullopt;
816 std::unordered_map<IfAddr, AddressInfo> addrs = {};
817 std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
818};
819
820} // namespace phosphor::network