rtnetlink_server: Avoid refreshing for gateway changes
Instead of refreshing all of the objects, we can just update the
ethernet object that has the gateway route.
Change-Id: Ib1922273b625b1400625c6a851330e3642a8c647
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 94a8b60..c2e3e63 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -944,7 +944,7 @@
EthernetInterfaceIntf::defaultGateway(gateway);
writeConfigurationFile();
- manager.reloadConfigs();
+ manager.reloadConfigsNoRefresh();
return gateway;
}
@@ -973,7 +973,7 @@
EthernetInterfaceIntf::defaultGateway6(gateway);
writeConfigurationFile();
- manager.reloadConfigs();
+ manager.reloadConfigsNoRefresh();
return gateway;
}
diff --git a/src/network_manager_main.cpp b/src/network_manager_main.cpp
index 80276b3..1c2e38e 100644
--- a/src/network_manager_main.cpp
+++ b/src/network_manager_main.cpp
@@ -292,7 +292,7 @@
manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
// RTNETLINK event handler
- netlink::Server svr(event);
+ netlink::Server svr(event, *manager);
#ifdef SYNC_MAC_FROM_INVENTORY
std::ifstream in(configFile);
diff --git a/src/rtnetlink_server.cpp b/src/rtnetlink_server.cpp
index 185589e..880eba1 100644
--- a/src/rtnetlink_server.cpp
+++ b/src/rtnetlink_server.cpp
@@ -1,6 +1,8 @@
#include "rtnetlink_server.hpp"
#include "netlink.hpp"
+#include "network_manager.hpp"
+#include "rtnetlink.hpp"
#include "types.hpp"
#include <linux/netlink.h>
@@ -8,6 +10,7 @@
#include <netinet/in.h>
#include <memory>
+#include <phosphor-logging/log.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/ops.hpp>
#include <string_view>
@@ -22,6 +25,10 @@
namespace netlink
{
+using phosphor::logging::entry;
+using phosphor::logging::level;
+using phosphor::logging::log;
+
static bool shouldRefresh(const struct nlmsghdr& hdr,
std::string_view data) noexcept
{
@@ -31,8 +38,6 @@
case RTM_DELLINK:
case RTM_NEWADDR:
case RTM_DELADDR:
- case RTM_NEWROUTE:
- case RTM_DELROUTE:
return true;
case RTM_NEWNEIGH:
case RTM_DELNEIGH:
@@ -49,17 +54,78 @@
return false;
}
-static void handler(const nlmsghdr& hdr, std::string_view data)
+static void rthandler(Manager& m, bool n, std::string_view data)
+{
+ auto ret = netlink::gatewayFromRtm(data);
+ if (!ret)
+ {
+ return;
+ }
+ auto ifIdx = std::get<unsigned>(*ret);
+ auto it = m.interfacesByIdx.find(ifIdx);
+ if (it == m.interfacesByIdx.end())
+ {
+ auto msg = fmt::format("Interface `{}` not found for route", ifIdx);
+ log<level::ERR>(msg.c_str(), entry("IFIDX=%u", ifIdx));
+ return;
+ }
+ std::visit(
+ [&](auto addr) {
+ if constexpr (std::is_same_v<in_addr, decltype(addr)>)
+ {
+ if (n)
+ {
+ it->second->EthernetInterfaceIntf::defaultGateway(
+ std::to_string(addr));
+ }
+ else if (it->second->defaultGateway() == std::to_string(addr))
+ {
+ it->second->EthernetInterfaceIntf::defaultGateway("");
+ }
+ }
+ else if constexpr (std::is_same_v<in6_addr, decltype(addr)>)
+ {
+ if (n)
+ {
+ it->second->EthernetInterfaceIntf::defaultGateway6(
+ std::to_string(addr));
+ }
+ else if (it->second->defaultGateway6() == std::to_string(addr))
+ {
+ it->second->EthernetInterfaceIntf::defaultGateway6("");
+ }
+ }
+ else
+ {
+ static_assert(!std::is_same_v<void, decltype(addr)>);
+ }
+ },
+ std::get<InAddrAny>(*ret));
+}
+
+static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data)
{
if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
{
refreshObjectTimer->restartOnce(refreshTimeout);
}
+ switch (hdr.nlmsg_type)
+ {
+ case RTM_NEWROUTE:
+ rthandler(m, true, data);
+ break;
+ case RTM_DELROUTE:
+ rthandler(m, false, data);
+ break;
+ }
}
-static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
+static void eventHandler(Manager& m, sdeventplus::source::IO&, int fd, uint32_t)
{
- while (receive(fd, handler) > 0)
+ auto cb = [&](auto&&... args) {
+ return handler(m, std::forward<decltype(args)>(args)...);
+ };
+ while (receive(fd, cb) > 0)
;
}
@@ -81,8 +147,11 @@
return sock;
}
-Server::Server(sdeventplus::Event& event) :
- sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler)
+Server::Server(sdeventplus::Event& event, Manager& manager) :
+ sock(makeSock()),
+ io(event, sock.get(), EPOLLIN | EPOLLET, [&](auto&&... args) {
+ return eventHandler(manager, std::forward<decltype(args)>(args)...);
+ })
{
}
diff --git a/src/rtnetlink_server.hpp b/src/rtnetlink_server.hpp
index 066f19c..49e32ea 100644
--- a/src/rtnetlink_server.hpp
+++ b/src/rtnetlink_server.hpp
@@ -7,6 +7,7 @@
{
namespace network
{
+class Manager;
namespace netlink
{
@@ -26,9 +27,9 @@
* @details Sets up the server to handle incoming RTNETLINK events
*
* @param[in] eventPtr - Unique ptr reference to sd_event.
- * @param[in] socket - netlink socket.
+ * @param[in] manager - The network manager that receives updates
*/
- Server(sdeventplus::Event& event);
+ Server(sdeventplus::Event& event, Manager& manager);
/** @brief Gets the socket associated with this netlink server */
inline stdplus::Fd& getSock()