summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apphandler.cpp47
-rw-r--r--transporthandler.cpp61
-rw-r--r--transporthandler.hpp9
-rw-r--r--types.hpp3
-rw-r--r--utils.cpp57
-rw-r--r--utils.hpp23
6 files changed, 187 insertions, 13 deletions
diff --git a/apphandler.cpp b/apphandler.cpp
index 7b30edd..2251e8c 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -17,7 +17,6 @@
#include <phosphor-logging/elog-errors.hpp>
#include "xyz/openbmc_project/Common/error.hpp"
-
extern sd_bus *bus;
constexpr auto app_obj = "/org/openbmc/NetworkManager/Interface";
@@ -535,6 +534,7 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
std::string ipaddress;
std::string gateway;
uint8_t prefix {};
+ uint32_t vlanID {};
// Todo: parse the request data if needed.
@@ -574,9 +574,21 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
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);
+ }
+
}
else
{
+ // We have partial filled cache so get the remaning
+ // info from the system.
+
// 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
@@ -585,7 +597,6 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
// if system is not having any ip object don't throw error,
try
{
-
auto ipObjectInfo = ipmi::getDbusObject(bus,
ipmi::network::IP_INTERFACE,
ipmi::network::ROOT,
@@ -605,6 +616,18 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
ipmi::network::toPrefix(AF_INET,
channelConfig.netmask);
+ 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);
+ }
+ else
+ {
+ vlanID = ipmi::network::getVLAN(ipObjectInfo.first);
+ }
+
}
catch (InternalFailure& e)
{
@@ -626,7 +649,7 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
}
// Currently network manager doesn't support purging of all the
- // ip addresses from the parent interface,
+ // ip addresses and the vlan interfaces from the parent interface,
// TODO once the support is there, will make the change here.
// https://github.com/openbmc/openbmc/issues/2141.
@@ -634,11 +657,24 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
// Multiple interface through
// https://github.com/openbmc/openbmc/issues/2138
- //delete all the ipv4 addresses
-
+ //delete all the vlan interfaces
+ //delete all the ipv4 addresses
+ ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
+ ipmi::network::VLAN_INTERFACE);
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::ROOT,
+ ipmi::network::INTERFACE, vlanID);
+
+ networkInterfaceObject = ipmi::getDbusObject(
+ bus,
+ ipmi::network::VLAN_INTERFACE,
+ ipmi::network::ROOT);
+ }
ipmi::network::createIP(bus, networkInterfaceObject.second,
networkInterfaceObject.first,
@@ -664,6 +700,7 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
return rc;
}
+
// ATTENTION: This ipmi function is very hardcoded on purpose
// OpenBMC does not fully support IPMI. This command is useful
// to have around because it enables testing of interfaces with
diff --git a/transporthandler.cpp b/transporthandler.cpp
index 4de9400..30526b3 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -49,6 +49,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data)
{
ipmi_ret_t rc = IPMI_CC_OK;
sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
try
{
switch (lan_param)
@@ -180,6 +181,37 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data)
}
break;
+ case LAN_PARM_VLAN:
+ {
+ if (lan_set_in_progress == SET_COMPLETE)
+ {
+ auto ipObjectInfo = ipmi::getDbusObject(
+ bus,
+ ipmi::network::IP_INTERFACE,
+ ipmi::network::ROOT,
+ ipmi::network::IP_TYPE);
+
+ auto vlanID = static_cast<uint16_t>(
+ ipmi::network::getVLAN(ipObjectInfo.first));
+
+ vlanID = htole16(vlanID);
+
+ if (vlanID)
+ {
+ //Enable the 16th bit
+ vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
+ }
+
+ memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
+ }
+ else if (lan_set_in_progress == SET_IN_PROGRESS)
+ {
+ memcpy(data, &(channelConfig.vlanID),
+ ipmi::network::VLAN_SIZE_BYTE);
+ }
+ }
+ break;
+
default:
rc = IPMI_CC_PARM_OUT_OF_RANGE;
}
@@ -290,6 +322,18 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
}
break;
+ case LAN_PARM_VLAN:
+ {
+ uint16_t vlan {};
+ memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
+ // We are not storing the enable bit
+ // We assume that ipmitool always send enable
+ // bit as 1.
+ vlan = le16toh(vlan);
+ channelConfig.vlanID = vlan;
+ }
+ break;
+
case LAN_PARM_INPROGRESS:
{
if (reqptr->data[0] == SET_COMPLETE)
@@ -299,7 +343,8 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
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));
log<level::INFO>("Use Set Channel Access command to apply");
@@ -314,8 +359,6 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
default:
{
- log<level::ERR>("Unsupported parameter",
- entry("PARAMETER=0x%x", reqptr->parameter));
rc = IPMI_CC_PARM_NOT_SUPPORTED;
}
@@ -398,6 +441,18 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn,
rc = IPMI_CC_UNSPECIFIED_ERROR;
}
}
+ else if (reqptr->parameter == LAN_PARM_VLAN)
+ {
+ uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1];
+
+ *data_len = sizeof(current_revision);
+ memcpy(buf, &current_revision, *data_len);
+ if (getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK)
+ {
+ *data_len = sizeof(buf);
+ memcpy(response, &buf, *data_len);
+ }
+ }
else
{
log<level::ERR>("Unsupported parameter",
diff --git a/transporthandler.hpp b/transporthandler.hpp
index f1fd410..24ee8be 100644
--- a/transporthandler.hpp
+++ b/transporthandler.hpp
@@ -1,7 +1,7 @@
#pragma once
+#include "types.hpp"
#include <string>
-
// IPMI commands for Transport net functions.
enum ipmi_netfn_storage_cmds
{
@@ -24,6 +24,7 @@ static const int LAN_PARM_IP = 3;
static const int LAN_PARM_MAC = 5;
static const int LAN_PARM_SUBNET = 6;
static const int LAN_PARM_GATEWAY = 12;
+static const int LAN_PARM_VLAN = 20;
struct ChannelConfig_t
{
@@ -31,11 +32,17 @@ struct ChannelConfig_t
std::string netmask;
std::string gateway;
std::string macAddress;
+ // IPMI stores the vlan info in 16 bits,32 bits is to aligned
+ // with phosphor-dbus interfaces.
+ // vlan id is in 12 bits and the 16th bit is for enable mask.
+ uint32_t vlanID = ipmi::network::VLAN_ID_MASK;
+
void clear()
{
ipaddr.clear();
netmask.clear();
gateway.clear();
macAddress.clear();
+ vlanID = ipmi::network::VLAN_ID_MASK;
}
};
diff --git a/types.hpp b/types.hpp
index 5b39c38..d3c8dc6 100644
--- a/types.hpp
+++ b/types.hpp
@@ -108,8 +108,11 @@ constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00";
constexpr auto DEFAULT_ADDRESS = "0.0.0.0";
constexpr auto MAC_ADDRESS_SIZE_BYTE = 6;
+constexpr auto VLAN_SIZE_BYTE = 2;
constexpr auto BITS_32 = 32;
constexpr auto MASK_32_BIT = 0xFFFFFFFF;
+constexpr auto VLAN_ID_MASK = 0x00000FFF;
+constexpr auto VLAN_ENABLE_MASK = 0x8000;
}//namespace network
}//namespace ipmi
diff --git a/utils.cpp b/utils.cpp
index 11dc2d4..2e6c5e7 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -339,6 +339,32 @@ void createIP(sdbusplus::bus::bus& bus,
}
+void createVLAN(sdbusplus::bus::bus& bus,
+ const std::string& service,
+ const std::string& objPath,
+ const std::string& interfaceName,
+ uint32_t vlanID)
+{
+ auto busMethod = bus.new_method_call(
+ service.c_str(),
+ objPath.c_str(),
+ VLAN_CREATE_INTERFACE,
+ "VLAN");
+
+ busMethod.append(interfaceName, vlanID);
+
+ auto reply = bus.call(busMethod);
+
+ if (reply.is_method_error())
+ {
+ log<level::ERR>("Failed to excute method",
+ entry("METHOD=%s", "VLAN"),
+ entry("PATH=%s", objPath.c_str()));
+ elog<InternalFailure>();
+ }
+
+}
+
uint8_t toPrefix(int addressFamily, const std::string& subnetMask)
{
if (addressFamily == AF_INET6)
@@ -370,7 +396,34 @@ uint8_t toPrefix(int addressFamily, const std::string& subnetMask)
}
}
-} // namespace network
-} // namespace ipmi
+uint32_t getVLAN(const std::string& path)
+{
+ // Path would be look like
+ // /xyz/openbmc_project/network/eth0_443/ipv4
+
+ uint32_t vlanID = 0;
+ try
+ {
+ auto intfObjectPath = path.substr(0,
+ path.find(IP_TYPE) - 1);
+
+ auto intfName = intfObjectPath.substr(intfObjectPath.rfind("/") + 1);
+ auto index = intfName.find("_");
+ if (index != std::string::npos)
+ {
+ auto str = intfName.substr(index + 1);
+ vlanID = std::stoul(str);
+ }
+ }
+ catch (std::exception & e)
+ {
+ log<level::ERR>("Exception occured during getVLAN",
+ entry("PATH=%s",path.c_str()),
+ entry("EXCEPTIOn=%s", e.what()));
+ }
+ return vlanID;
+}
+} // namespace network
+} // namespace ipmi
diff --git a/utils.hpp b/utils.hpp
index cb64a25..a172e22 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -135,7 +135,7 @@ namespace network
{
constexpr auto ROOT = "/xyz/openbmc_project/network";
-constexpr auto NETWORK_SERVICE = "xyz.openbmc_project.Network";
+constexpr auto SERVICE = "xyz.openbmc_project.Network";
constexpr auto INTERFACE = "eth0";
constexpr auto IP_TYPE = "ipv4";
constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
@@ -143,6 +143,8 @@ constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
constexpr auto SYSTEMCONFIG_INTERFACE = "xyz.openbmc_project.Network.SystemConfiguration";
constexpr auto ETHERNET_INTERFACE = "xyz.openbmc_project.Network.EthernetInterface";
constexpr auto IP_CREATE_INTERFACE = "xyz.openbmc_project.Network.IP.Create";
+constexpr auto VLAN_CREATE_INTERFACE = "xyz.openbmc_project.Network.VLAN.Create";
+constexpr auto VLAN_INTERFACE = "xyz.openbmc_project.Network.VLAN";
/* @brief converts the given subnet into prefix notation.
* @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
@@ -167,8 +169,25 @@ void createIP(sdbusplus::bus::bus& bus,
const std::string& ipaddress,
uint8_t prefix);
-}//namespace network
+/** @brief Creates the VLAN on the given interface.
+ * @param[in] bus - DBUS Bus Object.
+ * @param[in] service - Dbus service name.
+ * @param[in] objPath - Dbus object path.
+ * @param[in] interface - EthernetInterface.
+ * @param[in] vlanID - Vlan ID.
+ */
+void createVLAN(sdbusplus::bus::bus& bus,
+ const std::string& service,
+ const std::string& objPath,
+ const std::string& interface,
+ uint32_t vlanID);
+
+/** @brief Gets the vlan id from the given object path.
+ * @param[in] path - Dbus object path.
+ */
+uint32_t getVLAN(const std::string& path);
+} //namespace network
} // namespace ipmi
OpenPOWER on IntegriCloud