11bbe3d1eSWilliam A. Kennington III #pragma once 2bb0eaccbSWilliam A. Kennington III #include <fmt/core.h> 3bb0eaccbSWilliam A. Kennington III #include <net/ethernet.h> 41bbe3d1eSWilliam A. Kennington III #include <netinet/in.h> 51bbe3d1eSWilliam A. Kennington III 6bb0eaccbSWilliam A. Kennington III #include <algorithm> 7bb0eaccbSWilliam A. Kennington III #include <array> 81bbe3d1eSWilliam A. Kennington III #include <chrono> 91bbe3d1eSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 101bbe3d1eSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 111bbe3d1eSWilliam A. Kennington III #include <string> 12bb0eaccbSWilliam A. Kennington III #include <string_view> 13bb0eaccbSWilliam A. Kennington III #include <type_traits> 14dd9ef815SWilliam A. Kennington III #include <unordered_map> 15f7dce2e8SWilly Tu #include <unordered_set> 161bbe3d1eSWilliam A. Kennington III #include <variant> 171bbe3d1eSWilliam A. Kennington III 181bbe3d1eSWilliam A. Kennington III namespace phosphor 191bbe3d1eSWilliam A. Kennington III { 201bbe3d1eSWilliam A. Kennington III namespace network 211bbe3d1eSWilliam A. Kennington III { 221bbe3d1eSWilliam A. Kennington III 231bbe3d1eSWilliam A. Kennington III using namespace std::chrono_literals; 241bbe3d1eSWilliam A. Kennington III 25c7cf25f7SWilliam A. Kennington III // wait for three seconds before reloading systemd-networkd 26c7cf25f7SWilliam A. Kennington III constexpr auto reloadTimeout = 3s; 271bbe3d1eSWilliam A. Kennington III 28d41db383SWilliam A. Kennington III // refresh the objets after four seconds as network 29d41db383SWilliam A. Kennington III // configuration takes 3-4 sec to reconfigure at most. 30d41db383SWilliam A. Kennington III constexpr auto refreshTimeout = 4s; 311bbe3d1eSWilliam A. Kennington III 321bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order 33bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>; 341bbe3d1eSWilliam A. Kennington III 351bbe3d1eSWilliam A. Kennington III using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>; 361bbe3d1eSWilliam A. Kennington III 37dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 38dd9ef815SWilliam A. Kennington III { 39dd9ef815SWilliam A. Kennington III using is_transparent = void; 40dd9ef815SWilliam A. Kennington III }; 41dd9ef815SWilliam A. Kennington III template <typename V> 42dd9ef815SWilliam A. Kennington III using string_umap = 43dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 4496444795SWilliam A. Kennington III using string_uset = 4596444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 46dd9ef815SWilliam A. Kennington III 473e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 48991a8e81SWilliam A. Kennington III { 49991a8e81SWilliam A. Kennington III return 0; 50991a8e81SWilliam A. Kennington III } 51991a8e81SWilliam A. Kennington III 52991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 533e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, Args... args) noexcept 54991a8e81SWilliam A. Kennington III { 55991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 56991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 57991a8e81SWilliam A. Kennington III } 58991a8e81SWilliam A. Kennington III 59bb0eaccbSWilliam A. Kennington III namespace detail 60bb0eaccbSWilliam A. Kennington III { 61bb0eaccbSWilliam A. Kennington III 62bb0eaccbSWilliam A. Kennington III template <typename T> 63bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 64bb0eaccbSWilliam A. Kennington III { 65bb0eaccbSWilliam A. Kennington III return false; 66bb0eaccbSWilliam A. Kennington III } 67bb0eaccbSWilliam A. Kennington III 68bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 69bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 70bb0eaccbSWilliam A. Kennington III { 71bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 72bb0eaccbSWilliam A. Kennington III } 73bb0eaccbSWilliam A. Kennington III 74bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 75bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 76bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 77bb0eaccbSWilliam A. Kennington III { 78bb0eaccbSWilliam A. Kennington III return std::visit( 79bb0eaccbSWilliam A. Kennington III [t](auto v) { 80bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 81bb0eaccbSWilliam A. Kennington III { 82bb0eaccbSWilliam A. Kennington III return v == t; 83bb0eaccbSWilliam A. Kennington III } 84bb0eaccbSWilliam A. Kennington III else 85bb0eaccbSWilliam A. Kennington III { 86bb0eaccbSWilliam A. Kennington III return false; 87bb0eaccbSWilliam A. Kennington III } 88bb0eaccbSWilliam A. Kennington III }, 89bb0eaccbSWilliam A. Kennington III v); 90bb0eaccbSWilliam A. Kennington III } 91bb0eaccbSWilliam A. Kennington III 92bb0eaccbSWilliam A. Kennington III template <typename T> 93bb0eaccbSWilliam A. Kennington III struct AddrBufMaker 94bb0eaccbSWilliam A. Kennington III { 95bb0eaccbSWilliam A. Kennington III }; 96bb0eaccbSWilliam A. Kennington III 97bb0eaccbSWilliam A. Kennington III template <> 98bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<ether_addr> 99bb0eaccbSWilliam A. Kennington III { 100bb0eaccbSWilliam A. Kennington III public: 101bb0eaccbSWilliam A. Kennington III std::string_view operator()(ether_addr val) noexcept; 102bb0eaccbSWilliam A. Kennington III 103bb0eaccbSWilliam A. Kennington III private: 104bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf; 105bb0eaccbSWilliam A. Kennington III }; 106bb0eaccbSWilliam A. Kennington III 107bb0eaccbSWilliam A. Kennington III template <> 108bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in_addr> 109bb0eaccbSWilliam A. Kennington III { 110bb0eaccbSWilliam A. Kennington III public: 111bb0eaccbSWilliam A. Kennington III std::string_view operator()(in_addr val) noexcept; 112bb0eaccbSWilliam A. Kennington III 113bb0eaccbSWilliam A. Kennington III private: 114bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf; 115bb0eaccbSWilliam A. Kennington III }; 116bb0eaccbSWilliam A. Kennington III 117bb0eaccbSWilliam A. Kennington III template <> 118bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in6_addr> 119bb0eaccbSWilliam A. Kennington III { 120bb0eaccbSWilliam A. Kennington III public: 121bb0eaccbSWilliam A. Kennington III std::string_view operator()(in6_addr val) noexcept; 122bb0eaccbSWilliam A. Kennington III 123bb0eaccbSWilliam A. Kennington III private: 124bb0eaccbSWilliam A. Kennington III std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf; 125bb0eaccbSWilliam A. Kennington III }; 126bb0eaccbSWilliam A. Kennington III 127bb0eaccbSWilliam A. Kennington III template <typename BufMaker> 128bb0eaccbSWilliam A. Kennington III struct FormatFromBuf 129bb0eaccbSWilliam A. Kennington III { 130bb0eaccbSWilliam A. Kennington III private: 131bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 132bb0eaccbSWilliam A. Kennington III 133bb0eaccbSWilliam A. Kennington III public: 134bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 135bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 136bb0eaccbSWilliam A. Kennington III { 137bb0eaccbSWilliam A. Kennington III return ctx.begin(); 138bb0eaccbSWilliam A. Kennington III } 139bb0eaccbSWilliam A. Kennington III 140bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 141bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 142bb0eaccbSWilliam A. Kennington III { 143bb0eaccbSWilliam A. Kennington III return formatter.format(BufMaker{}(v), ctx); 144bb0eaccbSWilliam A. Kennington III } 145bb0eaccbSWilliam A. Kennington III }; 146bb0eaccbSWilliam A. Kennington III } // namespace detail 1471bbe3d1eSWilliam A. Kennington III } // namespace network 1481bbe3d1eSWilliam A. Kennington III } // namespace phosphor 1493e471c5fSWilliam A. Kennington III 1503e471c5fSWilliam A. Kennington III template <typename... Ts> 1513e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 1523e471c5fSWilliam A. Kennington III { 1533e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 1543e471c5fSWilliam A. Kennington III { 1553e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 1563e471c5fSWilliam A. Kennington III } 1573e471c5fSWilliam A. Kennington III }; 158bb0eaccbSWilliam A. Kennington III 159653114fcSWilliam A. Kennington III template <> 160653114fcSWilliam A. Kennington III struct std::hash<in_addr> 161653114fcSWilliam A. Kennington III { 162653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 163653114fcSWilliam A. Kennington III }; 164653114fcSWilliam A. Kennington III 165653114fcSWilliam A. Kennington III template <> 166653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 167653114fcSWilliam A. Kennington III { 168653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 169653114fcSWilliam A. Kennington III }; 170653114fcSWilliam A. Kennington III 171bb0eaccbSWilliam A. Kennington III namespace fmt 172bb0eaccbSWilliam A. Kennington III { 173bb0eaccbSWilliam A. Kennington III template <> 174bb0eaccbSWilliam A. Kennington III struct formatter<ether_addr> 175bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 176bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<ether_addr>> 177bb0eaccbSWilliam A. Kennington III { 178bb0eaccbSWilliam A. Kennington III }; 179bb0eaccbSWilliam A. Kennington III template <> 180bb0eaccbSWilliam A. Kennington III struct formatter<in_addr> 181bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 182bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in_addr>> 183bb0eaccbSWilliam A. Kennington III { 184bb0eaccbSWilliam A. Kennington III }; 185bb0eaccbSWilliam A. Kennington III template <> 186bb0eaccbSWilliam A. Kennington III struct formatter<in6_addr> 187bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 188bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in6_addr>> 189bb0eaccbSWilliam A. Kennington III { 190bb0eaccbSWilliam A. Kennington III }; 191bb0eaccbSWilliam A. Kennington III template <> 192bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny> 193bb0eaccbSWilliam A. Kennington III { 194bb0eaccbSWilliam A. Kennington III private: 195bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 196bb0eaccbSWilliam A. Kennington III 197bb0eaccbSWilliam A. Kennington III public: 198bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 199bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 200bb0eaccbSWilliam A. Kennington III { 201bb0eaccbSWilliam A. Kennington III return ctx.begin(); 202bb0eaccbSWilliam A. Kennington III } 203bb0eaccbSWilliam A. Kennington III 204bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 205bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 206bb0eaccbSWilliam A. Kennington III { 207bb0eaccbSWilliam A. Kennington III return std::visit( 208bb0eaccbSWilliam A. Kennington III [&](auto v) { 209bb0eaccbSWilliam A. Kennington III auto abm = 210bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<decltype(v)>{}; 211bb0eaccbSWilliam A. Kennington III return formatter.format(abm(v), ctx); 212bb0eaccbSWilliam A. Kennington III }, 213bb0eaccbSWilliam A. Kennington III v); 214bb0eaccbSWilliam A. Kennington III } 215bb0eaccbSWilliam A. Kennington III }; 216bb0eaccbSWilliam A. Kennington III } // namespace fmt 217bb0eaccbSWilliam A. Kennington III 218bb0eaccbSWilliam A. Kennington III namespace std 219bb0eaccbSWilliam A. Kennington III { 220bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 221bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 222bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 223bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 224bb0eaccbSWilliam A. Kennington III } // namespace std 225bb0eaccbSWilliam A. Kennington III 226bb0eaccbSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 227bb0eaccbSWilliam A. Kennington III { 228bb0eaccbSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 229bb0eaccbSWilliam A. Kennington III rhs.ether_addr_octet); 230bb0eaccbSWilliam A. Kennington III } 231bb0eaccbSWilliam A. Kennington III 232bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 233bb0eaccbSWilliam A. Kennington III { 234bb0eaccbSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 235bb0eaccbSWilliam A. Kennington III } 236bb0eaccbSWilliam A. Kennington III 237bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 238bb0eaccbSWilliam A. Kennington III { 239bb0eaccbSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 240bb0eaccbSWilliam A. Kennington III } 241bb0eaccbSWilliam A. Kennington III 242bb0eaccbSWilliam A. Kennington III template <typename T> 243bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 244bb0eaccbSWilliam A. Kennington III bool> 245bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 246bb0eaccbSWilliam A. Kennington III { 247bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 248bb0eaccbSWilliam A. Kennington III } 249bb0eaccbSWilliam A. Kennington III 250*86eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 251bb0eaccbSWilliam A. Kennington III { 252bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v); 253bb0eaccbSWilliam A. Kennington III } 254bb0eaccbSWilliam A. Kennington III 255*86eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 256bb0eaccbSWilliam A. Kennington III { 257bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v); 258bb0eaccbSWilliam A. Kennington III } 259bb0eaccbSWilliam A. Kennington III 260*86eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 261bb0eaccbSWilliam A. Kennington III { 262bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v); 263bb0eaccbSWilliam A. Kennington III } 264bb0eaccbSWilliam A. Kennington III 265*86eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 266bb0eaccbSWilliam A. Kennington III { 267bb0eaccbSWilliam A. Kennington III return os << std::visit( 268bb0eaccbSWilliam A. Kennington III [](auto v) { 269bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::AddrBufMaker< 270bb0eaccbSWilliam A. Kennington III decltype(v)>{}(v); 271bb0eaccbSWilliam A. Kennington III }, 272bb0eaccbSWilliam A. Kennington III v); 273bb0eaccbSWilliam A. Kennington III } 274