rtnetlink: Migrate neighbor functions
Change-Id: I697f3d70f327f5d1d5e104dc7e4a2af528bf2b6e
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index b3179f4..4664655 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -216,21 +216,16 @@
void EthernetInterface::createStaticNeighborObjects()
{
staticNeighbors.clear();
-
- NeighborFilter filter;
- filter.interface = ifIdx;
- filter.state = NUD_PERMANENT;
- auto neighbors = getCurrentNeighbors(filter);
- for (const auto& neighbor : neighbors)
+ for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
{
- if (!neighbor.mac)
+ if (!neighbor.mac || (neighbor.state & NUD_PERMANENT) == 0)
{
continue;
}
staticNeighbors.emplace(
- neighbor.address,
+ neighbor.addr,
std::make_unique<Neighbor>(bus, std::string_view(objPath), *this,
- neighbor.address, *neighbor.mac,
+ neighbor.addr, *neighbor.mac,
Neighbor::State::Permanent));
}
}
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index c9c1fc9..0f5140e 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -1,92 +1,17 @@
#include "neighbor.hpp"
#include "ethernet_interface.hpp"
-#include "netlink.hpp"
#include "network_manager.hpp"
-#include "util.hpp"
-
-#include <linux/neighbour.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/types.h>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
-#include <stdexcept>
-#include <stdplus/raw.hpp>
#include <string>
-#include <string_view>
-#include <utility>
-#include <vector>
#include <xyz/openbmc_project/Common/error.hpp>
namespace phosphor
{
namespace network
{
-namespace detail
-{
-
-void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr,
- std::string_view msg, std::vector<NeighborInfo>& neighbors)
-{
- if (hdr.nlmsg_type != RTM_NEWNEIGH)
- {
- throw std::runtime_error("Not a neighbor msg");
- }
- const auto& ndm = netlink::extractRtData<ndmsg>(msg);
-
- // Filter out neighbors we don't care about
- unsigned ifindex = ndm.ndm_ifindex;
- if (filter.interface != 0 && filter.interface != ifindex)
- {
- return;
- }
- if ((ndm.ndm_state & filter.state) == 0)
- {
- return;
- }
-
- // Build the neighbor info for our valid neighbor
- NeighborInfo neighbor;
- neighbor.interface = ifindex;
- neighbor.state = ndm.ndm_state;
- bool set_addr = false;
- while (!msg.empty())
- {
- auto [hdr, data] = netlink::extractRtAttr(msg);
- if (hdr.rta_type == NDA_LLADDR)
- {
- neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data);
- }
- else if (hdr.rta_type == NDA_DST)
- {
- neighbor.address = addrFromBuf(ndm.ndm_family, data);
- set_addr = true;
- }
- }
- if (!set_addr)
- {
- throw std::runtime_error("Missing address");
- }
- neighbors.push_back(std::move(neighbor));
-}
-
-} // namespace detail
-
-std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter)
-{
- std::vector<NeighborInfo> neighbors;
- auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) {
- detail::parseNeighbor(filter, hdr, msg, neighbors);
- };
- ndmsg msg{};
- msg.ndm_ifindex = filter.interface;
- netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb);
- return neighbors;
-}
static auto makeObjPath(std::string_view root, InAddrAny addr)
{
diff --git a/src/neighbor.hpp b/src/neighbor.hpp
index 4cd3682..37f8d17 100644
--- a/src/neighbor.hpp
+++ b/src/neighbor.hpp
@@ -1,16 +1,10 @@
#pragma once
#include "types.hpp"
-#include <linux/netlink.h>
-#include <net/ethernet.h>
-
-#include <cstdint>
-#include <optional>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/server/object.hpp>
#include <string_view>
-#include <vector>
#include <xyz/openbmc_project/Network/Neighbor/server.hpp>
#include <xyz/openbmc_project/Object/Delete/server.hpp>
@@ -26,34 +20,6 @@
class EthernetInterface;
-/* @class NeighborFilter
- */
-struct NeighborFilter
-{
- unsigned interface;
- uint16_t state;
-
- /* @brief Creates an empty filter */
- NeighborFilter() : interface(0), state(~UINT16_C(0))
- {
- }
-};
-
-/** @class NeighborInfo
- * @brief Information about a neighbor from the kernel
- */
-struct NeighborInfo
-{
- unsigned interface;
- InAddrAny address;
- std::optional<ether_addr> mac;
- uint16_t state;
-};
-
-/** @brief Returns a list of the current system neighbor table
- */
-std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter);
-
/** @class Neighbor
* @brief OpenBMC network neighbor implementation.
* @details A concrete implementation for the
@@ -111,13 +77,5 @@
State state);
};
-namespace detail
-{
-
-void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr,
- std::string_view msg, std::vector<NeighborInfo>& neighbors);
-
-} // namespace detail
-
} // namespace network
} // namespace phosphor
diff --git a/src/rtnetlink.cpp b/src/rtnetlink.cpp
index 5d6e660..6b456b7 100644
--- a/src/rtnetlink.cpp
+++ b/src/rtnetlink.cpp
@@ -81,4 +81,32 @@
return ret;
}
+NeighborInfo neighFromRtm(std::string_view msg)
+{
+ const auto& ndm = netlink::extractRtData<ndmsg>(msg);
+
+ NeighborInfo ret;
+ ret.ifidx = ndm.ndm_ifindex;
+ ret.state = ndm.ndm_state;
+ bool set_addr = false;
+ while (!msg.empty())
+ {
+ auto [hdr, data] = netlink::extractRtAttr(msg);
+ if (hdr.rta_type == NDA_LLADDR)
+ {
+ ret.mac = stdplus::raw::copyFrom<ether_addr>(data);
+ }
+ else if (hdr.rta_type == NDA_DST)
+ {
+ ret.addr = addrFromBuf(ndm.ndm_family, data);
+ set_addr = true;
+ }
+ }
+ if (!set_addr)
+ {
+ throw std::runtime_error("Missing address");
+ }
+ return ret;
+}
+
} // namespace phosphor::network::netlink
diff --git a/src/rtnetlink.hpp b/src/rtnetlink.hpp
index 48f3820..2862143 100644
--- a/src/rtnetlink.hpp
+++ b/src/rtnetlink.hpp
@@ -13,4 +13,6 @@
AddressInfo addrFromRtm(std::string_view msg);
+NeighborInfo neighFromRtm(std::string_view msg);
+
} // namespace phosphor::network::netlink
diff --git a/src/system_queries.cpp b/src/system_queries.cpp
index 5aba1d2..35dfa10 100644
--- a/src/system_queries.cpp
+++ b/src/system_queries.cpp
@@ -235,6 +235,16 @@
return true;
}
+bool detail::validateNewNeigh(const NeighborInfo& info,
+ const NeighborFilter& filter) noexcept
+{
+ if (filter.ifidx != 0 && filter.ifidx != info.ifidx)
+ {
+ return false;
+ }
+ return true;
+}
+
std::vector<InterfaceInfo> getInterfaces()
{
std::vector<InterfaceInfo> ret;
@@ -266,4 +276,20 @@
return ret;
}
+std::vector<NeighborInfo> getNeighbors(const NeighborFilter& filter)
+{
+ std::vector<NeighborInfo> ret;
+ auto cb = [&](const nlmsghdr&, std::string_view msg) {
+ auto info = netlink::neighFromRtm(msg);
+ if (detail::validateNewNeigh(info, filter))
+ {
+ ret.push_back(std::move(info));
+ }
+ };
+ ndmsg msg{};
+ msg.ndm_ifindex = filter.ifidx;
+ netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb);
+ return ret;
+}
+
} // namespace phosphor::network::system
diff --git a/src/system_queries.hpp b/src/system_queries.hpp
index 97a5faa..615c282 100644
--- a/src/system_queries.hpp
+++ b/src/system_queries.hpp
@@ -58,12 +58,19 @@
unsigned ifidx = 0;
};
+struct NeighborFilter
+{
+ unsigned ifidx = 0;
+};
+
namespace detail
{
InterfaceInfo parseInterface(const nlmsghdr& hdr, std::string_view msg);
bool validateNewInterface(const InterfaceInfo& info);
bool validateNewAddr(const AddressInfo& info,
const AddressFilter& filter) noexcept;
+bool validateNewNeigh(const NeighborInfo& info,
+ const NeighborFilter& filter) noexcept;
} // namespace detail
/** @brief Get all the interfaces from the system.
@@ -76,4 +83,8 @@
*/
std::vector<AddressInfo> getAddresses(const AddressFilter& filter);
+/** @brief Returns a list of system neighbor table
+ */
+std::vector<NeighborInfo> getNeighbors(const NeighborFilter& filter);
+
} // namespace phosphor::network::system
diff --git a/src/types.hpp b/src/types.hpp
index 8755068..bdb431d 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -86,6 +86,17 @@
uint32_t flags;
};
+/** @class NeighborInfo
+ * @brief Information about a neighbor from the kernel
+ */
+struct NeighborInfo
+{
+ unsigned ifidx;
+ InAddrAny addr;
+ std::optional<ether_addr> mac;
+ uint16_t state;
+};
+
struct string_hash : public std::hash<std::string_view>
{
using is_transparent = void;