diff options
author | Patrick Venture <venture@google.com> | 2017-11-15 14:29:18 -0800 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2017-12-12 05:31:12 +0000 |
commit | c7c1c3c2ff37a0e3d500e7eecd749595e8da7337 (patch) | |
tree | 39c7124d80eca76d316ea9a16793007bbd062848 | |
parent | ef7773ccd644cc2356f9a53295d3e58439329f3c (diff) | |
download | phosphor-host-ipmid-c7c1c3c2ff37a0e3d500e7eecd749595e8da7337.tar.gz phosphor-host-ipmid-c7c1c3c2ff37a0e3d500e7eecd749595e8da7337.zip |
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>
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | app/channel.cpp | 129 | ||||
-rw-r--r-- | net.cpp | 41 | ||||
-rw-r--r-- | net.hpp | 11 | ||||
-rw-r--r-- | transporthandler.cpp | 130 | ||||
-rw-r--r-- | transporthandler.hpp | 10 | ||||
-rw-r--r-- | utils.hpp | 1 |
7 files changed, 220 insertions, 103 deletions
diff --git a/Makefile.am b/Makefile.am index d4f43db..99808ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,7 @@ fru-read-gen.cpp: 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_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, // 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_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, ipmi::network::ETHERNET_INTERFACE)); commit<InternalFailure>(); rc = IPMI_CC_UNSPECIFIED_ERROR; - channelConfig.clear(); + channelConf->clear(); return rc; } @@ -138,7 +163,7 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, bus, ipmi::network::ETHERNET_INTERFACE, ipmi::network::ROOT, - ipmi::network::INTERFACE); + ethdevice); networkInterfacePath = std::move(networkInterfaceObject.first); } @@ -154,21 +179,21 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, // 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_get_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 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_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 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; @@ -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 + @@ -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 @@ namespace fs = std::experimental::filesystem; 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, - ipmi::network::IP_TYPE); + ethIP); auto properties = ipmi::getAllDbusProperties( bus, @@ -62,7 +84,6 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) // 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) { std::string networkInterfacePath; - if (channelConfig.lan_set_in_progress == SET_COMPLETE) + if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { @@ -96,7 +117,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) bus, ipmi::network::ETHERNET_INTERFACE, ipmi::network::ROOT, - ipmi::network::INTERFACE); + ethdevice); networkInterfacePath = networkInterfaceObject.first; } @@ -152,9 +173,9 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) } 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) { std::string gateway; - if (channelConfig.lan_set_in_progress == SET_COMPLETE) + if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { @@ -230,9 +251,9 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) } } - 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, { 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, bus, ipmi::network::MAC_INTERFACE, ipmi::network::ROOT, - ipmi::network::INTERFACE); + ethdevice); ipmi::setDbusProperty(bus, macObjectInfo.second, @@ -410,8 +440,7 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, "MACAddress", std::string(mac)); - channelConfig.macAddress = mac; - + channelConf->macAddress = mac; } break; @@ -420,7 +449,7 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, // We assume that ipmitool always send enable // bit as 1. vlan = le16toh(vlan); - channelConfig.vlanID = vlan; + channelConf->vlanID = vlan; } break; @@ -450,22 +478,20 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, { 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 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, { rc = IPMI_CC_PARM_NOT_SUPPORTED; } - } return rc; @@ -499,6 +524,8 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, 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 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, *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 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, *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 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, 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_IN_PROGRESS = 1; 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 @@ struct ChannelConfig_t 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); @@ -161,7 +161,6 @@ namespace network 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"; |