system: Get current neighbours from Rtnetlink
This will be used for implementing neighbours in ietf-ip YANG model [1].
We wrap libnl's rtnl_link and rtnl_neigh objects into unique_ptr with
custom deleter so the lifetime is auto-managed.
[1] https://tools.ietf.org/html/rfc8344
Change-Id: I1497d9f00d3e8ce969edb630024e26487ee7d0f4
diff --git a/src/system/Rtnetlink.cpp b/src/system/Rtnetlink.cpp
index 476a216..5201b62 100644
--- a/src/system/Rtnetlink.cpp
+++ b/src/system/Rtnetlink.cpp
@@ -6,6 +6,7 @@
*/
#include <netlink/route/link.h>
+#include <netlink/route/neighbour.h>
#include <utility>
#include "Rtnetlink.h"
#include "utils/log.h"
@@ -155,11 +156,23 @@
{
nl_cache* tmpCache;
+
if (auto err = rtnl_link_alloc_cache(m_nlSocket.get(), AF_UNSPEC, &tmpCache); err < 0) {
throw RtnetlinkException("rtnl_link_alloc_cache", err);
}
+
m_nlCacheLink = nlCache(tmpCache, nl_cache_free);
}
+
+ {
+ nl_cache* tmpCache;
+
+ if (auto err = rtnl_neigh_alloc_cache(m_nlSocket.get(), &tmpCache); err < 0) {
+ throw RtnetlinkException("rtnl_neigh_alloc_cache", err);
+ }
+
+ m_nlCacheNeighbour = nlCache(tmpCache, nl_cache_free);
+ }
}
Rtnetlink::~Rtnetlink() = default;
@@ -176,9 +189,23 @@
return res;
}
+std::vector<std::pair<Rtnetlink::nlNeigh, Rtnetlink::nlLink>> Rtnetlink::getNeighbours()
+{
+ resyncCache(m_nlCacheLink);
+ resyncCache(m_nlCacheNeighbour);
+
+ std::vector<std::pair<Rtnetlink::nlNeigh, Rtnetlink::nlLink>> res;
+ nlCacheForeachWrapper<rtnl_neigh>(m_nlCacheNeighbour.get(), [this, &res](rtnl_neigh* neigh) {
+ auto link = rtnl_link_get(m_nlCacheLink.get(), rtnl_neigh_get_ifindex(neigh));
+
+ res.emplace_back(nlObjectWrap(nlObjectClone(neigh)), nlObjectWrap(link));
+ });
+
+ return res;
+}
+
void Rtnetlink::resyncCache(const nlCache& cache)
{
nl_cache_resync(m_nlSocket.get(), cache.get(), [](nl_cache*, nl_object*, int, void*){}, nullptr);
}
-
}
diff --git a/src/system/Rtnetlink.h b/src/system/Rtnetlink.h
index 4ee1659..df73680 100644
--- a/src/system/Rtnetlink.h
+++ b/src/system/Rtnetlink.h
@@ -29,6 +29,7 @@
using nlCacheManager = std::shared_ptr<nl_cache_mngr>;
using nlCache = std::unique_ptr<nl_cache, std::function<void(nl_cache*)>>;
using nlLink = std::unique_ptr<rtnl_link, std::function<void(rtnl_link*)>>;
+ using nlNeigh = std::unique_ptr<rtnl_neigh, std::function<void(rtnl_neigh*)>>;
using LinkCB = std::function<void(rtnl_link* link, int cacheAction)>; /// cacheAction: NL_ACT_*
using AddrCB = std::function<void(rtnl_addr* addr, int cacheAction)>; /// cacheAction: NL_ACT_*
@@ -36,6 +37,7 @@
Rtnetlink(LinkCB cbLink, AddrCB cbAddr);
~Rtnetlink();
std::vector<nlLink> getLinks();
+ std::vector<std::pair<nlNeigh, nlLink>> getNeighbours();
private:
void resyncCache(const nlCache& cache);
@@ -43,7 +45,8 @@
velia::Log m_log;
std::unique_ptr<nl_sock, std::function<void(nl_sock*)>> m_nlSocket;
nlCacheManager m_nlCacheManager; // for updates
- nlCache m_nlCacheLink; // for getLinks
+ nlCache m_nlCacheLink; // for getLinks, getNeighbours
+ nlCache m_nlCacheNeighbour; // for getNeighbours
LinkCB m_cbLink;
AddrCB m_cbAddr;
std::unique_ptr<impl::nlCacheMngrWatcher> m_nlCacheMngrWatcher; // first to destroy, because the thread uses m_nlCacheManager and m_log