SetLan: Make changes in set channel access to support ipsrc param
Resolves openbmc/openbmc#2138
Change-Id: I4b4b8e915bcfea6ed5f913ede5f714290483e4f9
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/apphandler.cpp b/apphandler.cpp
index 8340922..d911356 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -11,6 +11,8 @@
#include <mapper.h>
#include <array>
#include <vector>
+#include <experimental/filesystem>
+
#include <arpa/inet.h>
#include "transporthandler.hpp"
@@ -30,6 +32,7 @@
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+namespace fs = std::experimental::filesystem;
// Offset in get device id command.
typedef struct
@@ -546,117 +549,179 @@
std::string gateway;
uint8_t prefix {};
uint32_t vlanID {};
+ std::string networkInterfacePath;
+ ipmi::DbusObjectInfo ipObject;
+ ipmi::DbusObjectInfo systemObject;
// Todo: parse the request data if needed.
-
// Using Set Channel cmd to apply changes of Set Lan Cmd.
try
{
-
sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
log<level::INFO>("Network data from Cache",
entry("PREFIX=%s", channelConfig.netmask.c_str()),
entry("ADDRESS=%s", channelConfig.ipaddr.c_str()),
- entry("GATEWAY=%s", channelConfig.gateway.c_str()));
+ entry("GATEWAY=%s", channelConfig.gateway.c_str()),
+ entry("VLAN=%d", channelConfig.vlanID),
+ entry("IPSRC=%d", channelConfig.ipsrc));
- auto systemObject = ipmi::getDbusObject(bus,
- ipmi::network::SYSTEMCONFIG_INTERFACE,
- ipmi::network::ROOT);
-
- // TODO Currently IPMI supports single interface,need to handle
- // Multiple interface through
- // https://github.com/openbmc/openbmc/issues/2138
-
- auto networkInterfaceObject = ipmi::getDbusObject(
- bus,
- ipmi::network::ETHERNET_INTERFACE,
- ipmi::network::ROOT,
- ipmi::network::INTERFACE);
-
-
-
- // check wthether user has given all the data
- if (!channelConfig.ipaddr.empty() &&
- !channelConfig.netmask.empty() &&
- !channelConfig.gateway.empty())
+ if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
{
- //convert mask into prefix
- ipaddress = channelConfig.ipaddr;
- prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask);
- gateway = channelConfig.gateway;
-
- if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
- {
- //get the first twelve bits which is vlan id
- //not interested in rest of the bits.
- vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
- channelConfig.vlanID = le32toh(channelConfig.vlanID);
- }
-
+ //get the first twelve bits which is vlan id
+ //not interested in rest of the bits.
+ channelConfig.vlanID = le32toh(channelConfig.vlanID);
+ vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
}
- else
+
+ // if the asked ip src is DHCP then not interested in
+ // any given data except vlan.
+ if (channelConfig.ipsrc != ipmi::network::IPOrigin::DHCP)
{
- // We have partial filled cache so get the remaning
- // info from the system.
+ // always get the system object
+ systemObject = ipmi::getDbusObject(
+ bus,
+ ipmi::network::SYSTEMCONFIG_INTERFACE,
+ ipmi::network::ROOT);
- // gets the network data from the system as user has
- // not given all the data then use the data fetched from the
- // system but it is implementation dependent,IPMI spec doesn't
- // force it.
-
- // if system is not having any ip object don't throw error,
+ // the below code is to determine the mode of the interface
+ // as the handling is same, if the system is configured with
+ // DHCP or user has given all the data.
try
{
- auto ipObjectInfo = ipmi::getDbusObject(bus,
- ipmi::network::IP_INTERFACE,
+ ipmi::ObjectTree ancestorMap;
+
+ ipmi::InterfaceList interfaces {
+ ipmi::network::ETHERNET_INTERFACE };
+
+ // if the system is having ip object,then
+ // get the IP object.
+ ipObject = ipmi::getDbusObject(bus,
+ ipmi::network::IP_INTERFACE,
+ ipmi::network::ROOT,
+ ipmi::network::IP_TYPE);
+
+ // Get the parent interface of the IP object.
+ try
+ {
+ ancestorMap = ipmi::getAllAncestors(bus,
+ ipObject.first,
+ std::move(interfaces));
+ }
+ catch (InternalFailure& e)
+ {
+ // if unable to get the parent interface
+ // then commit the error and return.
+ log<level::ERR>("Unable to get the parent interface",
+ entry("PATH=%s", ipObject.first.c_str()),
+ entry("INTERFACE=%s",
+ ipmi::network::ETHERNET_INTERFACE));
+ commit<InternalFailure>();
+ rc = IPMI_CC_UNSPECIFIED_ERROR;
+ channelConfig.clear();
+ return rc;
+ }
+
+ networkInterfacePath = ancestorMap.begin()->first;
+ }
+ catch (InternalFailure& e)
+ {
+ // TODO Currently IPMI supports single interface,need to handle
+ // Multiple interface through
+ // https://github.com/openbmc/openbmc/issues/2138
+
+ // if there is no ip configured on the system,then
+ // get the network interface object.
+ auto networkInterfaceObject = ipmi::getDbusObject(
+ bus,
+ ipmi::network::ETHERNET_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::IP_TYPE);
+ ipmi::network::INTERFACE);
- auto properties = ipmi::getAllDbusProperties(bus,
- ipObjectInfo.second,
- ipObjectInfo.first,
- ipmi::network::IP_INTERFACE);
+ networkInterfacePath = std::move(networkInterfaceObject.first);
+ }
- ipaddress = channelConfig.ipaddr.empty() ?
- std::move(properties["Address"].get<std::string>()) :
- channelConfig.ipaddr;
+ // get the configured mode on the system.
+ auto enableDHCP = ipmi::getDbusProperty(
+ bus,
+ ipmi::network::SERVICE,
+ networkInterfacePath,
+ ipmi::network::ETHERNET_INTERFACE,
+ "DHCPEnabled").get<bool>();
- prefix = channelConfig.netmask.empty() ?
- properties["PrefixLength"].get<uint8_t>() :
- ipmi::network::toPrefix(AF_INET,
- channelConfig.netmask);
-
+ // check whether user has given all the data
+ // or the configured system interface is dhcp enabled,
+ // in both of the cases get the values from the cache.
+ if ((!channelConfig.ipaddr.empty() &&
+ !channelConfig.netmask.empty() &&
+ !channelConfig.gateway.empty()) ||
+ (enableDHCP)) // configured system interface mode = DHCP
+ {
+ //convert mask into prefix
+ ipaddress = channelConfig.ipaddr;
+ prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask);
+ gateway = channelConfig.gateway;
if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
{
//get the first twelve bits which is vlan id
//not interested in rest of the bits.
- vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
channelConfig.vlanID = le32toh(channelConfig.vlanID);
+ vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
}
else
{
- vlanID = ipmi::network::getVLAN(ipObjectInfo.first);
+ vlanID = ipmi::network::getVLAN(networkInterfacePath);
}
}
- catch (InternalFailure& e)
+ else // asked ip src = static and configured system src = static
+ // or partially given data.
{
- log<level::INFO>("Failed to get IP object which matches",
- entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
- entry("MATCH=%s", ipmi::network::IP_TYPE));
+ // We have partial filled cache so get the remaining
+ // info from the system.
+
+ // Get the network data from the system as user has
+ // not given all the data then use the data fetched from the
+ // system but it is implementation dependent,IPMI spec doesn't
+ // force it.
+
+ // if system is not having any ip object don't throw error,
+ try
+ {
+ auto properties = ipmi::getAllDbusProperties(
+ bus,
+ ipObject.second,
+ ipObject.first,
+ ipmi::network::IP_INTERFACE);
+
+ ipaddress = channelConfig.ipaddr.empty() ?
+ properties["Address"].get<std::string>() :
+ channelConfig.ipaddr;
+
+ prefix = channelConfig.netmask.empty() ?
+ properties["PrefixLength"].get<uint8_t>() :
+ ipmi::network::toPrefix(AF_INET,
+ channelConfig.netmask);
+
+ }
+ catch (InternalFailure& e)
+ {
+ log<level::INFO>("Failed to get IP object which matches",
+ entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
+ entry("MATCH=%s", ipmi::network::IP_TYPE));
+ }
+
+ auto systemProperties = ipmi::getAllDbusProperties(
+ bus,
+ systemObject.second,
+ systemObject.first,
+ ipmi::network::SYSTEMCONFIG_INTERFACE);
+
+ gateway = channelConfig.gateway.empty() ?
+ systemProperties["DefaultGateway"].get<std::string>() :
+ channelConfig.gateway;
+
}
-
- auto systemProperties = ipmi::getAllDbusProperties(
- bus,
- systemObject.second,
- systemObject.first,
- ipmi::network::SYSTEMCONFIG_INTERFACE);
-
- gateway = channelConfig.gateway.empty() ?
- std::move(systemProperties["DefaultGateway"].get<std::string>()) :
- channelConfig.gateway;
-
}
// Currently network manager doesn't support purging of all the
@@ -668,40 +733,102 @@
// Multiple interface through
// https://github.com/openbmc/openbmc/issues/2138
+ // instead of deleting all the vlan interfaces and
+ // all the ipv4 address,we will call reset method.
//delete all the vlan interfaces
- //delete all the ipv4 addresses
- ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
+
+ ipmi::deleteAllDbusObjects(bus,
+ ipmi::network::ROOT,
ipmi::network::VLAN_INTERFACE);
- ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
+
+ // set the interface mode to static
+ auto networkInterfaceObject = ipmi::getDbusObject(
+ bus,
+ ipmi::network::ETHERNET_INTERFACE,
+ ipmi::network::ROOT,
+ ipmi::network::INTERFACE);
+
+ // setting the physical interface mode to static.
+ ipmi::setDbusProperty(bus,
+ ipmi::network::SERVICE,
+ networkInterfaceObject.first,
+ ipmi::network::ETHERNET_INTERFACE,
+ "DHCPEnabled",
+ false);
+
+ networkInterfacePath = networkInterfaceObject.first;
+
+ //delete all the ipv4 addresses
+ ipmi::deleteAllDbusObjects(bus,
+ ipmi::network::ROOT,
ipmi::network::IP_INTERFACE,
ipmi::network::IP_TYPE);
+
if (vlanID)
{
- ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
+ ipmi::network::createVLAN(bus,
+ ipmi::network::SERVICE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE, vlanID);
+ ipmi::network::INTERFACE,
+ vlanID);
- networkInterfaceObject = ipmi::getDbusObject(
+ auto networkInterfaceObject = ipmi::getDbusObject(
bus,
ipmi::network::VLAN_INTERFACE,
ipmi::network::ROOT);
+
+ networkInterfacePath = networkInterfaceObject.first;
}
- ipmi::network::createIP(bus, networkInterfaceObject.second,
- networkInterfaceObject.first,
- ipv4Protocol, ipaddress, prefix);
+ if (channelConfig.ipsrc == ipmi::network::IPOrigin::DHCP)
+ {
+ ipmi::setDbusProperty(bus,
+ ipmi::network::SERVICE,
+ networkInterfacePath,
+ ipmi::network::ETHERNET_INTERFACE,
+ "DHCPEnabled",
+ true);
+ }
+ else
+ {
+ //change the mode to static
+ ipmi::setDbusProperty(bus,
+ ipmi::network::SERVICE,
+ networkInterfacePath,
+ ipmi::network::ETHERNET_INTERFACE,
+ "DHCPEnabled",
+ false);
- ipmi::setDbusProperty(bus, systemObject.second, systemObject.first,
- ipmi::network::SYSTEMCONFIG_INTERFACE,
- "DefaultGateway", gateway);
+ if (!ipaddress.empty())
+ {
+ ipmi::network::createIP(bus,
+ ipmi::network::SERVICE,
+ networkInterfacePath,
+ ipv4Protocol,
+ ipaddress,
+ prefix);
+ }
+
+ if (!gateway.empty())
+ {
+ ipmi::setDbusProperty(bus,
+ systemObject.second,
+ systemObject.first,
+ ipmi::network::SYSTEMCONFIG_INTERFACE,
+ "DefaultGateway",
+ std::string(gateway));
+ }
+ }
}
catch (InternalFailure& e)
{
log<level::ERR>("Failed to set network data",
entry("PREFIX=%d", prefix),
- entry("ADDRESS=%s", ipaddress),
- entry("GATEWAY=%s", gateway));
+ entry("ADDRESS=%s", ipaddress.c_str()),
+ entry("GATEWAY=%s", gateway.c_str()),
+ entry("VLANID=%d", vlanID),
+ entry("IPSRC=%d", channelConfig.ipsrc));
commit<InternalFailure>();
rc = IPMI_CC_UNSPECIFIED_ERROR;