rtnetlink_server: Use netlink parser code
Change-Id: I97a8fd1c692973a8ac97171dfaf309cfc9cfceb1
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/netlink.cpp b/src/netlink.cpp
index 5bc876f..ed1278f 100644
--- a/src/netlink.cpp
+++ b/src/netlink.cpp
@@ -78,53 +78,6 @@
}
}
-static void receive(int sock, ReceiveCallback cb)
-{
- // We need to make sure we have enough room for an entire packet otherwise
- // it gets truncated. The netlink docs guarantee packets will not exceed 8K
- std::array<char, 8192> buf;
-
- iovec iov{};
- iov.iov_base = buf.data();
- iov.iov_len = buf.size();
-
- sockaddr_nl from{};
- from.nl_family = AF_NETLINK;
-
- msghdr hdr{};
- hdr.msg_name = &from;
- hdr.msg_namelen = sizeof(from);
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- // We only do multiple recvs if we have a MULTI type message
- bool done = true;
- do
- {
- ssize_t recvd = recvmsg(sock, &hdr, 0);
- if (recvd < 0)
- {
- throw std::system_error(errno, std::generic_category(),
- "netlink recvmsg");
- }
- if (recvd == 0)
- {
- throw std::runtime_error("netlink recvmsg: Got empty payload");
- }
-
- std::string_view msgs(buf.data(), recvd);
- do
- {
- processMsg(msgs, done, cb);
- } while (!done && !msgs.empty());
-
- if (done && !msgs.empty())
- {
- throw std::runtime_error("Extra unprocessed netlink messages");
- }
- } while (!done);
-}
-
static void requestSend(int sock, void* data, size_t size)
{
sockaddr_nl dst{};
@@ -170,6 +123,57 @@
} // namespace detail
+void receive(int sock, ReceiveCallback cb)
+{
+ // We need to make sure we have enough room for an entire packet otherwise
+ // it gets truncated. The netlink docs guarantee packets will not exceed 8K
+ std::array<char, 8192> buf;
+
+ iovec iov{};
+ iov.iov_base = buf.data();
+ iov.iov_len = buf.size();
+
+ sockaddr_nl from{};
+ from.nl_family = AF_NETLINK;
+
+ msghdr hdr{};
+ hdr.msg_name = &from;
+ hdr.msg_namelen = sizeof(from);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ // We only do multiple recvs if we have a MULTI type message
+ bool done = true;
+ do
+ {
+ ssize_t recvd = recvmsg(sock, &hdr, 0);
+ if (recvd < 0)
+ {
+ throw std::system_error(errno, std::generic_category(),
+ "netlink recvmsg");
+ }
+ if (recvd == 0)
+ {
+ if (!done)
+ {
+ throw std::runtime_error("netlink recvmsg: Got empty payload");
+ }
+ return;
+ }
+
+ std::string_view msgs(buf.data(), recvd);
+ do
+ {
+ detail::processMsg(msgs, done, cb);
+ } while (!done && !msgs.empty());
+
+ if (done && !msgs.empty())
+ {
+ throw std::runtime_error("Extra unprocessed netlink messages");
+ }
+ } while (!done);
+}
+
std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data)
{
auto hdr = stdplus::raw::copyFrom<rtattr>(data);
diff --git a/src/netlink.hpp b/src/netlink.hpp
index 2168972..1260f8e 100644
--- a/src/netlink.hpp
+++ b/src/netlink.hpp
@@ -28,6 +28,13 @@
} // namespace detail
+/** @brief Receives all outstanding messages on a netlink socket
+ *
+ * @param[in] sock - The socket to receive the messages on
+ * @param[in] cb - Called for each response message payload
+ */
+void receive(int sock, ReceiveCallback cb);
+
/* @brief Call on a block of rtattrs to parse a single one out
* Updates the input to remove the attr parsed out.
*
diff --git a/src/network_manager_main.cpp b/src/network_manager_main.cpp
index 876ed0a..8f8a89e 100644
--- a/src/network_manager_main.cpp
+++ b/src/network_manager_main.cpp
@@ -289,7 +289,7 @@
manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
// RTNETLINK event handler
- rtnetlink::Server svr(event);
+ netlink::Server svr(event);
#ifdef SYNC_MAC_FROM_INVENTORY
std::ifstream in(configFile);
diff --git a/src/rtnetlink_server.cpp b/src/rtnetlink_server.cpp
index d14b28e..cf68340 100644
--- a/src/rtnetlink_server.cpp
+++ b/src/rtnetlink_server.cpp
@@ -1,5 +1,6 @@
#include "rtnetlink_server.hpp"
+#include "netlink.hpp"
#include "types.hpp"
#include <linux/netlink.h>
@@ -18,10 +19,11 @@
extern std::unique_ptr<Timer> refreshObjectTimer;
-namespace rtnetlink
+namespace netlink
{
-static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
+static bool shouldRefresh(const struct nlmsghdr& hdr,
+ std::string_view data) noexcept
{
switch (hdr.nlmsg_type)
{
@@ -49,41 +51,17 @@
return false;
}
-/* Call Back for the sd event loop */
+static void handler(const nlmsghdr& hdr, std::string_view data)
+{
+ if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
+ {
+ refreshObjectTimer->restartOnce(refreshTimeout);
+ }
+}
+
static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
{
- std::array<char, BUFSIZE> buffer = {};
- int len{};
-
- auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
-
- while ((len = recv(fd, netLinkHeader, buffer.size(), 0)) > 0)
- {
- for (; (NLMSG_OK(netLinkHeader, len)) &&
- (netLinkHeader->nlmsg_type != NLMSG_DONE);
- netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
- {
- 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.
- if (!refreshObjectTimer->isEnabled())
- {
- // if start timer throws exception then let the application
- // crash
- refreshObjectTimer->restartOnce(refreshTimeout);
- } // end if
- } // end if
-
- } // end for
-
- buffer.fill('\0');
-
- netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
- } // end while
+ receive(fd, handler);
}
static stdplus::ManagedFd makeSock()
@@ -109,6 +87,6 @@
{
}
-} // namespace rtnetlink
+} // namespace netlink
} // namespace network
} // namespace phosphor
diff --git a/src/rtnetlink_server.hpp b/src/rtnetlink_server.hpp
index 1e849ee..066f19c 100644
--- a/src/rtnetlink_server.hpp
+++ b/src/rtnetlink_server.hpp
@@ -3,16 +3,11 @@
#include <sdeventplus/source/io.hpp>
#include <stdplus/fd/managed.hpp>
-namespace sdeventplus
-{
-class Event;
-}
-
namespace phosphor
{
namespace network
{
-namespace rtnetlink
+namespace netlink
{
constexpr auto BUFSIZE = 4096;
@@ -22,7 +17,6 @@
Usage would be create the server with the call back
and call the run method.
*/
-
class Server
{
@@ -47,6 +41,6 @@
sdeventplus::source::IO io;
};
-} // namespace rtnetlink
+} // namespace netlink
} // namespace network
} // namespace phosphor