blob: f426f8155dfb87ef392f10a13ee6101b94115f82 [file] [log] [blame]
Ratan Gupta82549cc2017-04-21 08:45:23 +05301#pragma once
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07002#include <fmt/core.h>
3#include <net/ethernet.h>
William A. Kennington III0d7ce482019-01-30 17:14:23 -08004#include <netinet/in.h>
Ratan Gupta3681a502017-06-17 19:20:04 +05305
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07006#include <algorithm>
7#include <array>
Patrick Venture189d44e2018-07-09 12:30:59 -07008#include <chrono>
William A. Kennington III71de63a2022-11-08 10:50:54 -08009#include <numeric>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070010#include <sdeventplus/clock.hpp>
11#include <sdeventplus/utility/timer.hpp>
Patrick Venture189d44e2018-07-09 12:30:59 -070012#include <string>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070013#include <string_view>
14#include <type_traits>
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070015#include <unordered_map>
Willy Tuf7dce2e2022-10-07 05:48:08 +000016#include <unordered_set>
William A. Kennington III0d7ce482019-01-30 17:14:23 -080017#include <variant>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053018
William A. Kennington III454a0de2022-11-12 01:01:04 -080019constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
20{
21 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
22 rhs.ether_addr_octet);
23}
24
25constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
26{
27 return lhs.s_addr == rhs.s_addr;
28}
29
30constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
31{
32 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
33}
34
Ratan Gupta82549cc2017-04-21 08:45:23 +053035namespace phosphor
36{
37namespace network
38{
Ratan Guptae05083a2017-09-16 07:12:11 +053039
40using namespace std::chrono_literals;
Ratan Gupta16f12882017-09-22 18:26:11 +053041
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080042// wait for three seconds before reloading systemd-networkd
43constexpr auto reloadTimeout = 3s;
Ratan Gupta16f12882017-09-22 18:26:11 +053044
William A. Kennington III0d7ce482019-01-30 17:14:23 -080045// Byte representations for common address types in network byte order
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070046using InAddrAny = std::variant<in_addr, in6_addr>;
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -080047class IfAddr
48{
49 private:
50 InAddrAny addr;
51 uint8_t pfx;
52
53 static void invalidPfx(uint8_t pfx);
54
55 public:
56 constexpr IfAddr() : addr({}), pfx(0)
57 {
58 }
59
60 constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx)
61 {
62 std::visit(
63 [pfx](auto v) {
64 if (sizeof(v) * 8 < pfx)
65 {
66 invalidPfx(pfx);
67 }
68 },
69 addr);
70 }
71
72 constexpr auto getAddr() const
73 {
74 return addr;
75 }
76
77 constexpr auto getPfx() const
78 {
79 return pfx;
80 }
81
82 constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept
83 {
84 return addr == rhs.addr && pfx == rhs.pfx;
85 }
86};
William A. Kennington III0d7ce482019-01-30 17:14:23 -080087
William A. Kennington III3a70fa22018-09-20 18:48:20 -070088using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
89
William A. Kennington III454a0de2022-11-12 01:01:04 -080090/** @class InterfaceInfo
91 * @brief Information about interfaces from the kernel
92 */
93struct InterfaceInfo
94{
95 unsigned idx;
96 unsigned flags;
97 std::optional<std::string> name = std::nullopt;
98 std::optional<ether_addr> mac = std::nullopt;
99 std::optional<unsigned> mtu = std::nullopt;
100 std::optional<unsigned> parent_idx = std::nullopt;
101 std::optional<std::string> kind = std::nullopt;
102 std::optional<uint16_t> vlan_id = std::nullopt;
103
104 constexpr bool operator==(const InterfaceInfo& rhs) const noexcept
105 {
106 return idx == rhs.idx && flags == rhs.flags && name == rhs.name &&
107 mac == rhs.mac && mtu == rhs.mtu &&
108 parent_idx == rhs.parent_idx && kind == rhs.kind &&
109 vlan_id == rhs.vlan_id;
110 }
111};
112
William A. Kennington III6a923632022-11-06 18:17:33 -0800113/** @class AddressInfo
114 * @brief Information about a addresses from the kernel
115 */
116struct AddressInfo
117{
118 unsigned ifidx;
119 IfAddr ifaddr;
120 uint8_t scope;
121 uint32_t flags;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800122
123 constexpr bool operator==(const AddressInfo& rhs) const noexcept
124 {
125 return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr &&
126 scope == rhs.scope && flags == rhs.flags;
127 }
William A. Kennington III6a923632022-11-06 18:17:33 -0800128};
129
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800130/** @class NeighborInfo
131 * @brief Information about a neighbor from the kernel
132 */
133struct NeighborInfo
134{
135 unsigned ifidx;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800136 uint16_t state;
William A. Kennington IIId3615142022-11-12 01:28:33 -0800137 std::optional<InAddrAny> addr;
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800138 std::optional<ether_addr> mac;
William A. Kennington III454a0de2022-11-12 01:01:04 -0800139
140 constexpr bool operator==(const NeighborInfo& rhs) const noexcept
141 {
142 return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr &&
143 mac == rhs.mac;
144 }
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800145};
146
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700147struct string_hash : public std::hash<std::string_view>
148{
149 using is_transparent = void;
150};
151template <typename V>
152using string_umap =
153 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -0700154using string_uset =
155 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -0700156
William A. Kennington III3e471c52022-10-27 19:46:07 -0700157constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700158{
159 return 0;
160}
161
162template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -0700163constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -0700164{
165 const std::size_t seed = hash_multi(args...);
166 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
167}
168
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700169namespace detail
170{
171
William A. Kennington III71de63a2022-11-08 10:50:54 -0800172template <typename T, uint8_t size = sizeof(T)>
173struct BswapAlign
174{
175 using type = T;
176};
177
178template <typename T>
179struct BswapAlign<T, 2>
180{
181 using type alignas(uint16_t) = T;
182};
183
184template <typename T>
185struct BswapAlign<T, 4>
186{
187 using type alignas(uint32_t) = T;
188};
189
190template <typename T>
191struct BswapAlign<T, 8>
192{
193 using type alignas(uint64_t) = T;
194};
195
196template <typename T>
197constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
198{
199 static_assert(std::is_trivially_copyable_v<T>);
200 if constexpr (sizeof(T) == 2)
201 {
202 reinterpret_cast<uint16_t&>(n) =
203 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
204 }
205 else if constexpr (sizeof(T) == 4)
206 {
207 reinterpret_cast<uint32_t&>(n) =
208 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
209 }
210 else if constexpr (sizeof(T) == 8)
211 {
212 reinterpret_cast<uint64_t&>(n) =
213 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
214 }
215 else
216 {
217 auto b = reinterpret_cast<std::byte*>(&n);
218 std::reverse(b, b + sizeof(n));
219 }
220 return n;
221}
222
223} // namespace detail
224
225template <typename T>
226constexpr T bswap(T n) noexcept
227{
228 return detail::bswapInt<T>(n);
229}
230
231template <typename T>
232constexpr T hton(T n) noexcept
233{
234 if constexpr (std::endian::native == std::endian::big)
235 {
236 return n;
237 }
238 else if constexpr (std::endian::native == std::endian::little)
239 {
240 return bswap(n);
241 }
242 else
243 {
244 static_assert(std::is_same_v<T, void>);
245 }
246}
247
248template <typename T>
249constexpr T ntoh(T n) noexcept
250{
251 return hton(n);
252}
253
254namespace detail
255{
William A. Kennington III238ef992022-11-03 12:47:49 -0700256inline constexpr auto charLookup = []() {
257 std::array<int8_t, 256> ret;
258 std::fill(ret.begin(), ret.end(), -1);
259 for (int8_t i = 0; i < 10; ++i)
260 {
261 ret[i + '0'] = i;
262 }
263 for (int8_t i = 0; i < 26; ++i)
264 {
265 ret[i + 'A'] = i + 10;
266 ret[i + 'a'] = i + 10;
267 }
268 return ret;
269}();
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700270inline constexpr auto intLookup = []() {
271 std::array<char, 36> ret;
272 for (int8_t i = 0; i < 10; ++i)
273 {
274 ret[i] = i + '0';
275 }
276 for (int8_t i = 0; i < 26; ++i)
277 {
278 ret[i + 10] = i + 'a';
279 }
280 return ret;
281}();
282} // namespace detail
William A. Kennington III238ef992022-11-03 12:47:49 -0700283
284template <typename T, uint8_t base>
285struct DecodeInt
286{
287 static_assert(base > 1 && base <= 36);
288 static_assert(std::is_unsigned_v<T>);
289
290 constexpr T operator()(std::string_view str) const
291 {
292 if (str.empty())
293 {
294 throw std::invalid_argument("Empty Str");
295 }
296 constexpr auto max = std::numeric_limits<T>::max();
297 auto ret =
298 std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) {
299 auto v = detail::charLookup[c];
300 if (v < 0 || v >= base)
301 {
302 throw std::invalid_argument("Invalid numeral");
303 }
304 if constexpr (std::popcount(base) == 1)
305 {
306 constexpr auto shift = std::countr_zero(base);
307 constexpr auto maxshift = max >> shift;
308 if (r > maxshift)
309 {
310 throw std::overflow_error("Integer Decode");
311 }
312 return (r << shift) | v;
313 }
314 else
315 {
316 constexpr auto maxbase = max / base;
317 if (r > maxbase)
318 {
319 throw std::overflow_error("Integer Decode");
320 }
321 r *= base;
322 if (max - v < r)
323 {
324 throw std::overflow_error("Integer Decode");
325 }
326 return r + v;
327 }
328 });
329 return ret;
330 }
331};
332
William A. Kennington IIIdd7c7b32022-11-04 15:19:36 -0700333template <typename T, uint8_t base>
334struct EncodeInt
335{
336 static_assert(base > 1 && base <= 36);
337 static_assert(std::is_unsigned_v<T>);
338
339 static constexpr uint8_t buf_size = []() {
340 T v = std::numeric_limits<T>::max();
341 uint8_t i = 0;
342 for (; v != 0; ++i)
343 {
344 v /= base;
345 }
346 return i;
347 }();
348 using buf_type = std::array<char, buf_size>;
349
350 constexpr uint8_t reverseFill(char* buf, T v) const noexcept
351 {
352 uint8_t i = 0;
353 do
354 {
355 if constexpr (std::popcount(base) == 1)
356 {
357 buf[i++] = detail::intLookup[v & 0xf];
358 v >>= 4;
359 }
360 else
361 {
362 buf[i++] = detail::intLookup[v % base];
363 v /= base;
364 }
365 } while (v > 0);
366 return i;
367 }
368
369 constexpr char* operator()(char* buf, T v) const noexcept
370 {
371 uint8_t i = reverseFill(buf, v);
372 std::reverse(buf, buf + i);
373 return buf + i;
374 }
375
376 constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
377 {
378 uint8_t i = reverseFill(buf, v);
379 auto end = buf + std::max(i, min_width);
380 std::fill(buf + i, end, '0');
381 std::reverse(buf, end);
382 return end;
383 }
384};
385
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700386template <typename T>
387struct ToAddr
388{
389};
390
391template <>
392struct ToAddr<ether_addr>
393{
394 constexpr ether_addr operator()(std::string_view str) const
395 {
396 constexpr DecodeInt<uint8_t, 16> di;
397 ether_addr ret;
398 if (str.size() == 12 && str.find(":") == str.npos)
399 {
400 for (size_t i = 0; i < 6; ++i)
401 {
402 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
403 }
404 }
405 else
406 {
407 for (size_t i = 0; i < 5; ++i)
408 {
409 auto loc = str.find(":");
410 ret.ether_addr_octet[i] = di(str.substr(0, loc));
411 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
412 if (str.empty())
413 {
414 throw std::invalid_argument("Missing mac data");
415 }
416 }
417 ret.ether_addr_octet[5] = di(str);
418 }
419 return ret;
420 }
421};
422
William A. Kennington IIIdf1178e2022-11-03 12:56:33 -0700423template <>
424struct ToAddr<in_addr>
425{
426 constexpr in_addr operator()(std::string_view str) const
427 {
428 constexpr DecodeInt<uint8_t, 10> di;
429 uint32_t addr = {};
430 for (size_t i = 0; i < 3; ++i)
431 {
432 auto loc = str.find(".");
433 addr |= di(str.substr(0, loc));
434 addr <<= 8;
435 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
436 if (str.empty())
437 {
438 throw std::invalid_argument("Missing addr data");
439 }
440 }
441 addr |= di(str);
442 return {hton(addr)};
443 }
444};
445
William A. Kennington IIIec496a82022-11-04 02:17:20 -0700446template <>
447struct ToAddr<in6_addr>
448{
449 constexpr in6_addr operator()(std::string_view str) const
450 {
451 constexpr DecodeInt<uint16_t, 16> di;
452 in6_addr ret = {};
453 size_t i = 0;
454 while (i < 8)
455 {
456 auto loc = str.find(':');
457 if (i == 6 && loc == str.npos)
458 {
459 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
460 return ret;
461 }
462 if (loc != 0 && !str.empty())
463 {
464 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
465 }
466 if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
467 {
468 str.remove_prefix(loc + 2);
469 break;
470 }
471 else if (str.empty())
472 {
473 throw std::invalid_argument("IPv6 Data");
474 }
475 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
476 }
477 if (str.starts_with(':'))
478 {
479 throw std::invalid_argument("Extra separator");
480 }
481 size_t j = 7;
482 if (!str.empty() && i < 6 && str.find('.') != str.npos)
483 {
484 auto loc = str.rfind(':');
485 ret.s6_addr32[3] =
486 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
487 .s_addr;
488 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
489 j -= 2;
490 }
491 while (!str.empty() && j > i)
492 {
493 auto loc = str.rfind(':');
494 ret.s6_addr16[j--] =
495 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
496 str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
497 }
498 if (!str.empty())
499 {
500 throw std::invalid_argument("Too much data");
501 }
502 return ret;
503 }
504};
505
William A. Kennington IIIead71982022-11-04 02:18:10 -0700506template <>
507struct ToAddr<InAddrAny>
508{
509 constexpr InAddrAny operator()(std::string_view str) const
510 {
511 if (str.find(':') == str.npos)
512 {
513 return ToAddr<in_addr>{}(str);
514 }
515 return ToAddr<in6_addr>{}(str);
516 }
517};
518
519template <>
520struct ToAddr<IfAddr>
521{
522 constexpr IfAddr operator()(std::string_view str) const
523 {
524 auto pos = str.rfind('/');
525 if (pos == str.npos)
526 {
527 throw std::invalid_argument("Invalid IfAddr");
528 }
529 return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
530 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
531 }
532};
533
William A. Kennington III55bdc362022-11-04 17:57:21 -0700534template <typename T>
535struct ToStr
536{
537};
538
539template <>
540struct ToStr<char>
541{
542 static constexpr uint8_t buf_size = 1;
543 using buf_type = std::array<char, buf_size>;
544
545 constexpr char* operator()(char* buf, char v) const noexcept
546 {
547 buf[0] = v;
548 return buf + 1;
549 }
550};
551
552template <>
553struct ToStr<ether_addr>
554{
555 // 6 octets * 2 hex chars + 5 separators
556 static constexpr uint8_t buf_size = 17;
557 using buf_type = std::array<char, buf_size>;
558
559 constexpr char* operator()(char* buf, ether_addr v) const noexcept
560 {
561 for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
562 {
563 *ptr = ':';
564 }
565 for (size_t i = 0; i < 6; ++i)
566 {
567 char* tmp = buf + i * 3;
568 uint8_t byte = v.ether_addr_octet[i];
569 EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
570 }
571 return buf + buf_size;
572 }
573};
574
575template <>
576struct ToStr<in_addr>
577{
578 // 4 octets * 3 dec chars + 3 separators
579 static constexpr uint8_t buf_size = 15;
580 using buf_type = std::array<char, buf_size>;
581
582 constexpr char* operator()(char* buf, in_addr v) const noexcept
583 {
584 auto n = bswap(ntoh(v.s_addr));
585 for (size_t i = 0; i < 3; ++i)
586 {
587 buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
588 n >>= 8;
589 }
590 return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
591 }
592};
593
594template <>
595struct ToStr<in6_addr>
596{
597 // 8 hextets * 4 hex chars + 7 separators
598 static constexpr uint8_t buf_size = 39;
599 using buf_type = std::array<char, buf_size>;
600
601 constexpr char* operator()(char* buf, in6_addr v) const noexcept
602 {
603 // IPv4 in IPv6 Addr
604 if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
605 v.s6_addr32[2] == hton(uint32_t(0xffff)))
606 {
607 constexpr auto prefix = std::string_view("::ffff:");
608 return ToStr<in_addr>{}(
609 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
610 }
611
612 size_t skip_start = 0;
613 size_t skip_size = 0;
614 {
615 size_t new_start = 0;
616 size_t new_size = 0;
617 for (size_t i = 0; i < 9; ++i)
618 {
619 if (i < 8 && v.s6_addr16[i] == 0)
620 {
621 if (new_start + new_size == i)
622 {
623 new_size++;
624 }
625 else
626 {
627 new_start = i;
628 new_size = 1;
629 }
630 }
631 else if (new_start + new_size == i && new_size > skip_size)
632 {
633 skip_start = new_start;
634 skip_size = new_size;
635 }
636 }
637 }
638 for (size_t i = 0; i < 8; ++i)
639 {
640 if (i == skip_start && skip_size > 1)
641 {
642 if (i == 0)
643 {
644 *(buf++) = ':';
645 }
646 *(buf++) = ':';
647 i += skip_size - 1;
648 continue;
649 }
650 buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
651 if (i < 7)
652 {
653 *(buf++) = ':';
654 }
655 }
656 return buf;
657 }
658};
659
660template <>
661struct ToStr<InAddrAny>
662{
663 // IPv6 is the bigger of the addrs
664 static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
665 using buf_type = std::array<char, buf_size>;
666
667 constexpr char* operator()(char* buf, InAddrAny v) const noexcept
668 {
669 return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
670 v);
671 }
672};
673
674template <>
675struct ToStr<IfAddr>
676{
677 // InAddrAny + sep + 3 prefix chars
678 static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
679 using buf_type = std::array<char, buf_size>;
680
681 constexpr char* operator()(char* buf, IfAddr v) const noexcept
682 {
683 buf = ToStr<InAddrAny>{}(buf, v.getAddr());
684 buf = ToStr<char>{}(buf, '/');
685 return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
686 }
687};
688
William A. Kennington III238ef992022-11-03 12:47:49 -0700689namespace detail
690{
William A. Kennington III71de63a2022-11-08 10:50:54 -0800691
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700692template <typename T>
693constexpr bool vcontains() noexcept
694{
695 return false;
696}
697
698template <typename T, typename V, typename... Vs>
699constexpr bool vcontains() noexcept
700{
701 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
702}
703
704template <typename T, typename... Types>
705constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
706 veq(T t, std::variant<Types...> v) noexcept
707{
708 return std::visit(
709 [t](auto v) {
710 if constexpr (std::is_same_v<T, decltype(v)>)
711 {
712 return v == t;
713 }
714 else
715 {
716 return false;
717 }
718 },
719 v);
720}
721
722template <typename T>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700723struct ToStrBuf
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700724{
725 public:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700726 constexpr std::string_view operator()(T v) noexcept
727 {
728 return {buf.data(), ToStr<T>{}(buf.data(), v)};
729 }
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700730
731 private:
William A. Kennington III55bdc362022-11-04 17:57:21 -0700732 typename ToStr<T>::buf_type buf;
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700733};
734
William A. Kennington III55bdc362022-11-04 17:57:21 -0700735template <typename T>
736struct Format
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700737{
738 private:
739 fmt::formatter<std::string_view> formatter;
740
741 public:
742 template <typename ParseContext>
743 constexpr auto parse(ParseContext& ctx)
744 {
745 return ctx.begin();
746 }
747
748 template <typename FormatContext>
749 auto format(auto v, FormatContext& ctx) const
750 {
William A. Kennington III55bdc362022-11-04 17:57:21 -0700751 return formatter.format(ToStrBuf<T>{}(v), ctx);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700752 }
753};
754} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500755} // namespace network
756} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700757
758template <typename... Ts>
759struct std::hash<std::tuple<Ts...>>
760{
761 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
762 {
763 return std::apply(phosphor::network::hash_multi<Ts...>, t);
764 }
765};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700766
William A. Kennington III653114f2022-11-01 22:34:04 -0700767template <>
768struct std::hash<in_addr>
769{
770 std::size_t operator()(in_addr addr) const noexcept;
771};
772
773template <>
774struct std::hash<in6_addr>
775{
776 std::size_t operator()(in6_addr addr) const noexcept;
777};
778
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800779template <>
780struct std::hash<phosphor::network::IfAddr>
781{
782 std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
783};
784
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700785namespace fmt
786{
787template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700788struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700789{
790};
791template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700792struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700793{
794};
795template <>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700796struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700797{
798};
799template <>
800struct formatter<phosphor::network::InAddrAny>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700801 : phosphor::network::detail::Format<phosphor::network::InAddrAny>
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700802{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700803};
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800804template <>
805struct formatter<phosphor::network::IfAddr>
William A. Kennington III55bdc362022-11-04 17:57:21 -0700806 : phosphor::network::detail::Format<phosphor::network::IfAddr>
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800807{
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800808};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700809} // namespace fmt
810
811namespace std
812{
813string to_string(ether_addr value);
814string to_string(in_addr value);
815string to_string(in6_addr value);
816string to_string(phosphor::network::InAddrAny value);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800817string to_string(phosphor::network::IfAddr value);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700818} // namespace std
819
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700820template <typename T>
821constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
822 bool>
823 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
824{
825 return phosphor::network::detail::veq(rhs, lhs);
826}
827
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700828auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700829{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700830 return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700831}
832
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700833auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700834{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700835 return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700836}
837
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700838auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700839{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700840 return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700841}
842
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700843auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700844{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700845 phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
846 return os << tsb(v);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700847}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800848
849auto& operator<<(auto& os, phosphor::network::IfAddr v)
850{
William A. Kennington III55bdc362022-11-04 17:57:21 -0700851 phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
852 return os << tsb(v);
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800853}
William A. Kennington III13d665c2022-11-15 20:34:40 -0800854
855namespace phosphor::network
856{
857
858/** @brief Contains all of the object information about the interface */
859struct AllIntfInfo
860{
861 InterfaceInfo intf;
862 std::optional<in_addr> defgw4 = std::nullopt;
863 std::optional<in6_addr> defgw6 = std::nullopt;
864 std::unordered_map<IfAddr, AddressInfo> addrs = {};
865 std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
866};
867
868} // namespace phosphor::network