xref: /openbmc/phosphor-networkd/src/netlink.hpp (revision b03a760f)
1 #pragma once
2 #include <linux/netlink.h>
3 #include <linux/rtnetlink.h>
4 
5 #include <function2/function2.hpp>
6 #include <stdplus/raw.hpp>
7 #include <string_view>
8 #include <tuple>
9 #include <type_traits>
10 
11 namespace phosphor
12 {
13 namespace network
14 {
15 namespace netlink
16 {
17 
18 /* @brief Called on each nlmsg received on the socket
19  */
20 using ReceiveCallback =
21     fu2::function_view<void(const nlmsghdr&, std::string_view)>;
22 
23 namespace detail
24 {
25 
26 void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb);
27 
28 void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb);
29 
30 } // namespace detail
31 
32 /** @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  */
37 size_t receive(int sock, ReceiveCallback cb);
38 
39 /* @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  */
45 template <typename T>
46 constexpr 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 
53 /* @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  */
59 std::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  */
70 template <typename T>
71 void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg,
72                     ReceiveCallback cb)
73 {
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
92