multiple channel configuration support
Previously, the ipmi daemon only supported eth0 and hard-coded it
to channel 1. This allows one to map via a configuration. The
channel number provided is checked against a configuration to retrieve
the ethernet device identifier, e.g. eth0.
Tested: Ran on a quanta-q71l and was able to properly set MAC, IP,
Netmask, Gateway IP, and then verified the data was set for the eth1
via `ip addr show eth1`.
Change-Id: I92f63188297304e9454fd0d6fe32bc6cf84bb181
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/Makefile.am b/Makefile.am
index d4f43db..99808ab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,7 @@
libapphandlerdir = ${libdir}/ipmid-providers
libapphandler_LTLIBRARIES = libapphandler.la
libapphandler_la_SOURCES = \
+ net.cpp \
app/channel.cpp \
app/watchdog.cpp \
apphandler.cpp \
diff --git a/app/channel.cpp b/app/channel.cpp
index 91d9987..64cc6e9 100644
--- a/app/channel.cpp
+++ b/app/channel.cpp
@@ -2,6 +2,7 @@
#include "types.hpp"
#include "transporthandler.hpp"
#include "utils.hpp"
+#include "net.hpp"
#include <string>
#include <arpa/inet.h>
@@ -10,13 +11,22 @@
#include <phosphor-logging/elog-errors.hpp>
#include "xyz/openbmc_project/Common/error.hpp"
-extern struct ChannelConfig_t channelConfig;
-
constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+/** @struct SetChannelAccessRequest
+ *
+ * IPMI payload for Set Channel access command request.
+ */
+struct SetChannelAccessRequest
+{
+ uint8_t channelNumber; //!< Channel number.
+ uint8_t setting; //!< The setting values.
+ uint8_t privilegeLevelLimit; //!< The Privilege Level Limit
+} __attribute__((packed));
+
/** @struct GetChannelAccessRequest
*
* IPMI payload for Get Channel access command request.
@@ -54,6 +64,22 @@
ipmi::DbusObjectInfo ipObject;
ipmi::DbusObjectInfo systemObject;
+ if (*data_len < sizeof(SetChannelAccessRequest))
+ {
+ return IPMI_CC_INVALID;
+ }
+
+ auto requestData = reinterpret_cast<const SetChannelAccessRequest*>
+ (request);
+ int channel = requestData->channelNumber & CHANNEL_MASK;
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+ if (ethdevice.empty())
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
+ auto channelConf = getChannelConfig(channel);
+
// Todo: parse the request data if needed.
// Using Set Channel cmd to apply changes of Set Lan Cmd.
try
@@ -61,23 +87,23 @@
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("VLAN=%d", channelConfig.vlanID),
- entry("IPSRC=%d", channelConfig.ipsrc));
+ entry("PREFIX=%s", channelConf->netmask.c_str()),
+ entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
+ entry("GATEWAY=%s", channelConf->gateway.c_str()),
+ entry("VLAN=%d", channelConf->vlanID),
+ entry("IPSRC=%d", channelConf->ipsrc));
- if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
+ if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
{
//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;
+ channelConf->vlanID = le32toh(channelConf->vlanID);
+ vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
}
// if the asked ip src is DHCP then not interested in
// any given data except vlan.
- if (channelConfig.ipsrc != ipmi::network::IPOrigin::DHCP)
+ if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
{
// always get the system object
systemObject = ipmi::getDbusObject(
@@ -97,11 +123,10 @@
// if the system is having ip object,then
// get the IP object.
- ipObject = ipmi::getIPObject(
- bus,
- ipmi::network::IP_INTERFACE,
- ipmi::network::ROOT,
- ipmi::network::IP_TYPE);
+ ipObject = ipmi::getDbusObject(bus,
+ ipmi::network::IP_INTERFACE,
+ ipmi::network::ROOT,
+ ethIp);
// Get the parent interface of the IP object.
try
@@ -120,7 +145,7 @@
ipmi::network::ETHERNET_INTERFACE));
commit<InternalFailure>();
rc = IPMI_CC_UNSPECIFIED_ERROR;
- channelConfig.clear();
+ channelConf->clear();
return rc;
}
@@ -138,7 +163,7 @@
bus,
ipmi::network::ETHERNET_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE);
+ ethdevice);
networkInterfacePath = std::move(networkInterfaceObject.first);
}
@@ -154,21 +179,21 @@
// 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()) ||
+ if ((!channelConf->ipaddr.empty() &&
+ !channelConf->netmask.empty() &&
+ !channelConf->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)
+ ipaddress = channelConf->ipaddr;
+ prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
+ gateway = channelConf->gateway;
+ if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
{
//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;
+ channelConf->vlanID = le32toh(channelConf->vlanID);
+ vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
}
else
{
@@ -196,21 +221,20 @@
ipObject.first,
ipmi::network::IP_INTERFACE);
- ipaddress = channelConfig.ipaddr.empty() ?
+ ipaddress = channelConf->ipaddr.empty() ?
properties["Address"].get<std::string>() :
- channelConfig.ipaddr;
+ channelConf->ipaddr;
- prefix = channelConfig.netmask.empty() ?
+ prefix = channelConf->netmask.empty() ?
properties["PrefixLength"].get<uint8_t>() :
ipmi::network::toPrefix(AF_INET,
- channelConfig.netmask);
-
+ channelConf->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));
+ entry("MATCH=%s", ethIp));
}
auto systemProperties = ipmi::getAllDbusProperties(
@@ -219,10 +243,9 @@
systemObject.first,
ipmi::network::SYSTEMCONFIG_INTERFACE);
- gateway = channelConfig.gateway.empty() ?
+ gateway = channelConf->gateway.empty() ?
systemProperties["DefaultGateway"].get<std::string>() :
- channelConfig.gateway;
-
+ channelConf->gateway;
}
}
@@ -248,7 +271,7 @@
bus,
ipmi::network::ETHERNET_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE);
+ ethdevice);
// setting the physical interface mode to static.
ipmi::setDbusProperty(bus,
@@ -264,14 +287,14 @@
ipmi::deleteAllDbusObjects(bus,
ipmi::network::ROOT,
ipmi::network::IP_INTERFACE,
- ipmi::network::IP_TYPE);
+ ethIp);
if (vlanID)
{
ipmi::network::createVLAN(bus,
ipmi::network::SERVICE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE,
+ ethdevice,
vlanID);
auto networkInterfaceObject = ipmi::getDbusObject(
@@ -282,7 +305,7 @@
networkInterfacePath = networkInterfaceObject.first;
}
- if (channelConfig.ipsrc == ipmi::network::IPOrigin::DHCP)
+ if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
{
ipmi::setDbusProperty(bus,
ipmi::network::SERVICE,
@@ -330,13 +353,13 @@
entry("ADDRESS=%s", ipaddress.c_str()),
entry("GATEWAY=%s", gateway.c_str()),
entry("VLANID=%d", vlanID),
- entry("IPSRC=%d", channelConfig.ipsrc));
+ entry("IPSRC=%d", channelConf->ipsrc));
commit<InternalFailure>();
rc = IPMI_CC_UNSPECIFIED_ERROR;
}
- channelConfig.clear();
+ channelConf->clear();
return rc;
}
@@ -350,17 +373,15 @@
auto responseData = reinterpret_cast<GetChannelAccessResponse*>
(outPayload.data());
- // Channel 1 is arbitrarily assigned to ETH0 channel
- constexpr auto channelOne = 0x01;
-
/*
* The value Eh is used as a way to identify the current channel that
* the command is being received from.
*/
constexpr auto channelE = 0x0E;
+ int channel = requestData->channelNumber;
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
- if (requestData->channelNumber != channelOne &&
- requestData->channelNumber != channelE)
+ if (channel != channelE && ethdevice.empty())
{
*data_len = 0;
return IPMI_CC_INVALID_FIELD_REQUEST;
@@ -406,20 +427,20 @@
IPMI_CHANNEL_TYPE_IPMB,
1,0x41,0xA7,0x00,0,0};
uint8_t *p = (uint8_t*) request;
+ int channel = (*p) & CHANNEL_MASK;
+ std::string ethdevice = ipmi::network::ChanneltoEthernet(channel);
printf("IPMI APP GET CHANNEL INFO\n");
- // The supported channels numbers are 1 and 8.
+ // The supported channels numbers are those which are configured.
// Channel Number E is used as way to identify the current channel
// that the command is being is received from.
- if (*p == 0xe || *p == 1 || *p == 8) {
-
- *data_len = sizeof(resp);
- memcpy(response, resp, *data_len);
-
- } else {
+ if (channel != 0xe && ethdevice.empty()) {
rc = IPMI_CC_PARM_OUT_OF_RANGE;
*data_len = 0;
+ } else {
+ *data_len = sizeof(resp);
+ memcpy(response, resp, *data_len);
}
return rc;
diff --git a/net.cpp b/net.cpp
new file mode 100644
index 0000000..6c492a2
--- /dev/null
+++ b/net.cpp
@@ -0,0 +1,41 @@
+#include <map>
+#include <string>
+
+// Not sure if this should live in utils. Because it's really a per-system
+// configuration, instead of just hard-coding channel 1 to be eth0, one could
+// conceivably configure it however they pleased.
+//
+// In this design, channel 0 is the in-band host channel.
+
+namespace ipmi
+{
+namespace network
+{
+
+// This map should come from a configuration yaml.
+// Also, no need to really be a map, could be just an array
+// we index into by channel. :D
+std::map<int, std::string> ethDeviceMap = {
+ {1, "eth0"},
+ {2, "eth1"},
+};
+
+
+// Given a channel number, return a matching ethernet device, or empty string
+// if there is no match.
+// TODO provide this from a configuration:
+// https://github.com/openbmc/openbmc/issues/2667
+std::string ChanneltoEthernet(int channel)
+{
+ auto dev = ethDeviceMap.find(channel);
+ if (dev == ethDeviceMap.end())
+ {
+ return "";
+ }
+
+ return dev->second;
+}
+
+} // namespace network
+} // namespace ipmi
+
diff --git a/net.hpp b/net.hpp
new file mode 100644
index 0000000..21131b2
--- /dev/null
+++ b/net.hpp
@@ -0,0 +1,11 @@
+#include <string>
+
+namespace ipmi
+{
+namespace network
+{
+
+std::string ChanneltoEthernet(int channel);
+
+} // namespace network
+} // namespace ipmi
diff --git a/transporthandler.cpp b/transporthandler.cpp
index 50bc473..f4326c1 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -9,6 +9,7 @@
#include "ipmid.hpp"
#include "transporthandler.hpp"
#include "utils.hpp"
+#include "net.hpp"
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
@@ -23,7 +24,7 @@
const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
-struct ChannelConfig_t channelConfig;
+std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
@@ -31,13 +32,34 @@
void register_netfn_transport_functions() __attribute__((constructor));
+struct ChannelConfig_t* getChannelConfig(int channel)
+{
+ auto item = channelConfig.find(channel);
+ if (item == channelConfig.end())
+ {
+ channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
+ }
+
+ return channelConfig[channel].get();
+}
+
// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network Manager or
// Cache based on Set-In-Progress State
-ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data)
+ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
{
ipmi_ret_t rc = IPMI_CC_OK;
sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+ // if ethdevice is an empty string they weren't expecting this channel.
+ if (ethdevice.empty())
+ {
+ // TODO: return error from getNetworkData()
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
+ auto channelConf = getChannelConfig(channel);
+
try
{
switch (lan_param)
@@ -45,7 +67,7 @@
case LAN_PARM_IP:
{
std::string ipaddress;
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
try
{
@@ -53,7 +75,7 @@
bus,
ipmi::network::IP_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::IP_TYPE);
+ ethIP);
auto properties = ipmi::getAllDbusProperties(
bus,
@@ -62,7 +84,6 @@
ipmi::network::IP_INTERFACE);
ipaddress = properties["Address"].get<std::string>();
-
}
// ignore the exception, as it is a valid condtion that
// system is not confiured with any ip.
@@ -71,9 +92,9 @@
// nothing to do.
}
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- ipaddress = channelConfig.ipaddr;
+ ipaddress = channelConf->ipaddr;
}
inet_pton(AF_INET, ipaddress.c_str(),
@@ -85,7 +106,7 @@
{
std::string networkInterfacePath;
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
try
{
@@ -96,7 +117,7 @@
bus,
ipmi::network::IP_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::IP_TYPE);
+ ethIP);
// Get the parent interface of the IP object.
try
@@ -133,7 +154,7 @@
bus,
ipmi::network::ETHERNET_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE);
+ ethdevice);
networkInterfacePath = networkInterfaceObject.first;
}
@@ -152,9 +173,9 @@
memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- memcpy(data, &(channelConfig.ipsrc),
+ memcpy(data, &(channelConf->ipsrc),
ipmi::network::IPSRC_SIZE_BYTE);
}
}
@@ -163,7 +184,7 @@
case LAN_PARM_SUBNET:
{
unsigned long mask {};
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
try
{
@@ -191,9 +212,9 @@
}
memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- inet_pton(AF_INET, channelConfig.netmask.c_str(),
+ inet_pton(AF_INET, channelConf->netmask.c_str(),
reinterpret_cast<void*>(data));
}
@@ -204,7 +225,7 @@
{
std::string gateway;
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
try
{
@@ -230,9 +251,9 @@
}
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- gateway = channelConfig.gateway;
+ gateway = channelConf->gateway;
}
inet_pton(AF_INET, gateway.c_str(),
@@ -243,12 +264,13 @@
case LAN_PARM_MAC:
{
std::string macAddress;
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
auto macObjectInfo = ipmi::getDbusObject(
bus,
ipmi::network::MAC_INTERFACE,
- ipmi::network::ROOT);
+ ipmi::network::ROOT,
+ ethdevice);
auto variant = ipmi::getDbusProperty(
bus,
@@ -260,9 +282,9 @@
macAddress = variant.get<std::string>();
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- macAddress = channelConfig.macAddress;
+ macAddress = channelConf->macAddress;
}
sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
@@ -278,7 +300,7 @@
case LAN_PARM_VLAN:
{
uint16_t vlanID {};
- if (channelConfig.lan_set_in_progress == SET_COMPLETE)
+ if (channelConf->lan_set_in_progress == SET_COMPLETE)
{
try
{
@@ -308,9 +330,9 @@
memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
}
- else if (channelConfig.lan_set_in_progress == SET_IN_PROGRESS)
+ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
{
- memcpy(data, &(channelConfig.vlanID),
+ memcpy(data, &(channelConf->vlanID),
ipmi::network::VLAN_SIZE_BYTE);
}
}
@@ -364,6 +386,15 @@
auto reqptr = reinterpret_cast<const set_lan_t*>(request);
sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+ // channel number is the lower nibble
+ int channel = reqptr->channel & CHANNEL_MASK;
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+ if (ethdevice.empty())
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ auto channelConf = getChannelConfig(channel);
+
switch (reqptr->parameter)
{
case LAN_PARM_IP:
@@ -372,8 +403,7 @@
reqptr->data[0], reqptr->data[1],
reqptr->data[2], reqptr->data[3]);
- channelConfig.ipaddr.assign(ipaddr);
-
+ channelConf->ipaddr.assign(ipaddr);
}
break;
@@ -381,7 +411,7 @@
{
uint8_t ipsrc{};
memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
- channelConfig.ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
+ channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
}
break;
@@ -401,7 +431,7 @@
bus,
ipmi::network::MAC_INTERFACE,
ipmi::network::ROOT,
- ipmi::network::INTERFACE);
+ ethdevice);
ipmi::setDbusProperty(bus,
macObjectInfo.second,
@@ -410,8 +440,7 @@
"MACAddress",
std::string(mac));
- channelConfig.macAddress = mac;
-
+ channelConf->macAddress = mac;
}
break;
@@ -420,7 +449,7 @@
snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
reqptr->data[0], reqptr->data[1],
reqptr->data[2], reqptr->data[3]);
- channelConfig.netmask.assign(netmask);
+ channelConf->netmask.assign(netmask);
}
break;
@@ -429,8 +458,7 @@
snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
reqptr->data[0], reqptr->data[1],
reqptr->data[2], reqptr->data[3]);
- channelConfig.gateway.assign(gateway);
-
+ channelConf->gateway.assign(gateway);
}
break;
@@ -442,7 +470,7 @@
// We assume that ipmitool always send enable
// bit as 1.
vlan = le16toh(vlan);
- channelConfig.vlanID = vlan;
+ channelConf->vlanID = vlan;
}
break;
@@ -450,22 +478,20 @@
{
if (reqptr->data[0] == SET_COMPLETE)
{
- channelConfig.lan_set_in_progress = SET_COMPLETE;
+ channelConf->lan_set_in_progress = SET_COMPLETE;
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("VLAN=%d", channelConfig.vlanID));
+ entry("PREFIX=%s", channelConf->netmask.c_str()),
+ entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
+ entry("GATEWAY=%s", channelConf->gateway.c_str()),
+ entry("VLAN=%d", channelConf->vlanID));
log<level::INFO>("Use Set Channel Access command to apply");
-
}
else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
{
- channelConfig.lan_set_in_progress = SET_IN_PROGRESS;
+ channelConf->lan_set_in_progress = SET_IN_PROGRESS;
}
-
}
break;
@@ -473,7 +499,6 @@
{
rc = IPMI_CC_PARM_NOT_SUPPORTED;
}
-
}
return rc;
@@ -499,6 +524,8 @@
const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
get_lan_t *reqptr = (get_lan_t*) request;
+ // channel number is the lower nibble
+ int channel = reqptr->rev_channel & CHANNEL_MASK;
if (reqptr->rev_channel & 0x80) // Revision is bit 7
{
@@ -508,9 +535,16 @@
return IPMI_CC_OK;
}
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+ if (ethdevice.empty())
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ auto channelConf = getChannelConfig(channel);
+
if (reqptr->parameter == LAN_PARM_INPROGRESS)
{
- uint8_t buf[] = {current_revision, channelConfig.lan_set_in_progress};
+ uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
*data_len = sizeof(buf);
memcpy(response, &buf, *data_len);
}
@@ -536,7 +570,7 @@
*data_len = sizeof(current_revision);
memcpy(buf, ¤t_revision, *data_len);
- if (getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK)
+ if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
{
if (reqptr->parameter == LAN_PARM_MAC)
{
@@ -559,7 +593,7 @@
*data_len = sizeof(current_revision);
memcpy(buf, ¤t_revision, *data_len);
- if (getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK)
+ if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
{
*data_len = sizeof(buf);
memcpy(response, &buf, *data_len);
@@ -570,7 +604,7 @@
uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
*data_len = sizeof(current_revision);
memcpy(buff, ¤t_revision, *data_len);
- if (getNetworkData(reqptr->parameter, &buff[1]) == IPMI_CC_OK)
+ if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
{
*data_len = sizeof(buff);
memcpy(response, &buff, *data_len);
diff --git a/transporthandler.hpp b/transporthandler.hpp
index a101794..42bf717 100644
--- a/transporthandler.hpp
+++ b/transporthandler.hpp
@@ -32,6 +32,9 @@
constexpr uint8_t SET_COMMIT_WRITE = 2; //Optional
constexpr uint8_t SET_IN_PROGRESS_RESERVED = 3; //Reserved
+const int CHANNEL_MASK = 0x0f;
+const int NUM_CHANNELS = 0x0f;
+
struct ChannelConfig_t
{
std::string ipaddr;
@@ -56,3 +59,10 @@
lan_set_in_progress = SET_COMPLETE;
}
};
+
+// Given a channel, get the corresponding configuration,
+// or allocate it first.
+//
+// @param[in] channel the channel
+// @return the ChannelConfig_t pointer.
+struct ChannelConfig_t* getChannelConfig(int channel);
diff --git a/utils.hpp b/utils.hpp
index 55978fb..1699c52 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -161,7 +161,6 @@
constexpr auto ROOT = "/xyz/openbmc_project/network";
constexpr auto SERVICE = "xyz.openbmc_project.Network";
-constexpr auto INTERFACE = "eth0";
constexpr auto IP_TYPE = "ipv4";
constexpr auto IPV4_PREFIX = "169.254";
constexpr auto IPV6_PREFIX = "fe80";