blob: b6b89d94311e470e87164c5939bd4ec0300c204a [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>
Patrick Williams89d734b2023-05-10 07:50:25 -05007
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07008#include <string_view>
9#include <tuple>
10#include <type_traits>
11
12namespace phosphor
13{
14namespace network
15{
16namespace netlink
17{
18
19/* @brief Called on each nlmsg received on the socket
20 */
William A. Kennington III058f4cf2022-08-25 17:01:48 -070021using ReceiveCallback =
22 fu2::function_view<void(const nlmsghdr&, std::string_view)>;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070023
24namespace detail
25{
26
William A. Kennington III058f4cf2022-08-25 17:01:48 -070027void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070028
William A. Kennington III058f4cf2022-08-25 17:01:48 -070029void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070030
31} // namespace detail
32
William A. Kennington III5f165dc2022-10-24 15:58:55 -070033/** @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 */
William A. Kennington III29418ef2022-11-07 22:59:47 -080038size_t receive(int sock, ReceiveCallback cb);
William A. Kennington III5f165dc2022-10-24 15:58:55 -070039
William A. Kennington IIIf1289a02022-10-24 18:30:36 -070040/* @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 */
46template <typename T>
47constexpr 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
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070054/* @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 */
60std::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 */
71template <typename T>
72void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg,
William A. Kennington III058f4cf2022-08-25 17:01:48 -070073 ReceiveCallback cb)
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070074{
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