join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
netlinkmanager.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_FABRIC_NETLINKMANAGER_HPP
26#define JOIN_FABRIC_NETLINKMANAGER_HPP
27
28// libjoin.
29#include <join/condition.hpp>
30#include <join/socket.hpp>
31
32// C++.
33#include <unordered_map>
34#include <memory>
35#include <atomic>
36
37// C.
38#include <linux/rtnetlink.h>
39#include <linux/netlink.h>
40#include <cstdint>
41#include <cstddef>
42
43namespace join
44{
49 {
50 public:
56 NetlinkManager (uint32_t groups, Reactor* reactor = nullptr);
57
61 NetlinkManager (const NetlinkManager&) = delete;
62
67
72
77
81 virtual ~NetlinkManager () = default;
82
87 Reactor* reactor () const noexcept;
88
89 protected:
93 void start ();
94
98 void stop ();
99
107 int sendRequest (struct nlmsghdr* nlh, bool sync, std::chrono::milliseconds timeout = std::chrono::seconds (5));
108
116 template <class Rep, class Period>
117 int waitResponse (ScopedLock<Mutex>& lock, uint32_t seq, std::chrono::duration<Rep, Period> timeout)
118 {
119 auto inserted = _pending.emplace (seq, std::make_unique<PendingRequest> ());
120 if (!inserted.second)
121 {
122 lastError = make_error_code (Errc::OperationFailed);
123 return -1;
124 }
125
126 if (!inserted.first->second->cond.timedWait (lock, timeout))
127 {
128 _pending.erase (inserted.first);
129 lastError = make_error_code (Errc::TimedOut);
130 return -1;
131 }
132
133 if (inserted.first->second->error != 0)
134 {
135 int err = inserted.first->second->error;
136 _pending.erase (inserted.first);
137 lastError = std::error_code (err, std::generic_category ());
138 return -1;
139 }
140
141 _pending.erase (inserted.first);
142 return 0;
143 }
144
149 virtual void onReceive (int fd) override final;
150
155 virtual void onMessage (struct nlmsghdr* nlh) = 0;
156
162 void notifyRequest (uint32_t seq, int error = 0);
163
171 static void addAttributes (struct nlmsghdr* nlh, int type, const void* data, int alen);
172
179 static struct rtattr* startNestedAttributes (struct nlmsghdr* nlh, int type);
180
187 static int stopNestedAttributes (struct nlmsghdr* nlh, struct rtattr* nested);
188
195 template <typename T, typename Flag>
196 static Flag updateValue (T& oldVal, const T& newVal, Flag changed)
197 {
198 if (oldVal != newVal)
199 {
200 oldVal = newVal;
201 return changed;
202 }
203 return static_cast<Flag> (0);
204 }
205
207 static constexpr size_t _bufferSize = 16384;
208
210 std::unique_ptr<char[]> _buffer;
211
213 std::atomic<uint32_t> _seq;
214
217 {
219 int error = 0;
220 };
221
223 std::unordered_map<uint32_t, std::unique_ptr<PendingRequest>> _pending;
224
227
230 };
231}
232
233#endif
basic datagram socket class.
Definition socket.hpp:645
int type() const noexcept
get the protocol communication semantic.
Definition socket.hpp:516
condition variable class.
Definition condition.hpp:42
class used to protect shared data from being simultaneously accessed by multiple threads.
Definition mutex.hpp:37
base class for netlink-based managers.
Definition netlinkmanager.hpp:49
static void addAttributes(struct nlmsghdr *nlh, int type, const void *data, int alen)
add an attribute to a netlink message.
Definition netlinkmanager.cpp:154
std::atomic< uint32_t > _seq
sequence number.
Definition netlinkmanager.hpp:213
virtual void onReceive(int fd) override final
method called when data are ready to be read on handle.
Definition netlinkmanager.cpp:105
int waitResponse(ScopedLock< Mutex > &lock, uint32_t seq, std::chrono::duration< Rep, Period > timeout)
wait for specific netlink response.
Definition netlinkmanager.hpp:117
static constexpr size_t _bufferSize
internal buffer size.
Definition netlinkmanager.hpp:207
NetlinkManager(uint32_t groups, Reactor *reactor=nullptr)
create instance.
Definition netlinkmanager.cpp:35
int sendRequest(struct nlmsghdr *nlh, bool sync, std::chrono::milliseconds timeout=std::chrono::seconds(5))
send a netlink request, optionally waiting for the ack.
Definition netlinkmanager.cpp:79
Mutex _syncMutex
protection mutex.
Definition netlinkmanager.hpp:226
static Flag updateValue(T &oldVal, const T &newVal, Flag changed)
update a value in place and report whether it changed.
Definition netlinkmanager.hpp:196
void notifyRequest(uint32_t seq, int error=0)
notify a pending synchronous request.
Definition netlinkmanager.cpp:138
NetlinkManager(NetlinkManager &&)=delete
create instance by move.
Reactor * reactor() const noexcept
get the event loop reactor.
Definition netlinkmanager.cpp:52
Reactor * _reactor
event loop reactor.
Definition netlinkmanager.hpp:229
NetlinkManager & operator=(const NetlinkManager &)=delete
assign instance by copy.
void stop()
stop listening for netlink events.
Definition netlinkmanager.cpp:70
NetlinkManager(const NetlinkManager &)=delete
create instance by copy.
static struct rtattr * startNestedAttributes(struct nlmsghdr *nlh, int type)
open a nested attribute block.
Definition netlinkmanager.cpp:169
void start()
start listening for netlink events.
Definition netlinkmanager.cpp:61
std::unique_ptr< char[]> _buffer
internal read buffer.
Definition netlinkmanager.hpp:210
virtual ~NetlinkManager()=default
destroy instance.
virtual void onMessage(struct nlmsghdr *nlh)=0
dispatch a single RTM_* message to the derived class.
std::unordered_map< uint32_t, std::unique_ptr< PendingRequest > > _pending
synchronous requests indexed by sequence number.
Definition netlinkmanager.hpp:223
static int stopNestedAttributes(struct nlmsghdr *nlh, struct rtattr *nested)
close a nested attribute block.
Definition netlinkmanager.cpp:181
Reactor class.
Definition reactor.hpp:120
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:246
Definition acceptor.hpp:32
Definition error.hpp:137
pending synchronous request.
Definition netlinkmanager.hpp:217
int error
Definition netlinkmanager.hpp:219
Condition cond
Definition netlinkmanager.hpp:218