Static neighbor support
This changes adds support for assigning static ARP / NDP
neighbors on each ethernet interface.
Tested:
Ran inside a romulus VM and made sure that `ip neigh add`
commands triggered the refresh of static_neighbor objects.
Also verified that static neighbors could be added through
the CreateStatic dbus interface. Verified that deleting those
static entries would persist to the system.
Change-Id: Ifaf753525c532b6dade392d7eb4ebd6d7242d480
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/rtnetlink_server.cpp b/rtnetlink_server.cpp
index 732055a..1c4fd53 100644
--- a/rtnetlink_server.cpp
+++ b/rtnetlink_server.cpp
@@ -14,6 +14,7 @@
#include <memory>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
+#include <string_view>
#include <xyz/openbmc_project/Common/error.hpp>
namespace phosphor
@@ -26,7 +27,7 @@
namespace rtnetlink
{
-static bool shouldRefresh(const struct nlmsghdr& hdr)
+static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
{
switch (hdr.nlmsg_type)
{
@@ -37,6 +38,18 @@
{
return true;
}
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ {
+ struct ndmsg ndm;
+ if (data.size() < sizeof(ndm))
+ {
+ return false;
+ }
+ memcpy(&ndm, data.data(), sizeof(ndm));
+ // We only want to refresh for static neighbors
+ return ndm.ndm_state & NUD_PERMANENT;
+ }
}
return false;
@@ -57,7 +70,10 @@
(netLinkHeader->nlmsg_type != NLMSG_DONE);
netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
{
- if (shouldRefresh(*netLinkHeader))
+ std::string_view data(
+ reinterpret_cast<const char*>(NLMSG_DATA(netLinkHeader)),
+ netLinkHeader->nlmsg_len - NLMSG_HDRLEN);
+ if (shouldRefresh(*netLinkHeader, data))
{
// starting the timer here to make sure that we don't want
// create the child objects multiple times.
@@ -125,7 +141,7 @@
std::memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
- RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
+ RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
{