Implement create interface for ipaddress

Change-Id: Ia4598c27c11667dafb70a8af58871661b7042d0f
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 247ea9b..75c49e6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,8 @@
 noinst_HEADERS = \
 		ethernet_interface.hpp \
 		network_manager.hpp \
-		ipaddress.hpp
+		ipaddress.hpp \
+		types.hpp
 
 phosphor_network_manager_SOURCES = \
 		ethernet_interface.cpp \
@@ -40,7 +41,8 @@
 phosphor_network_manager_LDFLAGS = \
 		$(SYSTEMD_LIBS) \
 		$(SDBUSPLUS_LIBS) \
-		$(PHOSPHOR_DBUS_INTERFACES_LIBS)
+		$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+		-lstdc++fs
 
 phosphor_network_manager_CXXFLAGS = \
 		$(SYSTEMD_CFLAGS) \
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index f4adf28..20b3e31 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -1,7 +1,10 @@
+#include "config.h"
+#include "ipaddress.hpp"
 #include "ethernet_interface.hpp"
 
 #include <phosphor-logging/log.hpp>
 
+#include <arpa/inet.h>
 #include <linux/ethtool.h>
 #include <net/if.h>
 #include <linux/sockios.h>
@@ -10,6 +13,10 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <string>
+#include <algorithm>
+#include <experimental/filesystem>
+
 namespace phosphor
 {
 namespace network
@@ -22,23 +29,72 @@
 
 EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
                                      const std::string& objPath,
-                                     bool dhcpEnabled) :
-    details::EthernetIface(bus, objPath.c_str(), true)
+                                     bool dhcpEnabled,
+                                     const AddrList& addrs) :
+                                     Ifaces(bus, objPath.c_str(), true),
+                                     bus(bus)
 {
     auto intfName = objPath.substr(objPath.rfind("/") + 1);
     interfaceName(intfName);
     dHCPEnabled(dhcpEnabled);
     mACAddress(getMACAddress());
+    std::string gateway;
+
+    IP::Protocol addressType = IP::Protocol::IPv4;
+
+    for (auto addr : addrs)
+    {
+        if (addr.addrType == AF_INET6)
+        {
+            addressType = IP::Protocol::IPv6;
+        }
+
+        std::string ipAddressObjectPath = getAddressObjectPath(addressType);
+        this->addrs.emplace(
+                std::make_pair(
+                        addr.ipaddress,
+                        std::make_unique<phosphor::network::IPAddress>(
+                            bus,
+                            ipAddressObjectPath.c_str(),
+                            *this,
+                            addressType,
+                            addr.ipaddress,
+                            addr.prefix,
+                            gateway)));
+    }
     // Emit deferred signal.
     this->emit_object_added();
 }
 
+void EthernetInterface::iP(IP::Protocol protType,
+                           std::string ipaddress,
+                           uint8_t prefixLength,
+                           std::string gateway)
+{
+
+    IP::Protocol protocolType  = protType;
+    std::string objectPath = getAddressObjectPath(protocolType);
+
+    this->addrs.emplace(
+            std::make_pair(ipaddress,
+                           std::make_unique<phosphor::network::IPAddress>(
+                                bus,
+                                objectPath.c_str(),
+                                *this,
+                                protocolType,
+                                ipaddress,
+                                prefixLength,
+                                gateway)));
+}
+
+
 /*
 Note: We don't have support for  ethtool now
 will enable this code once we bring the ethtool
 in the image.
 TODO: https://github.com/openbmc/openbmc/issues/1484
 */
+
 InterfaceInfo EthernetInterface::getInterfaceInfo() const
 {
     int sock{-1};
@@ -138,9 +194,42 @@
     return macAddress;
 }
 
+size_t EthernetInterface::getAddressCount(IP::Protocol addressType) const
+{
+    size_t count = 0;
+
+    std::for_each(addrs.cbegin(), addrs.cend(),
+                  [&count,addressType](const auto & addr)
+    {
+        if (addr.second->type() == addressType)
+        {
+            count += 1;
+        }
+    });
+
+    return count;
+}
+
 void EthernetInterface::deleteObject(const std::string& ipaddress)
 {
-     //NOTE:- will be implemented in next commit.
+    this->addrs.erase(addrs.find(ipaddress));
+}
+
+std::string EthernetInterface::getAddressObjectPath(IP::Protocol
+                                                    addressType) const
+{
+
+    std::string type = convertForMessage(addressType);
+    type = type.substr(type.rfind('.')+1);
+    std::transform(type.begin(), type.end(), type.begin(), ::tolower);
+
+    std::experimental::filesystem::path objectPath;
+    objectPath /= std::string(OBJ_NETWORK);
+    objectPath /= interfaceName();
+    objectPath /= type;
+    objectPath /= std::to_string(getAddressCount(addressType));
+    return objectPath.string();
+
 }
 
 }//namespace network
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index 71a3003..ab69a78 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -1,6 +1,10 @@
 #pragma once
 
+#include "ipaddress.hpp"
+#include "types.hpp"
+
 #include "xyz/openbmc_project/Network/EthernetInterface/server.hpp"
+#include "xyz/openbmc_project/Network/IP/Create/server.hpp"
 
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/server/object.hpp>
@@ -11,17 +15,14 @@
 {
 namespace network
 {
-namespace details
-{
 
-template <typename T>
-using ServerObject = typename sdbusplus::server::object::object<T>;
+using Ifaces =
+    sdbusplus::server::object::object<
+        sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface,
+        sdbusplus::xyz::openbmc_project::Network::IP::server::Create>;
 
-using EthernetIface =
-    sdbusplus::server::object::object <
-    sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface >;
+using IP = sdbusplus::xyz::openbmc_project::Network::server::IP;
 
-} // namespace details
 
 using LinkSpeed = uint16_t;
 using DuplexMode = uint8_t;
@@ -34,7 +35,7 @@
  *  @details A concrete implementation for the
  *  xyz.openbmc_project.Network.EthernetInterface DBus API.
  */
-class EthernetInterface : public details::EthernetIface
+class EthernetInterface : public Ifaces
 {
     public:
         EthernetInterface() = delete;
@@ -52,7 +53,20 @@
          */
         EthernetInterface(sdbusplus::bus::bus& bus,
                           const std::string& objPath,
-                          bool dhcpEnabled);
+                          bool dhcpEnabled,
+                          const AddrList& addrs);
+
+        /** @brief Function to create ipaddress dbus object.
+         *  @param[in] addressType - Type of ip address.
+         *  @param[in] ipaddress- IP adress.
+         *  @param[in] prefixLength - Length of prefix.
+         *  @param[in] gateway - Gateway ip address.
+         */
+
+        void iP(IP::Protocol addressType,
+                std::string ipaddress,
+                uint8_t prefixLength,
+                std::string gateway) override;
 
         /** @brief delete the dbus object of the given ipaddress.
          */
@@ -74,6 +88,28 @@
 
         std::string getMACAddress() const;
 
+        /** @brief construct the ip address dbus object path.
+         *  @param[in] addressType - Type of ip address.
+         *  @return path of the address object.
+         */
+
+        std::string getAddressObjectPath(IP::Protocol addressType) const;
+
+        /** @brief get the ipadress count for a specific type on this interface.
+         *  @param[in] addressType - Type of ip address.
+         *  @return count of ipaddreses for the incoming type.
+         */
+
+        size_t getAddressCount(IP::Protocol addressType) const;
+
+
+        /** @brief Persistent sdbusplus DBus bus connection. */
+        sdbusplus::bus::bus& bus;
+
+        /** @brief Persistent map of IPAddress dbus objects and their names */
+        std::map<std::string, std::unique_ptr<IPAddress>> addrs;
+
+
 };
 
 } // namespace network
diff --git a/network_manager.cpp b/network_manager.cpp
index 479e8a4..7362943 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -4,7 +4,7 @@
 #include <phosphor-logging/log.hpp>
 
 #include <algorithm>
-
+#include <experimental/filesystem>
 #include <arpa/inet.h>
 #include <dirent.h>
 #include <net/if.h>
@@ -14,34 +14,38 @@
 {
 namespace network
 {
+
 using namespace phosphor::logging;
+namespace fs = std::experimental::filesystem;
 
 Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath):
     details::VLANCreateIface(bus, objPath, true)
 {
-    auto interfaceInfoList = getInterfaceAndaddrs();
+    auto interfaceInfoList = getInterfaceAddrs();
 
     for( const auto& intfInfo : interfaceInfoList )
     {
-        std::string  objectPath = std::string(OBJ_NETWORK) + "/" + intfInfo.first;
+
+        fs::path objectPath = std::string(OBJ_NETWORK);
+        objectPath /= intfInfo.first;
 
         this->interfaces.emplace(std::make_pair(
                                  intfInfo.first,
                                  std::make_unique<
                                  phosphor::network::EthernetInterface >
                                  (bus, objectPath.c_str(),
-                                 false)));
+                                 false,intfInfo.second)));
     }
 }
 
-void Manager::vLAN(details::IntfName interfaceName, uint16_t id)
+void Manager::vLAN(IntfName interfaceName, uint16_t id)
 {
 }
 
-details::IntfAddrMap Manager::getInterfaceAndaddrs() const
+IntfAddrMap Manager::getInterfaceAddrs() const
 {
-    details::IntfAddrMap intfMap;
-    details::AddrList addrList;
+    IntfAddrMap intfMap;
+    AddrList addrList;
     struct ifaddrs* ifaddr;
     // attempt to fill struct with ifaddrs
     if (getifaddrs(&ifaddr) == -1)
@@ -86,28 +90,28 @@
                 addrList.clear();
             }
             intfName = ifa->ifa_name;
-            details::AddrInfo info;
-            char tmp[INET6_ADDRSTRLEN] = { 0 };
+            AddrInfo info;
+            char ip[INET6_ADDRSTRLEN] = { 0 };
 
             if (ifa->ifa_addr->sa_family == AF_INET)
             {
 
                 inet_ntop(ifa->ifa_addr->sa_family,
                           &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr),
-                          tmp,
-                          sizeof(tmp));
+                          ip,
+                          sizeof(ip));
             }
             else
             {
                 inet_ntop(ifa->ifa_addr->sa_family,
                           &(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr),
-                          tmp,
-                          sizeof(tmp));
+                          ip,
+                          sizeof(ip));
 
             }
 
             info.addrType = ifa->ifa_addr->sa_family;
-            info.ipaddress = tmp;
+            info.ipaddress = ip;
             addrList.emplace_back(info);
         }
     }
diff --git a/network_manager.hpp b/network_manager.hpp
index 2e90b23..3d745ce 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "ethernet_interface.hpp"
+#include "types.hpp"
 #include "xyz/openbmc_project/Network/VLAN/Create/server.hpp"
 
 #include <sdbusplus/bus.hpp>
@@ -69,16 +70,16 @@
          */
         Manager(sdbusplus::bus::bus& bus, const char* objPath);
 
-        void vLAN(details::IntfName interfaceName, uint16_t id) override;
+        void vLAN(IntfName interfaceName, uint16_t id) override;
 
     private:
         /** @brief Get all the interfaces from the system.
          *  @returns list of interface names.
          */
-        details::IntfAddrMap getInterfaceAndaddrs() const;
+        IntfAddrMap getInterfaceAddrs() const;
 
         /** @brief Persistent map of EthernetInterface dbus objects and their names */
-        std::map<details::IntfName, std::unique_ptr<EthernetInterface>> interfaces;
+        std::map<IntfName, std::unique_ptr<EthernetInterface>> interfaces;
 
 };
 
diff --git a/types.hpp b/types.hpp
new file mode 100644
index 0000000..28b34d9
--- /dev/null
+++ b/types.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <list>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace phosphor
+{
+namespace network
+{
+
+using IntfName = std::string;
+
+struct AddrInfo {
+    uint8_t addrType;
+    std::string ipaddress;
+    uint16_t prefix;
+};
+
+using AddrList = std::list<AddrInfo>;
+using IntfAddrMap = std::map<IntfName, AddrList>;
+
+
+}//namespace network
+}//namespace phosphor