Create the VLAN Interface Object

Change-Id: I118fc4bbcad2a478a8aad976e0619537780c1227
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index d7648a2..ef7b9df 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -1,6 +1,7 @@
 #include "config.h"
 #include "ipaddress.hpp"
 #include "ethernet_interface.hpp"
+#include "vlan_interface.hpp"
 #include "network_manager.hpp"
 #include "routing_table.hpp"
 
@@ -36,15 +37,17 @@
                                      Manager& parent,
                                      bool emitSignal) :
                                      Ifaces(bus, objPath.c_str(), true),
+                                     confDir(NETWORK_CONF_DIR),
                                      bus(bus),
                                      manager(parent),
                                      objPath(objPath)
 {
     auto intfName = objPath.substr(objPath.rfind("/") + 1);
+    std::replace(intfName.begin(), intfName.end(), '_', '.');
     interfaceName(intfName);
     dHCPEnabled(dhcpEnabled);
     mACAddress(getMACAddress());
-    createIPAddressObjects();
+
     // Emit deferred signal.
     if (emitSignal)
     {
@@ -58,9 +61,11 @@
     addrs.clear();
 
     auto addrs = getInterfaceAddrs()[interfaceName()];
+
     IP::Protocol addressType = IP::Protocol::IPv4;
     IP::AddressOrigin origin = IP::AddressOrigin::Static;
     route::Table routingTable;
+
     for (auto& addr : addrs)
     {
         if (addr.addrType == AF_INET6)
@@ -284,8 +289,13 @@
 
 bool EthernetInterface::dHCPEnabled(bool value)
 {
+    if (value == EthernetInterfaceIntf::dHCPEnabled())
+    {
+        return value;
+    }
+
     EthernetInterfaceIntf::dHCPEnabled(value);
-    if (value == true)
+    if (value)
     {
         manager.writeToConfigurationFile();
         createIPAddressObjects();
@@ -293,5 +303,30 @@
     return value;
 }
 
+void EthernetInterface::createVLAN(VlanId id)
+{
+    std::string vlanInterfaceName = interfaceName() + "." +
+                                    std::to_string(id);
+    std::string path = objPath;
+    path += "_" + std::to_string(id);
+
+
+    auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
+                        bus,
+                        path.c_str(),
+                        EthernetInterfaceIntf::dHCPEnabled(),
+                        id,
+                        *this,
+                        manager);
+
+    // write the device file for the vlan interface.
+    vlanIntf->writeDeviceFile();
+
+    this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
+                                 std::move(vlanIntf));
+    // write the new vlan device entry to the configuration(network) file.
+    manager.writeToConfigurationFile();
+
+}
 }//namespace network
 }//namespace phosphor
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index 88cbf1e..0ab849c 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -1,6 +1,5 @@
 #pragma once
 
-#include "ipaddress.hpp"
 #include "types.hpp"
 #include "util.hpp"
 
@@ -12,6 +11,7 @@
 #include <sdbusplus/server/object.hpp>
 
 #include <string>
+#include <experimental/filesystem>
 
 namespace phosphor
 {
@@ -29,15 +29,24 @@
 using EthernetInterfaceIntf =
     sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
 
+namespace fs = std::experimental::filesystem;
+
 class Manager; // forward declaration of network manager.
 
 class TestEthernetInterface;
 
+class VlanInterface;
+
+class IPAddress;
+
 using LinkSpeed = uint16_t;
 using DuplexMode = uint8_t;
 using Autoneg = uint8_t;
+using VlanId = uint32_t;
+using InterfaceName = std::string;
 using InterfaceInfo = std::tuple<LinkSpeed, DuplexMode, Autoneg>;
 using AddressMap = std::map<std::string, std::shared_ptr<IPAddress>>;
+using VlanInterfaceMap = std::map<InterfaceName, std::unique_ptr<VlanInterface>>;
 
 /** @class EthernetInterface
  *  @brief OpenBMC Ethernet Interface implementation.
@@ -99,7 +108,16 @@
         /** Set value of DHCPEnabled */
         bool dHCPEnabled(bool value) override;
 
+        /** @brief create Vlan interface.
+         *  @param[in] id- VLAN identifier.
+         */
+        void createVLAN(VlanId id);
+
         using EthernetInterfaceIntf::dHCPEnabled;
+        using EthernetInterfaceIntf::interfaceName;
+
+        /** @brief Network Configuration directory. */
+        fs::path confDir;
 
     protected:
 
@@ -150,6 +168,9 @@
         /** @brief Persistent map of IPAddress dbus objects and their names */
         AddressMap addrs;
 
+        /** @brief Persistent map of VLAN interface dbus objects and their names */
+        VlanInterfaceMap vlanInterfaces;
+
         /** @brief Dbus object path */
         std::string objPath;
 
diff --git a/network_manager.cpp b/network_manager.cpp
index cdbaf45..24f3568 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -3,6 +3,7 @@
 #include "util.hpp"
 #include "network_manager.hpp"
 #include "network_config.hpp"
+#include "ipaddress.hpp"
 #include "xyz/openbmc_project/Common/error.hpp"
 
 #include <phosphor-logging/log.hpp>
@@ -98,6 +99,9 @@
 
 void Manager::vLAN(IntfName interfaceName, uint32_t id)
 {
+   auto& intf = interfaces[interfaceName];
+   intf->createVLAN(id);
+   writeToConfigurationFile();
 }
 
 void Manager::reset()
@@ -207,6 +211,7 @@
 
             }
         }
+
         stream << "Gateway=" << systemConf->defaultGateway() << "\n";
         // write the route section
         stream << "[" << "Route" << "]\n";
@@ -225,7 +230,6 @@
                     destination != "0.0.0.0" &&
                     destination != "")
                 {
-
                     stream << "Gateway=" << addr.second->gateway() << "\n";
                     stream << "Destination=" << destination << "\n";
                 }
diff --git a/network_manager.hpp b/network_manager.hpp
index db4db0f..df98104 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -3,6 +3,8 @@
 #include "ethernet_interface.hpp"
 #include "system_configuration.hpp"
 #include "dhcp_configuration.hpp"
+#include "vlan_interface.hpp"
+
 #include <xyz/openbmc_project/Network/VLAN/Create/server.hpp>
 #include <xyz/openbmc_project/Common/FactoryReset/server.hpp>
 #include <sdbusplus/bus.hpp>
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index 67a25df..8d1913e 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -1,5 +1,6 @@
 #include "network_manager.hpp"
 #include "mock_syscall.hpp"
+#include "ipaddress.hpp"
 
 #include <gtest/gtest.h>
 #include <sdbusplus/bus.hpp>
diff --git a/vlan_interface.hpp b/vlan_interface.hpp
index 7f8d043..c308611 100644
--- a/vlan_interface.hpp
+++ b/vlan_interface.hpp
@@ -2,6 +2,7 @@
 
 #include "types.hpp"
 
+#include "ethernet_interface.hpp"
 #include "xyz/openbmc_project/Object/Delete/server.hpp"
 #include "xyz/openbmc_project/Network/VLAN/server.hpp"
 
@@ -9,7 +10,6 @@
 #include <sdbusplus/server/object.hpp>
 
 #include <string>
-#include "ethernet_interface.hpp"
 
 namespace phosphor
 {