blob: be44d24349ddf18c51ed6fd2d9f25743ac55911f [file] [log] [blame]
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07001#pragma once
2#include <linux/netlink.h>
3#include <linux/rtnetlink.h>
4
William A. Kennington III058f4cf2022-08-25 17:01:48 -07005#include <function2/function2.hpp>
William A. Kennington IIIf1289a02022-10-24 18:30:36 -07006#include <stdplus/raw.hpp>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07007#include <string_view>
8#include <tuple>
9#include <type_traits>
10
11namespace phosphor
12{
13namespace network
14{
15namespace netlink
16{
17
18/* @brief Called on each nlmsg received on the socket
19 */
William A. Kennington III058f4cf2022-08-25 17:01:48 -070020using ReceiveCallback =
21 fu2::function_view<void(const nlmsghdr&, std::string_view)>;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070022
23namespace detail
24{
25
William A. Kennington III058f4cf2022-08-25 17:01:48 -070026void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070027
William A. Kennington III058f4cf2022-08-25 17:01:48 -070028void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070029
30} // namespace detail
31
William A. Kennington III5f165dc2022-10-24 15:58:55 -070032/** @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 */
William A. Kennington III29418ef2022-11-07 22:59:47 -080037size_t receive(int sock, ReceiveCallback cb);
William A. Kennington III5f165dc2022-10-24 15:58:55 -070038
William A. Kennington IIIf1289a02022-10-24 18:30:36 -070039/* @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 */
45template <typename T>
46constexpr 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
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070053/* @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 */
59std::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 */
70template <typename T>
71void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg,
William A. Kennington III058f4cf2022-08-25 17:01:48 -070072 ReceiveCallback cb)
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070073{
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