11bbe3d1eSWilliam A. Kennington III #pragma once
21bbe3d1eSWilliam A. Kennington III #include <linux/netlink.h>
31bbe3d1eSWilliam A. Kennington III #include <linux/rtnetlink.h>
41bbe3d1eSWilliam A. Kennington III
5*2d86eb1bSWilliam A. Kennington III #include <stdplus/function_view.hpp>
6f1289a0aSWilliam A. Kennington III #include <stdplus/raw.hpp>
789d734b9SPatrick Williams
81bbe3d1eSWilliam A. Kennington III #include <string_view>
91bbe3d1eSWilliam A. Kennington III #include <tuple>
101bbe3d1eSWilliam A. Kennington III #include <type_traits>
111bbe3d1eSWilliam A. Kennington III
121bbe3d1eSWilliam A. Kennington III namespace phosphor
131bbe3d1eSWilliam A. Kennington III {
141bbe3d1eSWilliam A. Kennington III namespace network
151bbe3d1eSWilliam A. Kennington III {
161bbe3d1eSWilliam A. Kennington III namespace netlink
171bbe3d1eSWilliam A. Kennington III {
181bbe3d1eSWilliam A. Kennington III
191bbe3d1eSWilliam A. Kennington III /* @brief Called on each nlmsg received on the socket
201bbe3d1eSWilliam A. Kennington III */
21058f4cf7SWilliam A. Kennington III using ReceiveCallback =
22*2d86eb1bSWilliam A. Kennington III stdplus::function_view<void(const nlmsghdr&, std::string_view)>;
231bbe3d1eSWilliam A. Kennington III
241bbe3d1eSWilliam A. Kennington III namespace detail
251bbe3d1eSWilliam A. Kennington III {
261bbe3d1eSWilliam A. Kennington III
27058f4cf7SWilliam A. Kennington III void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb);
281bbe3d1eSWilliam A. Kennington III
29058f4cf7SWilliam A. Kennington III void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb);
301bbe3d1eSWilliam A. Kennington III
311bbe3d1eSWilliam A. Kennington III } // namespace detail
321bbe3d1eSWilliam A. Kennington III
335f165dccSWilliam A. Kennington III /** @brief Receives all outstanding messages on a netlink socket
345f165dccSWilliam A. Kennington III *
355f165dccSWilliam A. Kennington III * @param[in] sock - The socket to receive the messages on
365f165dccSWilliam A. Kennington III * @param[in] cb - Called for each response message payload
375f165dccSWilliam A. Kennington III */
3829418efcSWilliam A. Kennington III size_t receive(int sock, ReceiveCallback cb);
395f165dccSWilliam A. Kennington III
40f1289a0aSWilliam A. Kennington III /* @brief Call on an rtnetlink payload
41f1289a0aSWilliam A. Kennington III * Updates the input to remove the attr parsed out.
42f1289a0aSWilliam A. Kennington III *
43f1289a0aSWilliam A. Kennington III * @param[in,out] data - The buffer holding rtpayload to parse
44f1289a0aSWilliam A. Kennington III * @return The payload for the rt msg
45f1289a0aSWilliam A. Kennington III */
46f1289a0aSWilliam A. Kennington III template <typename T>
extractRtData(std::string_view & data)47f1289a0aSWilliam A. Kennington III constexpr const T& extractRtData(std::string_view& data)
48f1289a0aSWilliam A. Kennington III {
49f1289a0aSWilliam A. Kennington III const T& ret = stdplus::raw::refFrom<T, stdplus::raw::Aligned>(data);
50f1289a0aSWilliam A. Kennington III data.remove_prefix(NLMSG_ALIGN(sizeof(T)));
51f1289a0aSWilliam A. Kennington III return ret;
52f1289a0aSWilliam A. Kennington III }
53f1289a0aSWilliam A. Kennington III
541bbe3d1eSWilliam A. Kennington III /* @brief Call on a block of rtattrs to parse a single one out
551bbe3d1eSWilliam A. Kennington III * Updates the input to remove the attr parsed out.
561bbe3d1eSWilliam A. Kennington III *
571bbe3d1eSWilliam A. Kennington III * @param[in,out] attrs - The buffer holding rtattrs to parse
581bbe3d1eSWilliam A. Kennington III * @return A tuple of rtattr header + data buffer for the attr
591bbe3d1eSWilliam A. Kennington III */
601bbe3d1eSWilliam A. Kennington III std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data);
611bbe3d1eSWilliam A. Kennington III
621bbe3d1eSWilliam A. Kennington III /** @brief Performs a netlink request of the specified type with the given
631bbe3d1eSWilliam A. Kennington III * message Calls the callback upon receiving
641bbe3d1eSWilliam A. Kennington III *
651bbe3d1eSWilliam A. Kennington III * @param[in] protocol - The netlink protocol to use when opening the socket
661bbe3d1eSWilliam A. Kennington III * @param[in] type - The netlink message type
671bbe3d1eSWilliam A. Kennington III * @param[in] flags - Additional netlink flags for the request
681bbe3d1eSWilliam A. Kennington III * @param[in] msg - The message payload for the request
691bbe3d1eSWilliam A. Kennington III * @param[in] cb - Called for each response message payload
701bbe3d1eSWilliam A. Kennington III */
711bbe3d1eSWilliam A. Kennington III template <typename T>
performRequest(int protocol,uint16_t type,uint16_t flags,const T & msg,ReceiveCallback cb)721bbe3d1eSWilliam A. Kennington III void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg,
73058f4cf7SWilliam A. Kennington III ReceiveCallback cb)
741bbe3d1eSWilliam A. Kennington III {
751bbe3d1eSWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>);
761bbe3d1eSWilliam A. Kennington III
771bbe3d1eSWilliam A. Kennington III struct
781bbe3d1eSWilliam A. Kennington III {
791bbe3d1eSWilliam A. Kennington III nlmsghdr hdr;
801bbe3d1eSWilliam A. Kennington III T msg;
811bbe3d1eSWilliam A. Kennington III } data{};
821bbe3d1eSWilliam A. Kennington III data.hdr.nlmsg_len = sizeof(data);
831bbe3d1eSWilliam A. Kennington III data.hdr.nlmsg_type = type;
841bbe3d1eSWilliam A. Kennington III data.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
851bbe3d1eSWilliam A. Kennington III data.msg = msg;
861bbe3d1eSWilliam A. Kennington III
871bbe3d1eSWilliam A. Kennington III detail::performRequest(protocol, &data, sizeof(data), cb);
881bbe3d1eSWilliam A. Kennington III }
891bbe3d1eSWilliam A. Kennington III
901bbe3d1eSWilliam A. Kennington III } // namespace netlink
911bbe3d1eSWilliam A. Kennington III } // namespace network
921bbe3d1eSWilliam A. Kennington III } // namespace phosphor
93