diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
new file mode 100644
index 0000000..68e6ebb
--- /dev/null
+++ b/redfish-core/lib/ethernet.hpp
@@ -0,0 +1,497 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+
+#include "node.hpp"
+#include <boost/container/flat_map.hpp>
+
+namespace redfish {
+
+/**
+ * DBus types primitives for several generic DBus interfaces
+ * TODO(Pawel) consider move this to separate file into boost::dbus
+ */
+using PropertiesMapType =
+    boost::container::flat_map<std::string, dbus::dbus_variant>;
+
+using GetManagedObjectsType = boost::container::flat_map<
+    dbus::object_path,
+    boost::container::flat_map<std::string, PropertiesMapType>>;
+
+using GetAllPropertiesType = PropertiesMapType;
+
+/**
+ * Structure for keeping IPv4 data required by Redfish
+ * TODO(Pawel) consider change everything to ptr, or to non-ptr values.
+ */
+struct IPv4AddressData {
+  const std::string *address;
+  const std::string *domain;
+  const std::string *gateway;
+  std::string netmask;
+  std::string origin;
+  bool global;
+};
+
+/**
+ * Structure for keeping basic single Ethernet Interface information
+ * available from DBus
+ */
+struct EthernetInterfaceData {
+  const unsigned int *speed;
+  const bool *auto_neg;
+  const std::string *hostname;
+  const std::string *default_gateway;
+  const std::string *mac_address;
+};
+
+/**
+ * OnDemandEthernetProvider
+ * Ethernet provider class that retrieves data directly from dbus, before seting
+ * it into JSON output. This does not cache any data.
+ *
+ * TODO(Pawel)
+ * This perhaps shall be different file, which has to be chosen on compile time
+ * depending on OEM needs
+ */
+class OnDemandEthernetProvider {
+ private:
+  // Consts that may have influence on EthernetProvider performance/memory usage
+  const size_t MAX_IPV4_ADDRESSES_PER_INTERFACE = 10;
+
+  // Helper function that allows to extract GetAllPropertiesType from
+  // GetManagedObjectsType, based on object path, and interface name
+  const PropertiesMapType *extractInterfaceProperties(
+      const dbus::object_path &objpath, const std::string &interface,
+      const GetManagedObjectsType &dbus_data) {
+    const auto &dbus_obj = dbus_data.find(objpath);
+    if (dbus_obj != dbus_data.end()) {
+      const auto &iface = dbus_obj->second.find(interface);
+      if (iface != dbus_obj->second.end()) {
+        return &iface->second;
+      }
+    }
+    return nullptr;
+  }
+
+  // Helper Wrapper that does inline object_path conversion from string
+  // into dbus::object_path type
+  inline const PropertiesMapType *extractInterfaceProperties(
+      const std::string &objpath, const std::string &interface,
+      const GetManagedObjectsType &dbus_data) {
+    const auto &dbus_obj = dbus::object_path{objpath};
+    return extractInterfaceProperties(dbus_obj, interface, dbus_data);
+  }
+
+  // Helper function that allows to get pointer to the property from
+  // GetAllPropertiesType native, or extracted by GetAllPropertiesType
+  template <typename T>
+  inline const T *extractProperty(const PropertiesMapType &properties,
+                                  const std::string &name) {
+    const auto &property = properties.find(name);
+    if (property != properties.end()) {
+      return boost::get<T>(&property->second);
+    }
+    return nullptr;
+  }
+  // TODO(Pawel) Consider to move the above functions to dbus
+  // generic_interfaces.hpp
+
+  // Helper function that extracts data from several dbus objects and several
+  // interfaces required by single ethernet interface instance
+  void extractEthernetInterfaceData(const std::string &ethiface_id,
+                                    const GetManagedObjectsType &dbus_data,
+                                    EthernetInterfaceData &eth_data) {
+    // Extract data that contains MAC Address
+    const PropertiesMapType *mac_properties = extractInterfaceProperties(
+        "/xyz/openbmc_project/network/" + ethiface_id,
+        "xyz.openbmc_project.Network.MACAddress", dbus_data);
+
+    if (mac_properties != nullptr) {
+      eth_data.mac_address =
+          extractProperty<std::string>(*mac_properties, "MACAddress");
+    }
+
+    // Extract data that contains link information (auto negotiation and speed)
+    const PropertiesMapType *eth_properties = extractInterfaceProperties(
+        "/xyz/openbmc_project/network/" + ethiface_id,
+        "xyz.openbmc_project.Network.EthernetInterface", dbus_data);
+
+    if (eth_properties != nullptr) {
+      eth_data.auto_neg = extractProperty<bool>(*eth_properties, "AutoNeg");
+      eth_data.speed = extractProperty<unsigned int>(*eth_properties, "Speed");
+    }
+
+    // Extract data that contains network config (HostName and DefaultGW)
+    const PropertiesMapType *config_properties = extractInterfaceProperties(
+        "/xyz/openbmc_project/network/config",
+        "xyz.openbmc_project.Network.SystemConfiguration", dbus_data);
+
+    if (config_properties != nullptr) {
+      eth_data.hostname =
+          extractProperty<std::string>(*config_properties, "HostName");
+      eth_data.default_gateway =
+          extractProperty<std::string>(*config_properties, "DefaultGateway");
+    }
+  }
+
+  // Helper function that changes bits netmask notation (i.e. /24)
+  // into full dot notation
+  inline std::string getNetmask(unsigned int bits) {
+    uint32_t value = 0xffffffff << (32 - bits);
+    std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
+                          std::to_string((value >> 16) & 0xff) + "." +
+                          std::to_string((value >> 8) & 0xff) + "." +
+                          std::to_string(value & 0xff);
+    return netmask;
+  }
+
+  // Helper function that extracts data for single ethernet ipv4 address
+  void extractIPv4Data(const std::string &ethiface_id,
+                       const GetManagedObjectsType &dbus_data,
+                       std::vector<IPv4AddressData> &ipv4_config) {
+    // Since there might be several IPv4 configurations aligned with
+    // single ethernet interface, loop over all of them
+    for (auto &objpath : dbus_data) {
+      // Check if propper patter for object path appears
+      if (boost::starts_with(
+              objpath.first.value,
+              "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/")) {
+        // and get approrpiate interface
+        const auto &interface =
+            objpath.second.find("xyz.openbmc_project.Network.IP");
+        if (interface != objpath.second.end()) {
+          // Make a properties 'shortcut', to make everything more readable
+          const PropertiesMapType &properties = interface->second;
+          // Instance IPv4AddressData structure, and set as appropriate
+          IPv4AddressData ipv4_address;
+          // IPv4 address
+          ipv4_address.address =
+              extractProperty<std::string>(properties, "Address");
+          // IPv4 gateway
+          ipv4_address.gateway =
+              extractProperty<std::string>(properties, "Gateway");
+
+          // Origin is kind of DBus object so fetch pointer...
+          const std::string *origin =
+              extractProperty<std::string>(properties, "Origin");
+          if (origin != nullptr) {
+            // ... and get everything after last dot
+            int last = origin->rfind(".");
+            if (last != std::string::npos) {
+              ipv4_address.origin = origin->substr(last + 1);
+            }
+          }
+
+          // Netmask is presented as PrefixLength
+          const auto *mask =
+              extractProperty<uint8_t>(properties, "PrefixLength");
+          if (mask != nullptr) {
+            // convert it to the string
+            ipv4_address.netmask = getNetmask(*mask);
+          }
+
+          // Attach IPv4 only if address is present
+          if (ipv4_address.address != nullptr) {
+            // Check if given addres is local, or global
+            if (boost::starts_with(*ipv4_address.address, "169.254")) {
+              ipv4_address.global = false;
+            } else {
+              ipv4_address.global = true;
+            }
+            ipv4_config.emplace_back(std::move(ipv4_address));
+          }
+        }
+      }
+    }
+  }
+
+ public:
+  /**
+   * Function that retrieves all properties for given Ethernet Interface Object
+   * from EntityManager Network Manager
+   * @param ethiface_id a eth interface id to query on DBus
+   * @param callback a function that shall be called to convert Dbus output into
+   * JSON
+   */
+  template <typename CallbackFunc>
+  void getEthernetIfaceData(const std::string &ethiface_id,
+                            CallbackFunc &&callback) {
+    crow::connections::system_bus->async_method_call(
+        [
+          this, ethiface_id{std::move(ethiface_id)},
+          callback{std::move(callback)}
+        ](const boost::system::error_code error_code,
+          const GetManagedObjectsType &resp) {
+
+          EthernetInterfaceData eth_data;
+          std::vector<IPv4AddressData> ipv4_data;
+          ipv4_data.reserve(MAX_IPV4_ADDRESSES_PER_INTERFACE);
+
+          if (error_code) {
+            // Something wrong on DBus, the error_code is not important at this
+            // moment, just return success=false, and empty output. Since size
+            // of vector may vary depending on information from Network Manager,
+            // and empty output could not be treated same way as error.
+            callback(false, eth_data, ipv4_data);
+            return;
+          }
+
+          extractEthernetInterfaceData(ethiface_id, resp, eth_data);
+          extractIPv4Data(ethiface_id, resp, ipv4_data);
+
+          // Fix global GW
+          for (IPv4AddressData &ipv4 : ipv4_data) {
+            if ((ipv4.global) &&
+                ((ipv4.gateway == nullptr) || (*ipv4.gateway == "0.0.0.0"))) {
+              ipv4.gateway = eth_data.default_gateway;
+            }
+          }
+
+          // Finally make a callback with usefull data
+          callback(true, eth_data, ipv4_data);
+        },
+        {"xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
+         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"});
+  };
+
+  /**
+   * Function that retrieves all Ethernet Interfaces available through Network
+   * Manager
+   * @param callback a function that shall be called to convert Dbus output into
+   * JSON.
+   */
+  template <typename CallbackFunc>
+  void getEthernetIfaceList(CallbackFunc &&callback) {
+    crow::connections::system_bus->async_method_call(
+        [ this, callback{std::move(callback)} ](
+            const boost::system::error_code error_code,
+            const GetManagedObjectsType &resp) {
+          // Callback requires vector<string> to retrieve all available ethernet
+          // interfaces
+          std::vector<std::string> iface_list;
+          iface_list.reserve(resp.size());
+          if (error_code) {
+            // Something wrong on DBus, the error_code is not important at this
+            // moment, just return success=false, and empty output. Since size
+            // of vector may vary depending on information from Network Manager,
+            // and empty output could not be treated same way as error.
+            callback(false, iface_list);
+            return;
+          }
+
+          // Iterate over all retrieved ObjectPaths.
+          for (auto &objpath : resp) {
+            // And all interfaces available for certain ObjectPath.
+            for (auto &interface : objpath.second) {
+              // If interface is xyz.openbmc_project.Network.EthernetInterface,
+              // this is what we're looking for.
+              if (interface.first ==
+                  "xyz.openbmc_project.Network.EthernetInterface") {
+                // Cut out everyting until last "/", ...
+                const std::string &iface_id = objpath.first.value;
+                std::size_t last_pos = iface_id.rfind("/");
+                if (last_pos != std::string::npos) {
+                  // and put it into output vector.
+                  iface_list.emplace_back(iface_id.substr(last_pos + 1));
+                }
+              }
+            }
+          }
+          // Finally make a callback with usefull data
+          callback(true, iface_list);
+        },
+        {"xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
+         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"});
+  };
+};
+
+/**
+ * EthernetCollection derived class for delivering Ethernet Collection Schema
+ */
+class EthernetCollection : public Node {
+ public:
+  template <typename CrowApp>
+  // TODO(Pawel) Remove line from below, where we assume that there is only one
+  // manager called openbmc This shall be generic, but requires to update
+  // GetSubroutes method
+  EthernetCollection(CrowApp &app)
+      : Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/") {
+    Node::json["@odata.type"] =
+        "#EthernetInterfaceCollection.EthernetInterfaceCollection";
+    Node::json["@odata.context"] =
+        "/redfish/v1/"
+        "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection";
+    Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc/EthernetInterfaces";
+    Node::json["Name"] = "Ethernet Network Interface Collection";
+    Node::json["Description"] =
+        "Collection of EthernetInterfaces for this Manager";
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}};
+  }
+
+ private:
+  /**
+   * Functions triggers appropriate requests on DBus
+   */
+  void doGet(crow::response &res, const crow::request &req,
+             const std::vector<std::string> &params) override {
+    // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces for
+    // any Manager, not only hardcoded 'openbmc'.
+    std::string manager_id = "openbmc";
+
+    // Get eth interface list, and call the below callback for JSON preparation
+    ethernet_provider.getEthernetIfaceList(
+        [&, manager_id{std::move(manager_id)} ](
+            const bool &success, const std::vector<std::string> &iface_list) {
+          if (success) {
+            nlohmann::json iface_array = nlohmann::json::array();
+            for (const std::string &iface_item : iface_list) {
+              iface_array.push_back(
+                  {{"@odata.id", "/redfish/v1/Managers/" + manager_id +
+                                     "/EthernetInterfaces/" + iface_item}});
+            }
+            Node::json["Members"] = iface_array;
+            Node::json["Members@odata.count"] = iface_array.size();
+            Node::json["@odata.id"] =
+                "/redfish/v1/Managers/" + manager_id + "/EthernetInterfaces";
+            res.json_value = Node::json;
+          } else {
+            // No success, best what we can do is return INTERNALL ERROR
+            res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR);
+          }
+          res.end();
+        });
+  }
+
+  // Ethernet Provider object
+  // TODO(Pawel) consider move it to singleton
+  OnDemandEthernetProvider ethernet_provider;
+};
+
+/**
+ * EthernetInterface derived class for delivering Ethernet Schema
+ */
+class EthernetInterface : public Node {
+ public:
+  /*
+   * Default Constructor
+   */
+  template <typename CrowApp>
+  // TODO(Pawel) Remove line from below, where we assume that there is only one
+  // manager called openbmc This shall be generic, but requires to update
+  // GetSubroutes method
+  EthernetInterface(CrowApp &app)
+      : Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/<str>/",
+             std::string()) {
+    Node::json["@odata.type"] = "#EthernetInterface.v1_2_0.EthernetInterface";
+    Node::json["@odata.context"] =
+        "/redfish/v1/$metadata#EthernetInterface.EthernetInterface";
+    Node::json["Name"] = "Manager Ethernet Interface";
+    Node::json["Description"] = "Management Network Interface";
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}};
+  }
+
+ private:
+  /**
+   * Functions triggers appropriate requests on DBus
+   */
+  void doGet(crow::response &res, const crow::request &req,
+             const std::vector<std::string> &params) override {
+    // TODO(Pawel) this shall be parametrized call (two params) to get
+    // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
+    // Check if there is required param, truly entering this shall be
+    // impossible.
+    if (params.size() != 1) {
+      res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR);
+      res.end();
+      return;
+    }
+
+    const std::string &iface_id = params[0];
+
+    // Get single eth interface data, and call the below callback for JSON
+    // preparation
+    ethernet_provider.getEthernetIfaceData(
+        iface_id, [&, iface_id](const bool &success,
+                                const EthernetInterfaceData &eth_data,
+                                const std::vector<IPv4AddressData> &ipv4_data) {
+          if (success) {
+            // Copy JSON object to avoid race condition
+            nlohmann::json json_response(Node::json);
+
+            // Fill out obvious data...
+            json_response["Id"] = iface_id;
+            json_response["@odata.id"] =
+                "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + iface_id;
+
+            // ... then the one from DBus, regarding eth iface...
+            if (eth_data.speed != nullptr)
+              json_response["SpeedMbps"] = *eth_data.speed;
+
+            if (eth_data.mac_address != nullptr)
+              json_response["MACAddress"] = *eth_data.mac_address;
+
+            if (eth_data.hostname != nullptr)
+              json_response["HostName"] = *eth_data.hostname;
+
+            // ... at last, check if there are IPv4 data and prepare appropriate
+            // collection
+            if (ipv4_data.size() > 0) {
+              nlohmann::json ipv4_array = nlohmann::json::array();
+              for (auto &ipv4_config : ipv4_data) {
+                nlohmann::json json_ipv4;
+                if (ipv4_config.address != nullptr) {
+                  json_ipv4["Address"] = *ipv4_config.address;
+                  if (ipv4_config.gateway != nullptr)
+                    json_ipv4["Gateway"] = *ipv4_config.gateway;
+
+                  json_ipv4["AddressOrigin"] = ipv4_config.origin;
+                  json_ipv4["SubnetMask"] = ipv4_config.netmask;
+
+                  ipv4_array.push_back(json_ipv4);
+                }
+              }
+              json_response["IPv4Addresses"] = ipv4_array;
+            }
+            res.json_value = std::move(json_response);
+          } else {
+            // ... otherwise return error
+            // TODO(Pawel)consider distinguish between non existing object, and
+            // other errors
+            res.code = static_cast<int>(HttpRespCode::NOT_FOUND);
+          }
+          res.end();
+        });
+  }
+
+  // Ethernet Provider object
+  // TODO(Pawel) consider move it to singleton
+  OnDemandEthernetProvider ethernet_provider;
+};
+
+}  // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 7032a20..0ad768f 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -34,6 +34,14 @@
             .system_uuid;
     Node::json["Model"] = "OpenBmc";               // TODO(ed), get model
     Node::json["FirmwareVersion"] = "1234456789";  // TODO(ed), get fwversion
+    Node::json["EthernetInterfaces"] = nlohmann::json(
+        {{"@odata.id",
+          "/redfish/v1/Managers/openbmc/EthernetInterfaces"}});  // TODO(Pawel),
+                                                                 // remove this
+                                                                 // when
+                                                                 // subroutes
+                                                                 // will work
+                                                                 // correctly
 
     entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
                         {crow::HTTPMethod::HEAD, {{"Login"}}},
