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