summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-network/network
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-network/network')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb25
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch410
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0004-Fix-for-updating-MAC-address-from-RedFish.patch109
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0005-Added-debug-logs-to-isolate-the-coredump-issue-of-RT.patch261
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check161
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service11
10 files changed, 1091 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb
new file mode 100644
index 000000000..cdb8e2097
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb
@@ -0,0 +1,25 @@
+SUMMARY = "Check for host in reset to disable the NCSI iface"
+DESCRIPTION = "If the host is in reset, the NCSI NIC will not be \
+ available, so this will manually disable the NIC"
+
+FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:"
+
+PV = "1.0"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI = "\
+ file://check-for-host-in-reset \
+ file://${BPN}.service \
+ "
+
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE:${PN} += "${BPN}.service"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/check-for-host-in-reset ${D}/${bindir}/check-for-host-in-reset
+
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset
new file mode 100755
index 000000000..aa17aebf2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+# PFR Boot Time Detection
+#
+# The Platform Firmware Recovery system is designed to confirm the server is
+# running valid images. The server boot process is controlled with a
+# programmable device. The programmable device prevents the system, and the
+# BMC from booting until after it has confirmed the firmware images match a
+# known checksum. Two reset controls are asserted while the checksum
+# calculation is being performed. One prevents the BMC from booting, the other
+# (RSMRST_N) prevents the main processors from leaving reset.
+#
+# If the BMC FW checksum is correct the BMC is allowed to boot.
+# If the BIOS checksum fails the BIOS is not allowed to boot.
+# In this condition the BMC will boot believing the NCSI NIC is functional.
+# This will not be the case when RMSRST_N is asserted. The BIOS will not
+# configure the shared NIC. The BMC will not be able to send or receive
+# network traffic via the shared NIC. This becomes a problem depending on how
+# the NCSI channel is configured.
+#
+# When the NCSI channel is configured using DHCP the BMC is unable to
+# communicate to a DHCP server. Unable to acquire a valid IP state, the NCSI
+# NIC is left DOWN.
+# The problem that occurs is when the NIC is configured with a static
+# address. The BMC is unable to determine the configuration state of the NCSI
+# NIC, and behaves as if everything is working. The problem is the network
+# routing table will, in most cases, be left in a state that prevents traffic
+# from being sent/received from the dedicated NIC. This prevents network
+# access to the BMC, which in turn leaves the system unrecoverable.
+#
+# The purpose of this script is to check for the assertion of the RSMRST_N
+# control at BMC boot time. It will perform this test once. In the event the
+# RSMRST_N is found to be asserted, the BMC will take the NCSI NIC down. No
+# logic for detecting the deassertion will be performed. Once the new image
+# for the BIOS has been transferred, and the checksum confirmed, the BMC will
+# be reset by the programmable device. The programmable device will confirm
+# the checksums, and release both the BMC and the BIOS to boot normally.
+#
+# Flow:
+# The service will be a one-shot that waits for the network.target, as is done
+# by BMCWeb.
+# During a normal boot the RSMRST_N will not be asserted, and this script will
+# not perform an action.
+# When RSMRST_N is asserted the NCSI channel will be given a link down
+# command. This regardless of static or DHCP configuration mode.
+
+GPIOFIND=/usr/bin/gpiofind
+GPIOGET=/usr/bin/gpioget
+RSMRST="RSMRST_N"
+
+# Read the assertion state from the RSMRST_N input
+function get_rsmrst_state {
+ local __resultVal=$1
+ local gpio_state=$($GPIOGET $($GPIOFIND "$RSMRST"))
+ eval $__resultVal="'$gpio_state'"
+ return 0
+}
+
+get_rsmrst_state rsmrst_val
+
+if [ "$rsmrst_val" -eq 0 ]
+then
+ echo "RSMRST_N is asserted, take eth1 down"
+ ip link set down dev eth1
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service
new file mode 100644
index 000000000..19554c94d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Check for host in reset
+After=multi-user.target
+
+[Service]
+Type=oneshot
+Restart=no
+ExecStart=/usr/bin/check-for-host-in-reset
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch
new file mode 100644
index 000000000..2cfa380ef
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch
@@ -0,0 +1,410 @@
+From 29c6b0a294e2c32c9617d243d71d202e926262d0 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Thu, 2 Apr 2020 17:06:07 +0530
+Subject: [PATCH] Adding channel specific privilege to network
+
+ - Adding the channel access information to the network
+ interface object. This privilege will be used in
+ channel specific authorization.
+ - Get supported priv from user manager service dynamically.
+ - Signal handling for capturing the supported priv list
+ changes from user managerment.
+
+Tested-by:
+Verified channel access through ipmitool get/set channel
+access command
+
+Change-Id: I3b592a19363eef684e31d5f7c34dad8f2f9211df
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
+---
+ src/ethernet_interface.cpp | 124 +++++++++++++++++++++++++++++++++++++
+ src/ethernet_interface.hpp | 36 ++++++++++-
+ src/network_manager.cpp | 102 ++++++++++++++++++++++++++++++
+ src/network_manager.hpp | 9 +++
+ 4 files changed, 270 insertions(+), 1 deletion(-)
+
+diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
+index 5ce4349..4c52fc8 100644
+--- a/src/ethernet_interface.cpp
++++ b/src/ethernet_interface.cpp
+@@ -49,6 +49,10 @@ constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
+ constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
+ constexpr auto METHOD_GET = "Get";
+
++static constexpr const char* networkChannelCfgFile =
++ "/var/channel_intf_data.json";
++static constexpr const char* defaultChannelPriv = "priv-admin";
++
+ struct EthernetIntfSocket
+ {
+ EthernetIntfSocket(int domain, int type, int protocol)
+@@ -133,6 +137,7 @@ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
+ EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
+ #endif
++ getChannelPrivilege(intfName);
+
+ // Emit deferred signal.
+ if (emitSignal)
+@@ -1248,5 +1253,124 @@ std::string EthernetInterface::defaultGateway6(std::string gateway)
+ manager.writeToConfigurationFile();
+ return gw;
+ }
++
++nlohmann::json EthernetInterface::readJsonFile(const std::string& configFile)
++{
++ std::ifstream jsonFile(configFile);
++ if (!jsonFile.good())
++ {
++ log<level::ERR>("JSON file not found");
++ return nullptr;
++ }
++
++ nlohmann::json data = nullptr;
++ try
++ {
++ data = nlohmann::json::parse(jsonFile, nullptr, false);
++ }
++ catch (nlohmann::json::parse_error& e)
++ {
++ log<level::DEBUG>("Corrupted channel config.",
++ entry("MSG: %s", e.what()));
++ throw std::runtime_error("Corrupted channel config file");
++ }
++
++ return data;
++}
++
++int EthernetInterface::writeJsonFile(const std::string& configFile,
++ const nlohmann::json& jsonData)
++{
++ std::ofstream jsonFile(configFile);
++ if (!jsonFile.good())
++ {
++ log<level::ERR>("JSON file open failed",
++ entry("FILE=%s", networkChannelCfgFile));
++ return -1;
++ }
++
++ // Write JSON to file
++ jsonFile << jsonData;
++
++ jsonFile.flush();
++ return 0;
++}
++
++std::string
++ EthernetInterface::getChannelPrivilege(const std::string& interfaceName)
++{
++ std::string priv(defaultChannelPriv);
++ std::string retPriv;
++
++ nlohmann::json jsonData = readJsonFile(networkChannelCfgFile);
++ if (jsonData != nullptr)
++ {
++ try
++ {
++ priv = jsonData[interfaceName].get<std::string>();
++ retPriv = ChannelAccessIntf::maxPrivilege(std::move(priv));
++ return retPriv;
++ }
++ catch (const nlohmann::json::exception& e)
++ {
++ jsonData[interfaceName] = priv;
++ }
++ }
++ else
++ {
++ jsonData[interfaceName] = priv;
++ }
++
++ if (writeJsonFile(networkChannelCfgFile, jsonData) != 0)
++ {
++ log<level::DEBUG>("Error in write JSON data to file",
++ entry("FILE=%s", networkChannelCfgFile));
++ elog<InternalFailure>();
++ }
++
++ retPriv = ChannelAccessIntf::maxPrivilege(std::move(priv));
++
++ return retPriv;
++}
++
++std::string EthernetInterface::maxPrivilege(std::string priv)
++{
++ std::string intfName = interfaceName();
++
++ if (manager.supportedPrivList.empty())
++ {
++ // Populate the supported privilege list
++ manager.initSupportedPrivilges();
++ }
++
++ if (!priv.empty() && (std::find(manager.supportedPrivList.begin(),
++ manager.supportedPrivList.end(),
++ priv) == manager.supportedPrivList.end()))
++ {
++ log<level::ERR>("Invalid privilege");
++ elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege"),
++ Argument::ARGUMENT_VALUE(priv.c_str()));
++ }
++
++ if (ChannelAccessIntf::maxPrivilege() == priv)
++ {
++ // No change in privilege so just return.
++ return priv;
++ }
++
++ nlohmann::json jsonData = readJsonFile(networkChannelCfgFile);
++ jsonData[intfName] = priv;
++
++ if (writeJsonFile(networkChannelCfgFile, jsonData) != 0)
++ {
++ log<level::DEBUG>("Error in write JSON data to file",
++ entry("FILE=%s", networkChannelCfgFile));
++ elog<InternalFailure>();
++ }
++
++ // Property change signal will be sent
++ return ChannelAccessIntf::maxPrivilege(std::move(priv));
++}
++
+ } // namespace network
+ } // namespace phosphor
+diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
+index 12d307f..d764b2b 100644
+--- a/src/ethernet_interface.hpp
++++ b/src/ethernet_interface.hpp
+@@ -2,11 +2,14 @@
+
+ #include "types.hpp"
+ #include "util.hpp"
++#include "xyz/openbmc_project/Channel/ChannelAccess/server.hpp"
+ #include "xyz/openbmc_project/Network/IP/Create/server.hpp"
+ #include "xyz/openbmc_project/Network/Neighbor/CreateStatic/server.hpp"
+
+ #include <filesystem>
++#include <nlohmann/json.hpp>
+ #include <sdbusplus/bus.hpp>
++#include <sdbusplus/bus/match.hpp>
+ #include <sdbusplus/server/object.hpp>
+ #include <sdbusplus/timer.hpp>
+ #include <string>
+@@ -35,7 +38,8 @@ using Ifaces = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Network::server::MACAddress,
+ sdbusplus::xyz::openbmc_project::Network::IP::server::Create,
+ sdbusplus::xyz::openbmc_project::Network::Neighbor::server::CreateStatic,
+- sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll>;
++ sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll,
++ sdbusplus::xyz::openbmc_project::Channel::server::ChannelAccess>;
+
+ using IP = sdbusplus::xyz::openbmc_project::Network::server::IP;
+
+@@ -43,11 +47,14 @@ using EthernetInterfaceIntf =
+ sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
+ using MacAddressIntf =
+ sdbusplus::xyz::openbmc_project::Network::server::MACAddress;
++using ChannelAccessIntf =
++ sdbusplus::xyz::openbmc_project::Channel::server::ChannelAccess;
+
+ using ServerList = std::vector<std::string>;
+ using ObjectPath = sdbusplus::message::object_path;
+
+ namespace fs = std::filesystem;
++using DbusVariant = std::variant<std::string, std::vector<std::string>>;
+
+ class Manager; // forward declaration of network manager.
+
+@@ -247,6 +254,14 @@ class EthernetInterface : public Ifaces
+ std::string defaultGateway6(std::string gateway) override;
+
+ using EthernetInterfaceIntf::dhcpEnabled;
++ /** @brief sets the channel maxium privilege.
++ * @param[in] value - Channel privilege which needs to be set on the
++ * system.
++ * @returns privilege of the interface or throws an error.
++ */
++ std::string maxPrivilege(std::string value) override;
++
++ using ChannelAccessIntf::maxPrivilege;
+ using EthernetInterfaceIntf::interfaceName;
+ using EthernetInterfaceIntf::linkUp;
+ using EthernetInterfaceIntf::nicEnabled;
+@@ -374,6 +389,25 @@ class EthernetInterface : public Ifaces
+ * @returns true/false value if the NIC is enabled
+ */
+ bool queryNicEnabled() const;
++ /** @brief gets the channel privilege.
++ * @param[in] interfaceName - Network interface name.
++ * @returns privilege of the interface
++ */
++ std::string getChannelPrivilege(const std::string& interfaceName);
++
++ /** @brief reads the channel access info from file.
++ * @param[in] configFile - channel access filename
++ * @returns json file data
++ */
++ nlohmann::json readJsonFile(const std::string& configFile);
++
++ /** @brief writes the channel access info to file.
++ * @param[in] configFile - channel access filename
++ * @param[in] jsonData - json data to write
++ * @returns success or failure
++ */
++ int writeJsonFile(const std::string& configFile,
++ const nlohmann::json& jsonData);
+ };
+
+ } // namespace network
+diff --git a/src/network_manager.cpp b/src/network_manager.cpp
+index 9ae9c5b..2f5097a 100644
+--- a/src/network_manager.cpp
++++ b/src/network_manager.cpp
+@@ -36,6 +36,13 @@ extern std::unique_ptr<Timer> restartTimer;
+ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
++static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
++static constexpr const char* userMgrInterface =
++ "xyz.openbmc_project.User.Manager";
++static constexpr const char* propNameAllPrivileges = "AllPrivileges";
++
++std::unique_ptr<sdbusplus::bus::match_t> usrMgmtSignal(nullptr);
++
+ Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath,
+ const std::string& path) :
+ details::VLANCreateIface(bus, objPath, true),
+@@ -43,6 +50,101 @@ Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath,
+ {
+ fs::path confDir(path);
+ setConfDir(confDir);
++ initSupportedPrivilges();
++}
++
++std::string getUserService(sdbusplus::bus::bus& bus, const std::string& intf,
++ const std::string& path)
++{
++ auto mapperCall =
++ bus.new_method_call("xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject");
++
++ mapperCall.append(path);
++ mapperCall.append(std::vector<std::string>({intf}));
++
++ auto mapperResponseMsg = bus.call(mapperCall);
++
++ std::map<std::string, std::vector<std::string>> mapperResponse;
++ mapperResponseMsg.read(mapperResponse);
++
++ if (mapperResponse.begin() == mapperResponse.end())
++ {
++ throw std::runtime_error("ERROR in reading the mapper response");
++ }
++
++ return mapperResponse.begin()->first;
++}
++
++std::string Manager::getUserServiceName()
++{
++ static std::string userMgmtService;
++ if (userMgmtService.empty())
++ {
++ try
++ {
++ userMgmtService =
++ getUserService(bus, userMgrInterface, userMgrObjBasePath);
++ }
++ catch (const std::exception& e)
++ {
++ log<level::ERR>("Exception caught in getUserServiceName.");
++ userMgmtService.clear();
++ }
++ }
++ return userMgmtService;
++}
++
++void Manager::initSupportedPrivilges()
++{
++ std::string userServiceName = getUserServiceName();
++ if (!userServiceName.empty())
++ {
++ auto method = bus.new_method_call(
++ getUserServiceName().c_str(), userMgrObjBasePath,
++ "org.freedesktop.DBus.Properties", "Get");
++ method.append(userMgrInterface, propNameAllPrivileges);
++
++ auto reply = bus.call(method);
++ if (reply.is_method_error())
++ {
++ log<level::DEBUG>("get-property AllPrivileges failed",
++ entry("OBJPATH:%s", userMgrObjBasePath),
++ entry("INTERFACE:%s", userMgrInterface));
++ return;
++ }
++
++ std::variant<std::vector<std::string>> result;
++ reply.read(result);
++
++ supportedPrivList = std::get<std::vector<std::string>>(result);
++ }
++
++ // Resgister the signal
++ if (usrMgmtSignal == nullptr)
++ {
++ log<level::DEBUG>("Registering User.Manager propertychange signal.");
++ usrMgmtSignal = std::make_unique<sdbusplus::bus::match_t>(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(userMgrObjBasePath,
++ userMgrInterface),
++ [&](sdbusplus::message::message& msg) {
++ log<level::DEBUG>("UserMgr properties changed signal");
++ std::map<std::string, DbusVariant> props;
++ std::string iface;
++ msg.read(iface, props);
++ for (const auto& t : props)
++ {
++ if (t.first == propNameAllPrivileges)
++ {
++ supportedPrivList =
++ std::get<std::vector<std::string>>(t.second);
++ }
++ }
++ });
++ }
++ return;
+ }
+
+ bool Manager::createDefaultNetworkFiles(bool force)
+diff --git a/src/network_manager.hpp b/src/network_manager.hpp
+index 227955c..9f5b7a9 100644
+--- a/src/network_manager.hpp
++++ b/src/network_manager.hpp
+@@ -155,6 +155,12 @@ class Manager : public details::VLANCreateIface
+ return (interfaces.find(intf) != interfaces.end());
+ }
+
++ /** supported privilege list **/
++ std::vector<std::string> supportedPrivList;
++
++ /** @brief initializes the supportedPrivilege List */
++ void initSupportedPrivilges();
++
+ protected:
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+@@ -177,6 +183,9 @@ class Manager : public details::VLANCreateIface
+
+ /** @brief Network Configuration directory. */
+ fs::path confDir;
++
++ /** Get the user management service name dynamically **/
++ std::string getUserServiceName();
+ };
+
+ } // namespace network
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0004-Fix-for-updating-MAC-address-from-RedFish.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0004-Fix-for-updating-MAC-address-from-RedFish.patch
new file mode 100644
index 000000000..fe7c45532
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0004-Fix-for-updating-MAC-address-from-RedFish.patch
@@ -0,0 +1,109 @@
+From f6240a81c0ed87c128d454fa9c4023b9062efe5e Mon Sep 17 00:00:00 2001
+From: sunitakx <sunitax.kumari@linux.intel.com>
+Date: Tue, 13 Jul 2021 12:54:01 +0000
+Subject: [PATCH] Fix for updating MAC address from RedFish
+
+Issue: When IP address source for an interface is DHCP and its MAC
+address is patched using RedFish, response code is not reaching the
+RedFish request initiator (client).
+
+RootCause: After bmcweb patches the MAC address, immediately IP address
+of that interface also changes to new value (because of DHCP).
+Due to this, success response from bmcweb is not reaching the client as
+expected.
+
+Fix: Do MAC-ADDR patching after validating the request and responding
+"200 OK" to RedFish client. i.e Start a timer which will modify the
+MAC-ADDR at the end of its expiry.
+
+Tested:
+Update the MAC address from RedFish.
+PATCH: https://<bmc_ip>/redfish/v1/Managers/bmc/EthernetInterfaces/eth0
+Body:
+ {"MACAddress": "xx:xx:xx:xx:xx:xx"}
+
+Response code: {"200 OK"} received.
+
+Signed-off-by: sunitakx <sunitax.kumari@linux.intel.com>
+---
+ src/ethernet_interface.cpp | 19 +++++++++++++------
+ src/ethernet_interface.hpp | 5 +++++
+ 2 files changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
+index 666173e6587e..95bc8db9cd3a 100644
+--- a/src/ethernet_interface.cpp
++++ b/src/ethernet_interface.cpp
+@@ -144,6 +144,8 @@ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ {
+ this->emit_object_added();
+ }
++ macUpdateTimer = std::make_unique<phosphor::Timer>(
++ [this](void) { macAddressTimeoutHandler(); });
+ }
+
+ static IP::Protocol convertFamily(int family)
+@@ -1129,8 +1131,18 @@ void EthernetInterface::writeDHCPSection(std::fstream& stream)
+ }
+ }
+
++void EthernetInterface::macAddressTimeoutHandler()
++{
++ macUpdateTimer->stop();
++ // TODO: would remove the call below and
++ // just restart systemd-netwokd
++ // through https://github.com/systemd/systemd/issues/6696
++ execute("/sbin/ip", "ip", "link", "set", "dev", interfaceName().c_str(),
++ "down");
++}
+ std::string EthernetInterface::macAddress(std::string value)
+ {
++ std::chrono::seconds usec(defaultTimeout);
+ ether_addr newMAC;
+ try
+ {
+@@ -1164,12 +1176,7 @@ std::string EthernetInterface::macAddress(std::string value)
+ intf->MacAddressIntf::macAddress(validMAC);
+ }
+ MacAddressIntf::macAddress(validMAC);
+-
+- // TODO: would remove the call below and
+- // just restart systemd-netwokd
+- // through https://github.com/systemd/systemd/issues/6696
+- execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
+- "down");
++ macUpdateTimer->start(usec);
+ manager.writeToConfigurationFile();
+ }
+
+diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
+index 6c7bd69ef987..acf6b6792b75 100644
+--- a/src/ethernet_interface.hpp
++++ b/src/ethernet_interface.hpp
+@@ -11,11 +11,14 @@
+ #include <sdbusplus/bus.hpp>
+ #include <sdbusplus/bus/match.hpp>
+ #include <sdbusplus/server/object.hpp>
++#include <sdbusplus/timer.hpp>
+ #include <string>
+ #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
+ #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
+ #include <xyz/openbmc_project/Network/MACAddress/server.hpp>
+
++static constexpr const uint32_t defaultTimeout = 1;
++
+ namespace phosphor
+ {
+ namespace network
+@@ -83,6 +86,8 @@ class EthernetInterface : public Ifaces
+ EthernetInterface& operator=(EthernetInterface&&) = delete;
+ virtual ~EthernetInterface() = default;
+
++ std::unique_ptr<phosphor::Timer> macUpdateTimer;
++ void macAddressTimeoutHandler();
+ /** @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.
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0005-Added-debug-logs-to-isolate-the-coredump-issue-of-RT.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0005-Added-debug-logs-to-isolate-the-coredump-issue-of-RT.patch
new file mode 100644
index 000000000..255ae4836
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0005-Added-debug-logs-to-isolate-the-coredump-issue-of-RT.patch
@@ -0,0 +1,261 @@
+From f898e4512e7907ba185a1178ad36cb7af6ad0811 Mon Sep 17 00:00:00 2001
+From: sureshv1 <suresh.vijayakumar@intel.com>
+Date: Tue, 10 Aug 2021 16:38:42 +0530
+Subject: [PATCH] Added Debug logs to isolate coredump of RTNETLink Packet
+ Processing Clang Format updated
+
+Tested:
+Flashed the BMC firmware image with logs included and observed that
+the logs are logged during the boot up time and not flooding serial
+console.After the BMC is booted up, logs were logged in when ever a
+RT Net Link Packet is received and not flooding the journalctl logs.
+
+Change-Id: I5e1d152b18df17e5351c498210dae5c45f551f7b
+Signed-off-by: sureshv1 <suresh.vijayakumar@intel.com>
+---
+ src/network_manager.cpp | 15 ++++++++
+ src/network_manager_main.cpp | 12 +++++++
+ src/rtnetlink_server.cpp | 70 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 97 insertions(+)
+
+diff --git a/src/network_manager.cpp b/src/network_manager.cpp
+index 2f5097a..ec48f2a 100644
+--- a/src/network_manager.cpp
++++ b/src/network_manager.cpp
+@@ -15,6 +15,7 @@
+ #include <bitset>
+ #include <filesystem>
+ #include <fstream>
++#include <iostream>
+ #include <map>
+ #include <phosphor-logging/elog-errors.hpp>
+ #include <phosphor-logging/log.hpp>
+@@ -26,6 +27,8 @@ constexpr char SYSTEMD_PATH[] = "/org/freedesktop/systemd1";
+ constexpr char SYSTEMD_INTERFACE[] = "org.freedesktop.systemd1.Manager";
+ constexpr auto FirstBootFile = "/var/lib/network/firstBoot_";
+
++constexpr bool debug = true;
++
+ namespace phosphor
+ {
+ namespace network
+@@ -273,6 +276,12 @@ void Manager::createInterfaces()
+
+ void Manager::createChildObjects()
+ {
++ if (debug)
++ {
++ std::cout
++ << "Create Child Objects called(restart system conf and DHCP conf)"
++ << "\n";
++ }
+ // creates the ethernet interface dbus object.
+ createInterfaces();
+
+@@ -289,6 +298,12 @@ void Manager::createChildObjects()
+ objPath /= "dhcp";
+ dhcpConf = std::make_unique<phosphor::network::dhcp::Configuration>(
+ bus, objPath.string(), *this);
++
++ if (debug)
++ {
++ std::cout << "Create Child Objects Exiting"
++ << "\n";
++ }
+ }
+
+ ObjectPath Manager::vlan(IntfName interfaceName, uint32_t id)
+diff --git a/src/network_manager_main.cpp b/src/network_manager_main.cpp
+index 983616f..c9bdb15 100644
+--- a/src/network_manager_main.cpp
++++ b/src/network_manager_main.cpp
+@@ -10,6 +10,7 @@
+ #include <filesystem>
+ #include <fstream>
+ #include <functional>
++#include <iostream>
+ #include <memory>
+ #ifdef SYNC_MAC_FROM_INVENTORY
+ #include <nlohmann/json.hpp>
+@@ -41,6 +42,8 @@ constexpr auto configFile = "/usr/share/network/config.json";
+ constexpr auto invNetworkIntf =
+ "xyz.openbmc_project.Inventory.Item.NetworkInterface";
+
++constexpr bool debug = true;
++
+ namespace phosphor
+ {
+ namespace network
+@@ -255,10 +258,19 @@ void restartNetwork()
+
+ void initializeTimers()
+ {
++ if (debug)
++ std::cout
++ << "Initialize Timer for Refresh Object Timer and Restart Timer"
++ << "\n";
++
+ auto event = sdeventplus::Event::get_default();
+ refreshObjectTimer =
+ std::make_unique<Timer>(event, std::bind(refreshObjects));
+ restartTimer = std::make_unique<Timer>(event, std::bind(restartNetwork));
++
++ if (debug)
++ std::cout << "Initialize Timer Exiting"
++ << "\n";
+ }
+
+ } // namespace network
+diff --git a/src/rtnetlink_server.cpp b/src/rtnetlink_server.cpp
+index 07ca08c..74f08b3 100644
+--- a/src/rtnetlink_server.cpp
++++ b/src/rtnetlink_server.cpp
+@@ -11,12 +11,15 @@
+ #include <systemd/sd-daemon.h>
+ #include <unistd.h>
+
++#include <iostream>
+ #include <memory>
+ #include <phosphor-logging/elog-errors.hpp>
+ #include <phosphor-logging/log.hpp>
+ #include <string_view>
+ #include <xyz/openbmc_project/Common/error.hpp>
+
++constexpr bool debug = true;
++
+ namespace phosphor
+ {
+ namespace network
+@@ -29,6 +32,9 @@ namespace rtnetlink
+
+ static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
+ {
++ if (debug)
++ std::cout << "Should Refresh the Received Header with Data"
++ << "\n";
+ switch (hdr.nlmsg_type)
+ {
+ case RTM_NEWADDR:
+@@ -36,22 +42,43 @@ static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ {
++ if (debug)
++ std::cout << "Don't Copy Data as the Message Type is:"
++ << hdr.nlmsg_type << "\n";
+ return true;
+ }
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ {
++ if (debug)
++ std::cout << "Message Type is" << hdr.nlmsg_type << "\n";
+ struct ndmsg ndm;
+ if (data.size() < sizeof(ndm))
+ {
++ if (debug)
++ std::cout << "Data Size:" << data.size()
++ << " NDM Size:" << sizeof(ndm) << "\n";
+ return false;
+ }
++ if (debug)
++ std::cout
++ << "Processing/Copying the received Data for MLMSG_TYPE:"
++ << hdr.nlmsg_type << " Data Size:" << data.size() << "\n";
+ memcpy(&ndm, data.data(), sizeof(ndm));
++ if (debug)
++ std::cout << "Copied the received Data for MLMSG_TYPE:"
++ << hdr.nlmsg_type
++ << " and NDM Message Size is:" << sizeof(ndm) << "\n";
+ // We only want to refresh for static neighbors
+ return ndm.ndm_state & NUD_PERMANENT;
+ }
+ }
+
++ if (debug)
++ std::cout << "Should Refresh Object is verified and done without any "
++ "known header type"
++ << "\n";
++
+ return false;
+ }
+
+@@ -62,25 +89,58 @@ static int eventHandler(sd_event_source* /*es*/, int fd, uint32_t /*revents*/,
+ char buffer[phosphor::network::rtnetlink::BUFSIZE]{};
+ int len{};
+
++ if (debug)
++ std::cout << "\n"
++ << "RTNETLINK event Handler is called to read the RTNETLINK "
++ "Packet and Refresh it for a buffer size:"
++ << phosphor::network::rtnetlink::BUFSIZE << "\n";
+ auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
+ while ((len = recv(fd, netLinkHeader, phosphor::network::rtnetlink::BUFSIZE,
+ 0)) > 0)
+ {
++ if (debug)
++ {
++ std::cout << "Received the Packet with a Length:" << len << "\n";
++ }
+ for (; (NLMSG_OK(netLinkHeader, len)) &&
+ (netLinkHeader->nlmsg_type != NLMSG_DONE);
+ netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
+ {
++ if (debug)
++ std::cout << "NetLinkHeader Message Type is:"
++ << netLinkHeader->nlmsg_type
++ << " with total length(len):" << len
++ << " and block data packet "
++ "length(netLinkHeader->nlmsg_len - NLMSG_HDRLEN):"
++ << netLinkHeader->nlmsg_len - NLMSG_HDRLEN
++ << " and Message Length(netLinkHeader->nlmsg_len):"
++ << netLinkHeader->nlmsg_len << "\n";
+ std::string_view data(
+ reinterpret_cast<const char*>(NLMSG_DATA(netLinkHeader)),
+ netLinkHeader->nlmsg_len - NLMSG_HDRLEN);
++ if (debug)
++ {
++ if (netLinkHeader)
++ std::cout << "NetLinkHeader is valid"
++ << "\n";
++ }
+ if (shouldRefresh(*netLinkHeader, data))
+ {
+ // starting the timer here to make sure that we don't want
+ // create the child objects multiple times.
++ if (debug)
++ std::cout << "Check Refresh Object Timer is enabled?"
++ << "\n";
+ if (!refreshObjectTimer->isEnabled())
+ {
+ // if start timer throws exception then let the application
+ // crash
++ if (debug)
++ std::cout
++ << "Call Restart Once with a Timeout seconds:"
++ << std::chrono::seconds(refreshTimeout).count()
++ << "\n";
++
+ refreshObjectTimer->restartOnce(refreshTimeout);
+ } // end if
+ } // end if
+@@ -89,6 +149,16 @@ static int eventHandler(sd_event_source* /*es*/, int fd, uint32_t /*revents*/,
+
+ } // end while
+
++ if (debug)
++ {
++ std::cout << "RTNETLINK Event Handler completed read of packets and "
++ "processed it"
++ << " with an length(exit):" << len << "\n";
++
++ if (errno)
++ std::cout << "Error Number:" << errno << "\n";
++ }
++
+ return 0;
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend
new file mode 100644
index 000000000..f8010b283
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend
@@ -0,0 +1,14 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += "nlohmann-json boost"
+
+SRC_URI = "git://github.com/openbmc/phosphor-networkd"
+SRCREV = "b108fd740fdde4a9f0fe63e63ccdee695f5b92e7"
+
+SRC_URI += " file://0003-Adding-channel-specific-privilege-to-network.patch \
+ file://0004-Fix-for-updating-MAC-address-from-RedFish.patch \
+ file://0005-Added-debug-logs-to-isolate-the-coredump-issue-of-RT.patch \
+ "
+
+EXTRA_OECONF:append = " --enable-nic-ethtool=yes"
+EXTRA_OECONF:append = " --enable-ipv6-accept-ra=yes"
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb
new file mode 100644
index 000000000..ee55c5407
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb
@@ -0,0 +1,24 @@
+SUMMARY = "Enforce static MAC addresses"
+DESCRIPTION = "Set a priority on MAC addresses to run with: \
+ factory-specified > u-boot-specified > random"
+
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+PV = "1.0"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI = "\
+ file://mac-check \
+ file://${PN}.service \
+ "
+
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE:${PN} += "${PN}.service"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/mac-check ${D}${bindir}
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
new file mode 100644
index 000000000..39d7dd8a7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
@@ -0,0 +1,161 @@
+#!/bin/sh
+# Copyright 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.
+
+SOFS_MNT=/var/sofs
+SOFS_MACDIR=${SOFS_MNT}/factory-settings/network/mac
+
+read_hw_mac() {
+ local iface="$1"
+ cat /sys/class/net/"$iface"/address 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
+}
+
+set_hw_mac() {
+ local iface="$1"
+ local mac="$2"
+ ip link show dev "$iface" | grep -q "${iface}:.*\<UP\>" 2>/dev/null
+ local up=$?
+ [[ $up -eq 0 ]] && ip link set dev "$iface" down
+ ip link set dev "$iface" address "$mac"
+ [[ $up -eq 0 ]] && ip link set dev "$iface" up
+}
+
+read_sofs_mac() {
+ local iface="$1"
+ cat "${SOFS_MACDIR}/${iface}" 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
+}
+
+read_fw_env_mac() {
+ local envname="$1"
+ fw_printenv "$envname" 2>/dev/null | sed "s/^$envname=//" 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
+}
+
+set_fw_env_mac() {
+ local envname="$1"
+ local mac="$2"
+ fw_setenv "$envname" "$mac"
+}
+
+create_macdir() {
+if [ -a ${SOFS_MACDIR} ]; then
+ if [ ! -d ${SOFS_MACDIR} ]; then
+ rm -rf ${SOFS_MACDIR}
+ mkdir -p ${SOFS_MACDIR}
+ fi
+else
+ mkdir -p ${SOFS_MACDIR}
+fi
+return 0
+}
+
+# An earlier version of the mac_check utility disabled the netipmid for
+# eth1. This was done to eliminate an error message being logged in the
+# journal for systems that only had a single NIC. The error message is
+# undesirable as it is present in Redfish session log output.
+
+# Systems that have both NICs have also had the eth1 netipmid disabled.
+# The reason for this is failing to specify the correct kernel device
+# tree during the U-Boot kernel boot process. Without the correct
+# device tree, eth1 is not enumerated by the kernel. The mac-check
+# script turned off the netipmid service for eth1.
+
+# The configure_netipmid_svc_eth1 function manages enabling and
+# disabling netipmid for eth1. It is explicit, and does not rely upon
+# previous state to enable or disable the service.
+
+# Note: Enabling the service is independent of the IPMI channel
+# enable/disable command. This means "ipmitool lan set <chid> access
+# off" functions correctly with the netipmid service enabled.
+configure_netipmid_svc_eth1() {
+ if [ -h /sys/class/net/eth1 ]; then
+ if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.socket) == "disabled" ];
+ then
+ /bin/systemctl enable "phosphor-ipmi-net@eth1.socket"
+ /bin/systemctl start "phosphor-ipmi-net@eth1.socket"
+ fi
+ if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.service) =="disabled" ];
+ then
+ /bin/systemctl enable "phosphor-ipmi-net@eth1.service"
+ /bin/systemctl start "phosphor-ipmi-net@eth1.service"
+ fi
+ else
+ if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.socket) == "enabled" ];
+ then
+ /bin/systemctl disable "phosphor-ipmi-net@eth1.socket"
+ /bin/systemctl stop "phosphor-ipmi-net@eth1.socket"
+ fi
+ if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.service) == "enabled" ];
+ then
+ /bin/systemctl disable "phosphor-ipmi-net@eth1.service"
+ /bin/systemctl stop "phosphor-ipmi-net@eth1.service"
+ fi
+ fi
+}
+
+mac_check() {
+ local iface="$1"
+ local envname="$2"
+
+ # Read the MAC address in use by the NIC
+ local hw_mac=$(read_hw_mac "$iface")
+
+ # Read the MAC address stored in the non-volatile file provisioned in
+ # manufacturing.
+ local sofs_mac=$(read_sofs_mac "$iface")
+
+ if [ -n "$sofs_mac" ] && [ "$hw_mac" != "$sofs_mac" ]; then
+ # A factory assigned address was found, and it is newly assigned.
+ # Update the active interface and save the new value to the u-boot
+ # environment.
+ set_hw_mac "$iface" "$sofs_mac"
+ set_fw_env_mac "$envname" "$sofs_mac"
+ return $?
+ elif [ -n "$hw_mac" ]; then
+ # Read the MAC address stored by U-Boot
+ local fw_env_mac=$(read_fw_env_mac "$envname")
+ if [ -z "$fw_env_mac" ] || [ "$fw_env_mac" != "$hw_mac" ]; then
+ set_fw_env_mac "$envname" "$hw_mac"
+ return $?
+ fi
+ else
+ # Could not identify a MAC address
+ return 255
+ fi
+ return 0
+}
+
+create_macdir
+
+configure_netipmid_svc_eth1
+
+error=0
+first_error_seen=0
+
+while read IFACE UBDEV; do
+ # Try to configure the MAC address if the kernel finds the NIC. Blindly
+ # trying all of the interfaces listed in the DOCSTRING (END_CONF) below
+ # may result in first_error_seen being set to a non-zero value. If that
+ # happens the journal log will report the error, which is undesirable.
+ if [ -h /sys/class/net/$IFACE ]; then
+ mac_check "$IFACE" "$UBDEV"
+ error=$?
+ if [ $error -ne 0 ] && [ $first_error_seen -eq 0 ]; then
+ first_error_seen=$error
+ fi
+ fi
+done <<-END_CONF
+ eth0 eth1addr
+ eth1 ethaddr
+END_CONF
+exit $first_error_seen
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service
new file mode 100644
index 000000000..86371db11
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Enforce Static MAC addr mapping
+
+[Service]
+Type=oneshot
+Restart=no
+ExecStart=/usr/bin/mac-check
+
+[Install]
+WantedBy=network.target
+