1 #pragma once 2 #include <linux/netlink.h> 3 #include <linux/rtnetlink.h> 4 5 #include <function2/function2.hpp> 6 #include <stdplus/raw.hpp> 7 #include <string_view> 8 #include <tuple> 9 #include <type_traits> 10 11 namespace phosphor 12 { 13 namespace network 14 { 15 namespace netlink 16 { 17 18 /* @brief Called on each nlmsg received on the socket 19 */ 20 using ReceiveCallback = 21 fu2::function_view<void(const nlmsghdr&, std::string_view)>; 22 23 namespace detail 24 { 25 26 void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb); 27 28 void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb); 29 30 } // namespace detail 31 32 /** @brief Receives all outstanding messages on a netlink socket 33 * 34 * @param[in] sock - The socket to receive the messages on 35 * @param[in] cb - Called for each response message payload 36 */ 37 size_t receive(int sock, ReceiveCallback cb); 38 39 /* @brief Call on an rtnetlink payload 40 * Updates the input to remove the attr parsed out. 41 * 42 * @param[in,out] data - The buffer holding rtpayload to parse 43 * @return The payload for the rt msg 44 */ 45 template <typename T> 46 constexpr const T& extractRtData(std::string_view& data) 47 { 48 const T& ret = stdplus::raw::refFrom<T, stdplus::raw::Aligned>(data); 49 data.remove_prefix(NLMSG_ALIGN(sizeof(T))); 50 return ret; 51 } 52 53 /* @brief Call on a block of rtattrs to parse a single one out 54 * Updates the input to remove the attr parsed out. 55 * 56 * @param[in,out] attrs - The buffer holding rtattrs to parse 57 * @return A tuple of rtattr header + data buffer for the attr 58 */ 59 std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data); 60 61 /** @brief Performs a netlink request of the specified type with the given 62 * message Calls the callback upon receiving 63 * 64 * @param[in] protocol - The netlink protocol to use when opening the socket 65 * @param[in] type - The netlink message type 66 * @param[in] flags - Additional netlink flags for the request 67 * @param[in] msg - The message payload for the request 68 * @param[in] cb - Called for each response message payload 69 */ 70 template <typename T> 71 void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg, 72 ReceiveCallback cb) 73 { 74 static_assert(std::is_trivially_copyable_v<T>); 75 76 struct 77 { 78 nlmsghdr hdr; 79 T msg; 80 } data{}; 81 data.hdr.nlmsg_len = sizeof(data); 82 data.hdr.nlmsg_type = type; 83 data.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; 84 data.msg = msg; 85 86 detail::performRequest(protocol, &data, sizeof(data), cb); 87 } 88 89 } // namespace netlink 90 } // namespace network 91 } // namespace phosphor 92