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