diff options
-rw-r--r-- | apphandler.cpp | 47 | ||||
-rw-r--r-- | transporthandler.cpp | 61 | ||||
-rw-r--r-- | transporthandler.hpp | 9 | ||||
-rw-r--r-- | types.hpp | 3 | ||||
-rw-r--r-- | utils.cpp | 57 | ||||
-rw-r--r-- | utils.hpp | 23 |
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, ¤t_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; } }; @@ -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 @@ -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 @@ -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 |