rtnetlink_server: Don't refresh for addresses

We can dynamically add and remove addresses without having to recreate
all of the objects.

Change-Id: Ic510263cc6ba5d2ec228ce94fa83cf5fe4664c6d
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index a0c6193..3df966d 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -173,31 +173,35 @@
     );
 }
 
+void EthernetInterface::addAddr(const AddressInfo& info)
+{
+    if (info.flags & IFA_F_DEPRECATED)
+    {
+        return;
+    }
+    IP::AddressOrigin origin = IP::AddressOrigin::Static;
+    if (dhcpIsEnabled(info.ifaddr.getAddr()))
+    {
+        origin = IP::AddressOrigin::DHCP;
+    }
+#ifdef LINK_LOCAL_AUTOCONFIGURATION
+    if (info.scope == RT_SCOPE_LINK)
+    {
+        origin = IP::AddressOrigin::LinkLocal;
+    }
+#endif
+
+    this->addrs.insert_or_assign(
+        info.ifaddr, std::make_unique<IPAddress>(bus, std::string_view(objPath),
+                                                 *this, info.ifaddr, origin));
+}
+
 void EthernetInterface::createIPAddressObjects()
 {
     addrs.clear();
     for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
     {
-        if (addr.flags & IFA_F_DEPRECATED)
-        {
-            continue;
-        }
-        IP::AddressOrigin origin = IP::AddressOrigin::Static;
-        if (dhcpIsEnabled(addr.ifaddr.getAddr()))
-        {
-            origin = IP::AddressOrigin::DHCP;
-        }
-#ifdef LINK_LOCAL_AUTOCONFIGURATION
-        if (addr.scope == RT_SCOPE_LINK)
-        {
-            origin = IP::AddressOrigin::LinkLocal;
-        }
-#endif
-
-        this->addrs.insert_or_assign(
-            addr.ifaddr,
-            std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
-                                        addr.ifaddr, origin));
+        addAddr(addr);
     }
 }
 
@@ -270,7 +274,7 @@
                                     ifaddr, IP::AddressOrigin::Static));
 
     writeConfigurationFile();
-    manager.reloadConfigs();
+    manager.reloadConfigsNoRefresh();
 
     return it->second->getObjPath();
 }
diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
index 7d14385..f14e069 100644
--- a/src/ethernet_interface.hpp
+++ b/src/ethernet_interface.hpp
@@ -100,6 +100,8 @@
     /** @brief Persistent map of Neighbor dbus objects and their names */
     std::unordered_map<InAddrAny, std::unique_ptr<Neighbor>> staticNeighbors;
 
+    void addAddr(const AddressInfo& info);
+
     /** @brief Updates the interface information based on new InterfaceInfo */
     void updateInfo(const system::InterfaceInfo& info);
 
diff --git a/src/ipaddress.cpp b/src/ipaddress.cpp
index 560129d..b3ca3db 100644
--- a/src/ipaddress.cpp
+++ b/src/ipaddress.cpp
@@ -111,7 +111,7 @@
     }
 
     parent.writeConfigurationFile();
-    parent.manager.reloadConfigs();
+    parent.manager.reloadConfigsNoRefresh();
 }
 
 } // namespace network
diff --git a/src/rtnetlink_server.cpp b/src/rtnetlink_server.cpp
index 880eba1..2a0ab38 100644
--- a/src/rtnetlink_server.cpp
+++ b/src/rtnetlink_server.cpp
@@ -36,8 +36,6 @@
     {
         case RTM_NEWLINK:
         case RTM_DELLINK:
-        case RTM_NEWADDR:
-        case RTM_DELADDR:
             return true;
         case RTM_NEWNEIGH:
         case RTM_DELNEIGH:
@@ -103,6 +101,26 @@
         std::get<InAddrAny>(*ret));
 }
 
+static void addrhandler(Manager& m, bool n, std::string_view data)
+{
+    auto info = netlink::addrFromRtm(data);
+    auto it = m.interfacesByIdx.find(info.ifidx);
+    if (it == m.interfacesByIdx.end())
+    {
+        auto msg = fmt::format("Interface `{}` not found for addr", info.ifidx);
+        log<level::ERR>(msg.c_str(), entry("IFIDX=%u", info.ifidx));
+        return;
+    }
+    if (n)
+    {
+        it->second->addAddr(info);
+    }
+    else
+    {
+        it->second->addrs.erase(info.ifaddr);
+    }
+}
+
 static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data)
 {
     if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
@@ -117,6 +135,12 @@
         case RTM_DELROUTE:
             rthandler(m, false, data);
             break;
+        case RTM_NEWADDR:
+            addrhandler(m, true, data);
+            break;
+        case RTM_DELADDR:
+            addrhandler(m, false, data);
+            break;
     }
 }