blob: 75db6a46cb54b00c0cdede7609a08abd4ace6974 [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
Ratan Gupta82549cc2017-04-21 08:45:23 +053019namespace phosphor
20{
21namespace network
22{
Ratan Guptae05083a2017-09-16 07:12:11 +053023
24using namespace std::chrono_literals;
Ratan Gupta16f12882017-09-22 18:26:11 +053025
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080026// wait for three seconds before reloading systemd-networkd
27constexpr auto reloadTimeout = 3s;
Ratan Gupta16f12882017-09-22 18:26:11 +053028
William A. Kennington IIId41db382021-11-09 20:42:29 -080029// refresh the objets after four seconds as network
30// configuration takes 3-4 sec to reconfigure at most.
31constexpr auto refreshTimeout = 4s;
Ratan Guptae05083a2017-09-16 07:12:11 +053032
William A. Kennington III0d7ce482019-01-30 17:14:23 -080033// Byte representations for common address types in network byte order
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070034using InAddrAny = std::variant<in_addr, in6_addr>;
William A. Kennington III0d7ce482019-01-30 17:14:23 -080035
William A. Kennington III3a70fa22018-09-20 18:48:20 -070036using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
37
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070038struct string_hash : public std::hash<std::string_view>
39{
40 using is_transparent = void;
41};
42template <typename V>
43using string_umap =
44 std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
William A. Kennington III96444792022-10-05 15:16:22 -070045using string_uset =
46 std::unordered_set<std::string, string_hash, std::equal_to<>>;
William A. Kennington IIIdd9ef812022-10-05 02:08:02 -070047
William A. Kennington III3e471c52022-10-27 19:46:07 -070048constexpr std::size_t hash_multi() noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -070049{
50 return 0;
51}
52
53template <typename T, typename... Args>
William A. Kennington IIIbecda1a2022-11-03 12:44:59 -070054constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
William A. Kennington III991a8e82022-10-11 15:02:47 -070055{
56 const std::size_t seed = hash_multi(args...);
57 return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
58}
59
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070060namespace detail
61{
62
William A. Kennington III71de63a2022-11-08 10:50:54 -080063template <typename T, uint8_t size = sizeof(T)>
64struct BswapAlign
65{
66 using type = T;
67};
68
69template <typename T>
70struct BswapAlign<T, 2>
71{
72 using type alignas(uint16_t) = T;
73};
74
75template <typename T>
76struct BswapAlign<T, 4>
77{
78 using type alignas(uint32_t) = T;
79};
80
81template <typename T>
82struct BswapAlign<T, 8>
83{
84 using type alignas(uint64_t) = T;
85};
86
87template <typename T>
88constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
89{
90 static_assert(std::is_trivially_copyable_v<T>);
91 if constexpr (sizeof(T) == 2)
92 {
93 reinterpret_cast<uint16_t&>(n) =
94 __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
95 }
96 else if constexpr (sizeof(T) == 4)
97 {
98 reinterpret_cast<uint32_t&>(n) =
99 __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
100 }
101 else if constexpr (sizeof(T) == 8)
102 {
103 reinterpret_cast<uint64_t&>(n) =
104 __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
105 }
106 else
107 {
108 auto b = reinterpret_cast<std::byte*>(&n);
109 std::reverse(b, b + sizeof(n));
110 }
111 return n;
112}
113
114} // namespace detail
115
116template <typename T>
117constexpr T bswap(T n) noexcept
118{
119 return detail::bswapInt<T>(n);
120}
121
122template <typename T>
123constexpr T hton(T n) noexcept
124{
125 if constexpr (std::endian::native == std::endian::big)
126 {
127 return n;
128 }
129 else if constexpr (std::endian::native == std::endian::little)
130 {
131 return bswap(n);
132 }
133 else
134 {
135 static_assert(std::is_same_v<T, void>);
136 }
137}
138
139template <typename T>
140constexpr T ntoh(T n) noexcept
141{
142 return hton(n);
143}
144
145namespace detail
146{
147
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700148template <typename T>
149constexpr bool vcontains() noexcept
150{
151 return false;
152}
153
154template <typename T, typename V, typename... Vs>
155constexpr bool vcontains() noexcept
156{
157 return vcontains<T, Vs...>() || std::is_same_v<T, V>;
158}
159
160template <typename T, typename... Types>
161constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
162 veq(T t, std::variant<Types...> v) noexcept
163{
164 return std::visit(
165 [t](auto v) {
166 if constexpr (std::is_same_v<T, decltype(v)>)
167 {
168 return v == t;
169 }
170 else
171 {
172 return false;
173 }
174 },
175 v);
176}
177
178template <typename T>
179struct AddrBufMaker
180{
181};
182
183template <>
184struct AddrBufMaker<ether_addr>
185{
186 public:
187 std::string_view operator()(ether_addr val) noexcept;
188
189 private:
190 std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf;
191};
192
193template <>
194struct AddrBufMaker<in_addr>
195{
196 public:
197 std::string_view operator()(in_addr val) noexcept;
198
199 private:
200 std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf;
201};
202
203template <>
204struct AddrBufMaker<in6_addr>
205{
206 public:
207 std::string_view operator()(in6_addr val) noexcept;
208
209 private:
210 std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf;
211};
212
213template <typename BufMaker>
214struct FormatFromBuf
215{
216 private:
217 fmt::formatter<std::string_view> formatter;
218
219 public:
220 template <typename ParseContext>
221 constexpr auto parse(ParseContext& ctx)
222 {
223 return ctx.begin();
224 }
225
226 template <typename FormatContext>
227 auto format(auto v, FormatContext& ctx) const
228 {
229 return formatter.format(BufMaker{}(v), ctx);
230 }
231};
232} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500233} // namespace network
234} // namespace phosphor
William A. Kennington III3e471c52022-10-27 19:46:07 -0700235
236template <typename... Ts>
237struct std::hash<std::tuple<Ts...>>
238{
239 constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
240 {
241 return std::apply(phosphor::network::hash_multi<Ts...>, t);
242 }
243};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700244
William A. Kennington III653114f2022-11-01 22:34:04 -0700245template <>
246struct std::hash<in_addr>
247{
248 std::size_t operator()(in_addr addr) const noexcept;
249};
250
251template <>
252struct std::hash<in6_addr>
253{
254 std::size_t operator()(in6_addr addr) const noexcept;
255};
256
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700257namespace fmt
258{
259template <>
260struct formatter<ether_addr>
261 : phosphor::network::detail::FormatFromBuf<
262 phosphor::network::detail::AddrBufMaker<ether_addr>>
263{
264};
265template <>
266struct formatter<in_addr>
267 : phosphor::network::detail::FormatFromBuf<
268 phosphor::network::detail::AddrBufMaker<in_addr>>
269{
270};
271template <>
272struct formatter<in6_addr>
273 : phosphor::network::detail::FormatFromBuf<
274 phosphor::network::detail::AddrBufMaker<in6_addr>>
275{
276};
277template <>
278struct formatter<phosphor::network::InAddrAny>
279{
280 private:
281 fmt::formatter<std::string_view> formatter;
282
283 public:
284 template <typename ParseContext>
285 constexpr auto parse(ParseContext& ctx)
286 {
287 return ctx.begin();
288 }
289
290 template <typename FormatContext>
291 auto format(auto v, FormatContext& ctx) const
292 {
293 return std::visit(
294 [&](auto v) {
295 auto abm =
296 phosphor::network::detail::AddrBufMaker<decltype(v)>{};
297 return formatter.format(abm(v), ctx);
298 },
299 v);
300 }
301};
302} // namespace fmt
303
304namespace std
305{
306string to_string(ether_addr value);
307string to_string(in_addr value);
308string to_string(in6_addr value);
309string to_string(phosphor::network::InAddrAny value);
310} // namespace std
311
312constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
313{
314 return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
315 rhs.ether_addr_octet);
316}
317
318constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
319{
320 return lhs.s_addr == rhs.s_addr;
321}
322
323constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
324{
325 return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
326}
327
328template <typename T>
329constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
330 bool>
331 operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
332{
333 return phosphor::network::detail::veq(rhs, lhs);
334}
335
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700336auto& operator<<(auto& os, ether_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700337{
338 return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v);
339}
340
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700341auto& operator<<(auto& os, in_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700342{
343 return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v);
344}
345
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700346auto& operator<<(auto& os, in6_addr v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700347{
348 return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v);
349}
350
William A. Kennington III86eb8b72022-11-01 22:35:04 -0700351auto& operator<<(auto& os, phosphor::network::InAddrAny v)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700352{
353 return os << std::visit(
354 [](auto v) {
355 return phosphor::network::detail::AddrBufMaker<
356 decltype(v)>{}(v);
357 },
358 v);
359}