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