Implement the Vlan Interface

Change-Id: I6085868ba4e30bb9e1c6f6d9895a40ebff82804f
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 4c7ab37..8135e16 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,8 @@
 		routing_table.hpp \
 		config_parser.hpp \
 		system_configuration.hpp \
-		dhcp_configuration.hpp
+		dhcp_configuration.hpp \
+        vlan_interface.hpp
 
 phosphor_network_manager_SOURCES = \
 		ethernet_interface.cpp \
@@ -34,7 +35,8 @@
 		util.cpp \
 		routing_table.cpp \
 		config_parser.cpp \
-		dhcp_configuration.cpp
+		dhcp_configuration.cpp \
+        vlan_interface.cpp
 
 CLEANFILES = \
 		xyz/openbmc_project/Network/VLAN/Create/server.cpp \
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index 14ccc6c..d7648a2 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -33,7 +33,8 @@
 EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
                                      const std::string& objPath,
                                      bool dhcpEnabled,
-                                     Manager& parent) :
+                                     Manager& parent,
+                                     bool emitSignal) :
                                      Ifaces(bus, objPath.c_str(), true),
                                      bus(bus),
                                      manager(parent),
@@ -45,7 +46,10 @@
     mACAddress(getMACAddress());
     createIPAddressObjects();
     // Emit deferred signal.
-    this->emit_object_added();
+    if (emitSignal)
+    {
+        this->emit_object_added();
+    }
 }
 
 void EthernetInterface::createIPAddressObjects()
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index 88200f8..88cbf1e 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -59,11 +59,14 @@
          *  @param[in] objPath - Path to attach at.
          *  @param[in] dhcpEnabled - is dhcp enabled(true/false).
          *  @param[in] parent - parent object.
+         *  @param[in] emitSignal - true if the object added signal needs to be
+         *                          send.
          */
         EthernetInterface(sdbusplus::bus::bus& bus,
                           const std::string& objPath,
                           bool dhcpEnabled,
-                          Manager& parent);
+                          Manager& parent,
+                          bool emitSignal = true);
 
         /** @brief Function to create ipaddress dbus object.
          *  @param[in] addressType - Type of ip address.
@@ -98,7 +101,7 @@
 
         using EthernetInterfaceIntf::dHCPEnabled;
 
-    private:
+    protected:
 
         /** @brief get the info of the ethernet interface.
          *  @return tuple having the link speed,autonegotiation,duplexmode .
diff --git a/test/Makefile.am b/test/Makefile.am
index 5903ee0..35f49db 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,5 +35,6 @@
 			$(top_builddir)/system_configuration.o \
 			$(top_builddir)/dhcp_configuration.o \
 			$(top_builddir)/config_parser.o \
+			$(top_builddir)/vlan_interface.o \
 			$(top_builddir)/xyz/openbmc_project/Network/VLAN/Create/phosphor_network_manager-server.o \
 			$(top_builddir)/xyz/openbmc_project/Network/IP/Create/phosphor_network_manager-server.o
diff --git a/vlan_interface.cpp b/vlan_interface.cpp
new file mode 100644
index 0000000..f4224d4
--- /dev/null
+++ b/vlan_interface.cpp
@@ -0,0 +1,68 @@
+#include "config.h"
+#include "ethernet_interface.hpp"
+#include "vlan_interface.hpp"
+#include "network_manager.hpp"
+
+#include <phosphor-logging/log.hpp>
+#include "xyz/openbmc_project/Common/error.hpp"
+#include <phosphor-logging/elog-errors.hpp>
+
+#include <string>
+#include <algorithm>
+#include <fstream>
+#include <experimental/filesystem>
+
+namespace phosphor
+{
+namespace network
+{
+
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
+VlanInterface::VlanInterface(sdbusplus::bus::bus& bus,
+                             const std::string& objPath,
+                             bool dhcpEnabled,
+                             uint32_t vlanID,
+                             EthernetInterface& intf,
+                             Manager& parent ) :
+        VlanIntfObject(bus, objPath.c_str(), true),
+        EthernetInterface(bus, objPath, dhcpEnabled, parent, false),
+        parentInterface(intf)
+{
+    id(vlanID);
+    VlanIface::interfaceName(EthernetInterface::interfaceName());
+
+    VlanIntfObject::emit_object_added();
+}
+
+void VlanInterface::writeDeviceFile()
+{
+    using namespace std::string_literals;
+    fs::path confPath = manager.getConfDir();
+    std::string fileName = EthernetInterface::interfaceName() + ".netdev"s;
+    confPath /= fileName;
+    std::fstream stream;
+    try
+    {
+        stream.open(confPath.c_str(), std::fstream::out);
+    }
+    catch (std::ios_base::failure& e)
+    {
+        log<level::ERR>("Unable to open the VLAN device file",
+                         entry("FILE=%s", confPath.c_str()),
+                         entry("ERROR=%s", e.what()));
+        elog<InternalFailure>();
+
+    }
+
+    stream << "[" << "NetDev" << "]\n";
+    stream << "Name=" << EthernetInterface::interfaceName() << "\n";
+    stream << "Kind=vlan" << "\n";
+    stream << "[VLAN]" << "\n";
+    stream << "Id=" << id() << "\n";
+    stream.close();
+}
+
+}//namespace network
+}//namespace phosphor
diff --git a/vlan_interface.hpp b/vlan_interface.hpp
new file mode 100644
index 0000000..7f8d043
--- /dev/null
+++ b/vlan_interface.hpp
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "types.hpp"
+
+#include "xyz/openbmc_project/Object/Delete/server.hpp"
+#include "xyz/openbmc_project/Network/VLAN/server.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+
+#include <string>
+#include "ethernet_interface.hpp"
+
+namespace phosphor
+{
+namespace network
+{
+
+class EthernetInterface;
+class Manager;
+
+
+using VlanIface = sdbusplus::xyz::openbmc_project::Network::server::VLAN;
+using VlanIntfObject =  sdbusplus::server::object::object<VlanIface>;
+
+/** @class VlanInterface
+ *  @brief OpenBMC vlan Interface implementation.
+ *  @details A concrete implementation for the vlan interface
+ */
+class VlanInterface : public VlanIntfObject, public EthernetInterface
+{
+    public:
+        VlanInterface() = delete;
+        VlanInterface(const VlanInterface&) = delete;
+        VlanInterface& operator=(const VlanInterface&) = delete;
+        VlanInterface(VlanInterface&&) = delete;
+        VlanInterface& operator=(VlanInterface&&) = delete;
+        virtual ~VlanInterface() = default;
+
+        /** @brief Constructor to put object onto bus at a dbus path.
+         *  @param[in] bus - Bus to attach to.
+         *  @param[in] objPath - Path to attach at.
+         *  @param[in] dhcpEnabled - DHCP enable value.
+         *  @param[in] vlanID - vlan identifier.
+         *  @param[in] intf - ethernet interface object.
+         *  @param[in] manager - network manager object.
+         */
+        VlanInterface(sdbusplus::bus::bus& bus,
+                      const std::string& objPath,
+                      bool dhcpEnabled,
+                      uint32_t vlanID,
+                      EthernetInterface& intf,
+                      Manager& manager);
+
+        /** @brief writes the device configuration.
+                   systemd reads this configuration file
+                   and creates the vlan interface.*/
+        void writeDeviceFile();
+
+    private:
+
+        /** @brief VLAN Identifier. */
+        using VlanIface::id;
+
+        EthernetInterface& parentInterface;
+
+        friend class TestVlanInterface;
+};
+
+} // namespace network
+} // namespace phosphor