Restart the network through networkManager

Extend the refresh timer once we get the Dbus request which
requires network restart.

Detaching the network restart from the writeConfiguration func.
Write the configuration file for the vlan interface in
writeConfiguration func.

During creation of vlan,vlan interface should come up with
dhcp as false.

Change-Id: Iadc7b44554aca412d211d13e9569cc601ad04074
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index bcb8f6c..7c4e8bb 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -134,7 +134,7 @@
                         prefixLength,
                         gateway));
 
-    writeConfigurationFile();
+    manager.writeToConfigurationFile();
 }
 
 
@@ -246,7 +246,7 @@
         return;
     }
     this->addrs.erase(it);
-    writeConfigurationFile();
+    manager.writeToConfigurationFile();
 }
 
 void EthernetInterface::deleteVLANObject(const std::string& interface)
@@ -282,9 +282,6 @@
     }
     // delete the interface
     vlanInterfaces.erase(it);
-    // restart the systemd-networkd
-
-    restartSystemdUnit("systemd-networkd.service");
 
     // TODO  systemd doesn't delete the virtual network interface
     // even after deleting all the related configuartion.
@@ -297,6 +294,8 @@
     {
         commit<InternalFailure>();
     }
+
+    manager.writeToConfigurationFile();
 }
 
 std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
@@ -323,7 +322,7 @@
     }
 
     EthernetInterfaceIntf::dHCPEnabled(value);
-    writeConfigurationFile();
+    manager.writeToConfigurationFile();
     return value;
 }
 
@@ -364,19 +363,18 @@
     auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
                         bus,
                         path.c_str(),
-                        EthernetInterfaceIntf::dHCPEnabled(),
+                        false,
                         id,
                         *this,
                         manager);
 
     // write the device file for the vlan interface.
     vlanIntf->writeDeviceFile();
-    vlanIntf->writeConfigurationFile();
 
     this->vlanInterfaces.emplace(vlanInterfaceName,
                                  std::move(vlanIntf));
     // write the new vlan device entry to the configuration(network) file.
-    writeConfigurationFile();
+    manager.writeToConfigurationFile();
 }
 
 // Need to merge the below function with the code which writes the
@@ -391,6 +389,15 @@
     using AddressOrigin =
         sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
     namespace fs = std::experimental::filesystem;
+
+    // if there is vlan interafce then write the configuration file
+    // for vlan also.
+
+    for (const auto& intf: vlanInterfaces)
+    {
+        intf.second->writeConfigurationFile();
+    }
+
     fs::path confPath = manager.getConfDir();
 
     std::string fileName = systemd::config::networkFilePrefix + interfaceName() +
@@ -429,7 +436,6 @@
         // configured as dhcp.
         writeDHCPSection(stream);
         stream.close();
-        restartSystemdUnit("systemd-networkd.service");
         return;
     }
 
@@ -475,7 +481,6 @@
     }
 
     stream.close();
-    restartSystemdUnit("systemd-networkd.service");
 }
 
 void EthernetInterface::writeDHCPSection(std::fstream& stream)
diff --git a/network_manager.cpp b/network_manager.cpp
index ae0cbaf..4525e34 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -3,6 +3,7 @@
 #include "network_manager.hpp"
 #include "network_config.hpp"
 #include "ipaddress.hpp"
+#include "timer.hpp"
 #include "xyz/openbmc_project/Common/error.hpp"
 
 #include <phosphor-logging/log.hpp>
@@ -24,6 +25,7 @@
 namespace network
 {
 
+extern std::unique_ptr<phosphor::network::Timer> refreshTimer;
 using namespace phosphor::logging;
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
@@ -104,9 +106,14 @@
 {
     // creates the ethernet interface dbus object.
     createInterfaces();
-    // create the system conf object.
+
+    systemConf.reset(nullptr);
+    dhcpConf.reset(nullptr);
+
     fs::path objPath = objectPath;
     objPath /= "config";
+
+    // create the system conf object.
     systemConf = std::make_unique<phosphor::network::SystemConfiguration>(
                         bus, objPath.string(), *this);
     // create the dhcp conf object.
@@ -170,12 +177,25 @@
 void Manager::writeToConfigurationFile()
 {
     // write all the static ip address in the systemd-network conf file
-
     for (const auto& intf : interfaces)
     {
         intf.second->writeConfigurationFile();
 
     }
+    restartNetwork();
+}
+
+void Manager::restartNetwork()
+{
+    using namespace std::chrono;
+
+    if (refreshTimer && !refreshTimer->isExpired())
+    {
+        auto time =  duration_cast<microseconds>(
+                        phosphor::network::networkChangeTimeout);
+        refreshTimer->startTimer(time);
+    }
+    restartSystemdUnit("systemd-networkd.service");
 }
 
 }//namespace network
diff --git a/network_manager.hpp b/network_manager.hpp
index 1890565..0d15fc6 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -96,6 +96,9 @@
 
     private:
 
+        /** @brief restart the systemd networkd. */
+        void restartNetwork();
+
         /** @brief Persistent sdbusplus DBus bus connection. */
         sdbusplus::bus::bus& bus;
 
diff --git a/rtnetlink_server.cpp b/rtnetlink_server.cpp
index 8e636a1..91e9947 100644
--- a/rtnetlink_server.cpp
+++ b/rtnetlink_server.cpp
@@ -26,9 +26,6 @@
 namespace rtnetlink
 {
 
-using namespace std::chrono_literals;
-constexpr auto networkChangeTimeout = 1s; //seconds
-
 /* Call Back for the sd event loop */
 static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
                         void* userdata)
diff --git a/test/Makefile.am b/test/Makefile.am
index f1d11d4..024fa25 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -33,6 +33,7 @@
 			$(top_builddir)/ipaddress.o \
 			$(top_builddir)/routing_table.o \
 			$(top_builddir)/util.o \
+			$(top_builddir)/timer.o \
 			$(top_builddir)/system_configuration.o \
 			$(top_builddir)/dhcp_configuration.o \
 			$(top_builddir)/config_parser.o \
diff --git a/test/test_network_manager.cpp b/test/test_network_manager.cpp
index 3e1f0e3..6281081 100644
--- a/test/test_network_manager.cpp
+++ b/test/test_network_manager.cpp
@@ -3,6 +3,7 @@
 
 #include "xyz/openbmc_project/Common/error.hpp"
 #include <phosphor-logging/elog-errors.hpp>
+#include "timer.hpp"
 
 #include <gtest/gtest.h>
 #include <sdbusplus/bus.hpp>
@@ -20,6 +21,7 @@
 namespace network
 {
 
+std::unique_ptr<phosphor::network::Timer> refreshTimer = nullptr;
 namespace fs = std::experimental::filesystem;
 
 class TestNetworkManager : public testing::Test
diff --git a/timer.cpp b/timer.cpp
index 0aaf7d8..afd4b8d 100644
--- a/timer.cpp
+++ b/timer.cpp
@@ -73,6 +73,7 @@
     }
 
     log<level::INFO>("Timer expired");
+    sd_event_source_set_enabled(eventSource, SD_EVENT_OFF);
     return 0;
 }
 
diff --git a/types.hpp b/types.hpp
index 4f07522..f180ece 100644
--- a/types.hpp
+++ b/types.hpp
@@ -8,12 +8,17 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <chrono>
 #include <systemd/sd-event.h>
 
 namespace phosphor
 {
 namespace network
 {
+
+using namespace std::chrono_literals;
+constexpr auto networkChangeTimeout = 1s;
+
 namespace systemd
 {
 namespace config