diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch | 877 |
1 files changed, 877 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch new file mode 100644 index 000000000..c862a306a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch @@ -0,0 +1,877 @@ +From c20bc8eb6a08d177d951012eb91b37398b15d81d Mon Sep 17 00:00:00 2001 +From: Vernon Mauery <vernon.mauery@linux.intel.com> +Date: Tue, 27 Nov 2018 11:01:15 -0800 +Subject: [PATCH] IPv6 Network changes + +Allow IPv6 IPMI set/get commands + +Signed-off-by: David Cobbley <david.j.cobbley@linux.intel.com> +Signed-off-by: Yong Li <yong.b.li@linux.intel.com> +Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com> + +Change-Id: If5528d3b7294c5f8c17db5919439235d0fad0446 +--- + include/ipmid/types.hpp | 9 + + include/ipmid/utils.hpp | 1 + + transporthandler.cpp | 654 +++++++++++++++++++++++++++++++++++++++- + transporthandler.hpp | 50 +++ + 4 files changed, 713 insertions(+), 1 deletion(-) + +Index: phosphor-host-ipmid.clean/include/ipmid/types.hpp +=================================================================== +--- phosphor-host-ipmid.clean.orig/include/ipmid/types.hpp ++++ phosphor-host-ipmid.clean/include/ipmid/types.hpp +@@ -224,6 +224,7 @@ constexpr auto ADDR_TYPE_FORMAT = "%hhx" + + constexpr auto IPV4_ADDRESS_SIZE_BYTE = 4; + constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16; ++constexpr auto IPV6_ADDRESS_STATUS_SIZE = 22; + + constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00"; + constexpr auto DEFAULT_ADDRESS = "0.0.0.0"; +@@ -235,6 +236,7 @@ constexpr auto BITS_32 = 32; + constexpr auto MASK_32_BIT = 0xFFFFFFFF; + constexpr auto VLAN_ID_MASK = 0x00000FFF; + constexpr auto VLAN_ENABLE_MASK = 0x8000; ++constexpr auto IPV6_DUID_SIZE = 18; + + enum class IPOrigin : uint8_t + { +@@ -243,5 +245,12 @@ enum class IPOrigin : uint8_t + DHCP = 2, + }; + ++enum class AddressingEnables : uint8_t ++{ ++ IPv4Only = 0, ++ IPv6Only = 1, ++ IPv4AndIPv6 = 2, ++}; ++ + } // namespace network + } // namespace ipmi +Index: phosphor-host-ipmid.clean/include/ipmid/utils.hpp +=================================================================== +--- phosphor-host-ipmid.clean.orig/include/ipmid/utils.hpp ++++ phosphor-host-ipmid.clean/include/ipmid/utils.hpp +@@ -256,6 +256,7 @@ namespace network + constexpr auto ROOT = "/xyz/openbmc_project/network"; + constexpr auto SERVICE = "xyz.openbmc_project.Network"; + constexpr auto IP_TYPE = "ipv4"; ++constexpr auto IPV6_TYPE = "ipv6"; + constexpr auto IPV4_PREFIX = "169.254"; + constexpr auto IPV6_PREFIX = "fe80"; + constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP"; +Index: phosphor-host-ipmid.clean/transporthandler.cpp +=================================================================== +--- phosphor-host-ipmid.clean.orig/transporthandler.cpp ++++ phosphor-host-ipmid.clean/transporthandler.cpp +@@ -29,6 +29,12 @@ std::unique_ptr<phosphor::Timer> network + + const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx + constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; ++constexpr auto ipv6Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv6"; ++ ++static const std::array<std::string, 3> ipAddressEnablesType = { ++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4Only", ++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv6Only", ++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4AndIPv6"}; + + std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig; + +@@ -445,6 +451,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + { + case LanParam::IP: + { ++ if (reqLen != lanParamIPSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + std::snprintf(ipaddr, INET_ADDRSTRLEN, + ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0], + reqptr->data[1], reqptr->data[2], reqptr->data[3]); +@@ -455,6 +466,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + + case LanParam::IPSRC: + { ++ if (reqLen != lanParamIPSrcSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + uint8_t ipsrc{}; + std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE); + channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc); +@@ -463,6 +479,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + + case LanParam::MAC: + { ++ if (reqLen != lanParamMACSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + char mac[SIZE_MAC]; + + std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT, +@@ -483,6 +504,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + + case LanParam::SUBNET: + { ++ if (reqLen != lanParamSubnetSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + std::snprintf(netmask, INET_ADDRSTRLEN, + ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0], + reqptr->data[1], reqptr->data[2], reqptr->data[3]); +@@ -492,6 +518,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + + case LanParam::GATEWAY: + { ++ if (reqLen != lanParamGatewaySize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + std::snprintf(gateway, INET_ADDRSTRLEN, + ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0], + reqptr->data[1], reqptr->data[2], reqptr->data[3]); +@@ -522,6 +553,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + + case LanParam::INPROGRESS: + { ++ if (reqLen != lanParamInProgressSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ + if (reqptr->data[0] == SET_COMPLETE) + { + channelConf->lan_set_in_progress = SET_COMPLETE; +@@ -540,6 +576,122 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n + } + break; + ++ case LanParam::IPV6_AND_IPV4_ENABLES: ++ { ++ if (reqLen != lanParamIPv6AndIPv4EnablesSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ channelConf->ipv6AddressingEnables = reqptr->data[0]; ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ADDRESSES: ++ { ++ if (reqLen != lanParamIPv6StaticAddressesSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ channelConf->ipv6AddressSource = ++ reqptr->data[1] & 0x81; // Looking at bit 0 and bit 7 ++ char tmpIPV6[INET6_ADDRSTRLEN]; ++ inet_ntop(AF_INET6, &reqptr->data[2], tmpIPV6, INET6_ADDRSTRLEN); ++ channelConf->ipv6Addr.assign(tmpIPV6); ++ channelConf->ipv6Prefix = reqptr->data[19]; ++ break; ++ } ++ ++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL: ++ { ++ if (reqLen != lanParamIPv6RouterAddressConfCtrlSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ channelConf->ipv6RouterAddressConfigControl = reqptr->data[0]; ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR: ++ { ++ if (reqLen != lanParamIPv6StaticRouter1IPAddrSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ char tmpIPV6[INET6_ADDRSTRLEN]; ++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data), ++ tmpIPV6, INET6_ADDRSTRLEN); ++ channelConf->ipv6GatewayAddr.assign(tmpIPV6); ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN: ++ { ++ if (reqLen != lanParamIPv6StaticRouter1PrefixLenSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ channelConf->ipv6GatewayPrefixLength = reqptr->data[0]; ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL: ++ { ++ if (reqLen != lanParamIPv6StaticRouter1PrefixValSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ char tmpIPV6[INET6_ADDRSTRLEN]; ++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data), ++ tmpIPV6, INET6_ADDRSTRLEN); ++ channelConf->ipv6GatewayPrefixValue.assign(tmpIPV6); ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR: ++ { ++ if (reqLen != lanParamIPv6StaticRouter2IPAddrSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ char tmpIPV6[INET6_ADDRSTRLEN]; ++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data), ++ tmpIPV6, INET6_ADDRSTRLEN); ++ channelConf->ipv6BackupGatewayAddr.assign(tmpIPV6); ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN: ++ { ++ if (reqLen != lanParamIPv6StaticRouter2PrefixLenSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ channelConf->ipv6BackupGatewayPrefixLength = reqptr->data[0]; ++ break; ++ } ++ ++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL: ++ { ++ if (reqLen != lanParamIPv6StaticRouter2PrefixValSize) ++ { ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ ++ char tmpIPV6[INET6_ADDRSTRLEN]; ++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data), ++ tmpIPV6, INET6_ADDRSTRLEN); ++ channelConf->ipv6BackupGatewayPrefixValue.assign(tmpIPV6); ++ break; ++ } ++ + default: + { + rc = IPMI_CC_PARM_NOT_SUPPORTED; +@@ -568,6 +720,7 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_n + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 ++ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + + get_lan_t* reqptr = (get_lan_t*)request; + // channel number is the lower nibble +@@ -713,6 +866,476 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_n + static_cast<uint8_t>(cipherList.size()); + break; + } ++ case LanParam::IPV6_AND_IPV4_SUPPORTED: ++ { ++ uint8_t addressSupport = ++ 0x1; // Allow both IPv4 & IPv6 simultaneously ++ std::array<uint8_t, 2> buf = {current_revision, addressSupport}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_AND_IPV4_ENABLES: ++ { ++ // If DHCP, check if you have an ipv6 and ipv4 address. If static ++ // return not supported ++ ++ // 00h check if conf DHCP == ipv4 or off ++ // 01h check if conf DHCP == ipv6 ++ // 02h check if DHCP == true ++ ++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE; ++ std::string networkInterfacePath; ++ uint8_t ipVAddressEnables = 0; ++ ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ try ++ { ++ ipmi::ObjectTree ancestorMap; ++ // if the system has an ip object,then ++ // get the IP object. ++ auto ipObject = ++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE, ++ ipmi::network::ROOT, ethIP); ++ // Get the parent interface of the IP object. ++ try ++ { ++ ipmi::InterfaceList interfaces; ++ interfaces.emplace_back( ++ ipmi::network::ETHERNET_INTERFACE); ++ ++ 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)); ++ return IPMI_CC_UNSPECIFIED_ERROR; ++ } ++ // for an ip object there would be single parent ++ // interface. ++ networkInterfacePath = ancestorMap.begin()->first; ++ } ++ catch (InternalFailure& e) ++ { ++ // 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, ethdevice); ++ ++ networkInterfacePath = networkInterfaceObject.first; ++ } ++ ++ ipmi::Value ipEnablesProp = ipmi::getDbusProperty( ++ bus, ipmi::network::SERVICE, networkInterfacePath, ++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables"); ++ std::string ipEnables = std::get<std::string>(ipEnablesProp); ++ ++ // check if on off ipv4 ipv6, etc. ++ bool found = false; ++ for (uint8_t ii = 0; ii < ipAddressEnablesType.size(); ii++) ++ { ++ if (ipEnables == ipAddressEnablesType[ii]) ++ { ++ ipVAddressEnables = ii; ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ { ++ return IPMI_CC_PARM_NOT_SUPPORTED; ++ } ++ } ++ else ++ { ++ ipVAddressEnables = channelConf->ipv6AddressingEnables; ++ } ++ ++ std::array<uint8_t, 2> buf = {current_revision, ipVAddressEnables}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATUS: ++ { ++ // Number of IPV6 addresses that are supported ++ constexpr std::array<uint8_t, 3> statusData = {1, 1, 3}; ++ ++ std::array<uint8_t, 4> buf = {current_revision, statusData[0], ++ statusData[1], statusData[2]}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ADDRESSES: ++ { ++ // Only return set selector 0 ++ uint8_t ipv6SetSelector = 0; ++ std::string ipaddress; ++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE; ++ uint8_t ipv6AddressSource = 0; ++ uint8_t prefixLength = 0; ++ uint8_t status = 0; ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ try ++ { ++ auto ipObjectInfo = ++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE, ++ ipmi::network::ROOT, ethIP); ++ ++ auto properties = ipmi::getAllDbusProperties( ++ bus, ipObjectInfo.second, ipObjectInfo.first, ++ ipmi::network::IP_INTERFACE); ++ ++ if (std::get<std::string>(properties["Origin"]) == ++ "xyz.openbmc_project.Network.IP.AddressOrigin.Static") ++ { ++ ipaddress = ++ std::get<std::string>(properties["Address"]); ++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7 ++ prefixLength = ++ std::get<uint8_t>(properties["PrefixLength"]); ++ status = 0; ++ } ++ } ++ // ignore the exception, as it is a valid condition that ++ // the system is not configured with any IP. ++ catch (InternalFailure& e) ++ { ++ // nothing to do. ++ } ++ } ++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) ++ { ++ ipv6AddressSource = channelConf->ipv6AddressSource; ++ ipaddress = channelConf->ipv6Addr.c_str(); ++ prefixLength = channelConf->ipv6Prefix; ++ status = 1; ++ } ++ ++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_STATUS_SIZE> buf = { ++ current_revision, ipv6SetSelector, ipv6AddressSource}; ++ inet_pton(AF_INET6, ipaddress.c_str(), ++ reinterpret_cast<void*>(&buf[3])); ++ buf[20] = prefixLength; ++ buf[21] = status; ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_DHCPV6_STATIC_DUID_STORAGE_LENGTH: ++ { ++ // DHCP unique identified ++ // Only 1 read-only 16-byte Block needed ++ uint8_t duidLength = 1; ++ std::array<uint8_t, 2> buf = {current_revision, duidLength}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_DHCPV6_STATIC_DUIDS: ++ { ++ std::string macAddress; ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ auto macObjectInfo = ++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE, ++ ipmi::network::ROOT, ethdevice); ++ ++ auto variant = ipmi::getDbusProperty( ++ bus, macObjectInfo.second, macObjectInfo.first, ++ ipmi::network::MAC_INTERFACE, "MACAddress"); ++ ++ macAddress = std::get<std::string>(variant); ++ } ++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) ++ { ++ macAddress = channelConf->macAddress; ++ } ++ ++ std::array<uint8_t, ++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)> ++ buf; ++ buf = {current_revision, ++ reqptr->parameter_set, ++ reqptr->parameter_block, ++ DUID_LEN, ++ 0, // Filler byte ++ DUID_LL_TYPE, ++ 0, // Filler byte ++ DUIC_ETH_HW_TYPE}; ++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, ++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]), ++ (&buf[13])); ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_DYNAMIC_ADDRESSES: ++ { ++ std::string ipaddress; ++ uint8_t ipv6AddressSource = 0; ++ uint8_t prefixLength = 0; ++ uint8_t status = 0; ++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE; ++ ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ try ++ { ++ auto ipObjectInfo = ++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE, ++ ipmi::network::ROOT, ethIP); ++ ++ auto properties = ipmi::getAllDbusProperties( ++ bus, ipObjectInfo.second, ipObjectInfo.first, ++ ipmi::network::IP_INTERFACE); ++ ++ if (std::get<std::string>(properties["Origin"]) == ++ "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") ++ { ++ ipaddress = ++ std::get<std::string>(properties["Address"]); ++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7 ++ prefixLength = ++ std::get<uint8_t>(properties["PrefixLength"]); ++ status = 0; ++ } ++ else ++ { ++ status = 1; ++ } ++ } ++ // ignore the exception, as it is a valid condition that ++ // the system is not configured with any IP. ++ catch (InternalFailure& e) ++ { ++ // nothing to do. ++ } ++ } ++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) ++ { ++ ipaddress = channelConf->ipv6Addr; ++ ipv6AddressSource = channelConf->ipv6AddressSource; ++ prefixLength = channelConf->ipv6Prefix; ++ status = channelConf->ipv6AddressStatus; ++ } ++ ++ uint8_t ipv6SetSelector = 0; ++ std::array<uint8_t, 22> buf = {current_revision, ipv6SetSelector, ++ ipv6AddressSource}; ++ inet_pton(AF_INET6, ipaddress.c_str(), ++ reinterpret_cast<void*>(&buf[3])); ++ buf[20] = prefixLength; ++ buf[21] = status; ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUID_STOR_LEN: ++ { ++ uint8_t duidLength = 0; ++ // Only 1 read-only 16-byte Block needed ++ duidLength = 1; ++ ++ std::array<uint8_t, 2> buf = {current_revision, duidLength}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUIDS: ++ { ++ std::string macAddress; ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ auto macObjectInfo = ++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE, ++ ipmi::network::ROOT, ethdevice); ++ ++ auto variant = ipmi::getDbusProperty( ++ bus, macObjectInfo.second, macObjectInfo.first, ++ ipmi::network::MAC_INTERFACE, "MACAddress"); ++ ++ macAddress = std::get<std::string>(variant); ++ } ++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) ++ { ++ macAddress = channelConf->macAddress; ++ } ++ ++ std::array<uint8_t, ++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)> ++ buf; ++ buf = {current_revision, ++ reqptr->parameter_set, ++ reqptr->parameter_block, ++ DUID_LEN, ++ 0, // Filler byte ++ DUID_LL_TYPE, ++ 0, // Filler byte ++ DUIC_ETH_HW_TYPE}; ++ ++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, ++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]), ++ (&buf[13])); ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL: ++ { ++ // Determine if automated router discovery occurs when static ++ // addresses are used for the bmc ++ ++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE; ++ std::string networkInterfacePath; ++ uint8_t dynamicRA; ++ if (channelConf->lan_set_in_progress == SET_COMPLETE) ++ { ++ ++ try ++ { ++ ipmi::ObjectTree ancestorMap; ++ // if the system is having ip object,then ++ // get the IP object. ++ auto ipObject = ++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE, ++ ipmi::network::ROOT, ethIP); ++ ++ // Get the parent interface of the IP object. ++ try ++ { ++ ipmi::InterfaceList interfaces; ++ interfaces.emplace_back( ++ ipmi::network::ETHERNET_INTERFACE); ++ ++ 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)); ++ return IPMI_CC_UNSPECIFIED_ERROR; ++ } ++ // for an ip object there would be single parent ++ // interface. ++ networkInterfacePath = ancestorMap.begin()->first; ++ } ++ catch (InternalFailure& e) ++ { ++ // 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, ethdevice); ++ ++ networkInterfacePath = networkInterfaceObject.first; ++ } ++ ++ auto variant = ipmi::getDbusProperty( ++ bus, ipmi::network::SERVICE, networkInterfacePath, ++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA"); ++ dynamicRA = std::get<bool>(variant); ++ } ++ else ++ { ++ dynamicRA = channelConf->ipv6RouterAddressConfigControl; ++ } ++ ++ std::array<uint8_t, 2> buf = {current_revision, dynamicRA}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR: ++ { ++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE + ++ sizeof(current_revision)> ++ buf = {current_revision}; ++ inet_pton(AF_INET6, channelConf->ipv6GatewayAddr.c_str(), ++ reinterpret_cast<void*>(&buf[1])); ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN: ++ { ++ std::array<uint8_t, 2> buf = {current_revision, ++ channelConf->ipv6GatewayPrefixLength}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL: ++ { ++ constexpr uint8_t setSelector = 0; ++ std::array<uint8_t, sizeof(setSelector) + ++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE + ++ sizeof(current_revision)> ++ buf = {current_revision, setSelector}; ++ ++ inet_pton(AF_INET6, channelConf->ipv6GatewayPrefixValue.c_str(), ++ reinterpret_cast<void*>(&buf[2])); ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR: ++ { ++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE + ++ sizeof(current_revision)> ++ buf = {current_revision}; ++ inet_pton(AF_INET6, channelConf->ipv6BackupGatewayAddr.c_str(), ++ reinterpret_cast<void*>(&buf[1])); ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN: ++ { ++ std::array<uint8_t, 2> buf = { ++ current_revision, channelConf->ipv6BackupGatewayPrefixLength}; ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } ++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL: ++ { ++ ++ constexpr uint8_t setSelector = 0; ++ std::array<uint8_t, sizeof(setSelector) + ++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE + ++ sizeof(current_revision)> ++ buf = {current_revision, setSelector}; ++ inet_pton(AF_INET6, ++ channelConf->ipv6BackupGatewayPrefixValue.c_str(), ++ reinterpret_cast<void*>(&buf[2])); ++ ++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response)); ++ *data_len = buf.size(); ++ break; ++ } + default: + log<level::ERR>("Unsupported parameter", + entry("PARAMETER=0x%x", reqptr->parameter)); +@@ -957,6 +1580,16 @@ void applyChanges(int channel) + ipaddress, prefix); + } + ++ if (!channelConf->ipv6Addr.empty() && ++ channelConf->ipv6AddressSource == ++ 0x80) // Check if IPv6 static addresses are enabled ++ { ++ ipmi::network::createIP(bus, ipmi::network::SERVICE, ++ networkInterfacePath, ipv6Protocol, ++ channelConf->ipv6Addr, ++ channelConf->ipv6Prefix); ++ } ++ + if (!gateway.empty()) + { + ipmi::setDbusProperty(bus, systemObject.second, +@@ -964,7 +1597,24 @@ void applyChanges(int channel) + ipmi::network::SYSTEMCONFIG_INTERFACE, + "DefaultGateway", std::string(gateway)); + } ++ else if (!channelConf->ipv6GatewayAddr.empty()) ++ { ++ ipmi::setDbusProperty( ++ bus, systemObject.second, systemObject.first, ++ ipmi::network::SYSTEMCONFIG_INTERFACE, "DefaultGateway", ++ std::string(channelConf->ipv6GatewayAddr)); ++ } + } ++ // set IPAddress Enables ++ ipmi::setDbusProperty( ++ bus, ipmi::network::SERVICE, networkInterfaceObject.first, ++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables", ++ ipAddressEnablesType[channelConf->ipv6AddressingEnables]); ++ ++ ipmi::setDbusProperty( ++ bus, ipmi::network::SERVICE, networkInterfaceObject.first, ++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA", ++ (bool)channelConf->ipv6RouterAddressConfigControl); + } + catch (sdbusplus::exception::exception& e) + { +Index: phosphor-host-ipmid.clean/transporthandler.hpp +=================================================================== +--- phosphor-host-ipmid.clean.orig/transporthandler.hpp ++++ phosphor-host-ipmid.clean/transporthandler.hpp +@@ -79,8 +79,27 @@ enum class LanParam : uint8_t + IPV6_NEIGHBOR_TIMING_CONFIGURATION = 80, + }; + ++constexpr uint8_t DUID_LEN = 10; ++constexpr uint8_t DUID_LL_TYPE = 3; ++constexpr uint8_t DUIC_ETH_HW_TYPE = 1; ++ + // Data length of parameters + constexpr size_t lanParamVLANSize = 4; ++constexpr size_t lanParamInProgressSize = 3; ++constexpr size_t lanParamIPSize = 6; ++constexpr size_t lanParamIPSrcSize = 3; ++constexpr size_t lanParamMACSize = 8; ++constexpr size_t lanParamSubnetSize = 6; ++constexpr size_t lanParamGatewaySize = 6; ++constexpr size_t lanParamIPv6AndIPv4EnablesSize = 3; ++constexpr size_t lanParamIPv6StaticAddressesSize = 23; ++constexpr size_t lanParamIPv6RouterAddressConfCtrlSize = 3; ++constexpr size_t lanParamIPv6StaticRouter1IPAddrSize = 18; ++constexpr size_t lanParamIPv6StaticRouter1PrefixLenSize = 3; ++constexpr size_t lanParamIPv6StaticRouter1PrefixValSize = 19; ++constexpr size_t lanParamIPv6StaticRouter2IPAddrSize = 18; ++constexpr size_t lanParamIPv6StaticRouter2PrefixLenSize = 3; ++constexpr size_t lanParamIPv6StaticRouter2PrefixValSize = 19; + constexpr uint8_t SET_COMPLETE = 0; + constexpr uint8_t SET_IN_PROGRESS = 1; + constexpr uint8_t SET_COMMIT_WRITE = 2; // Optional +@@ -103,6 +122,20 @@ struct ChannelConfig_t + uint8_t lan_set_in_progress = SET_COMPLETE; + bool flush = false; + ++ // IPV6 parameters ++ uint8_t ipv6AddressSource = 0x0; ++ uint8_t ipv6AddressingEnables = 0x2; ++ std::string ipv6Addr; ++ uint8_t ipv6Prefix = 32; ++ uint8_t ipv6AddressStatus = 0x0; ++ uint8_t ipv6RouterAddressConfigControl = 0x0; ++ std::string ipv6GatewayAddr; ++ std::string ipv6BackupGatewayAddr; ++ uint8_t ipv6GatewayPrefixLength; ++ std::string ipv6GatewayPrefixValue; ++ uint8_t ipv6BackupGatewayPrefixLength = 0x0; ++ std::string ipv6BackupGatewayPrefixValue; ++ + void clear() + { + ipaddr.clear(); +@@ -113,6 +146,20 @@ struct ChannelConfig_t + ipsrc = ipmi::network::IPOrigin::UNSPECIFIED; + lan_set_in_progress = SET_COMPLETE; + flush = false; ++ ++ // IPv6 ++ ipv6Addr.clear(); ++ ipv6GatewayAddr.clear(); ++ ipv6BackupGatewayAddr.clear(); ++ ipv6AddressingEnables = 0x2; ++ ipv6AddressSource = 0x0; ++ ipv6Prefix = 32; ++ ipv6AddressStatus = 0x0; ++ ipv6RouterAddressConfigControl = 0x0; ++ ipv6GatewayPrefixLength = 0x0; ++ ipv6GatewayPrefixValue.clear(); ++ ipv6BackupGatewayPrefixLength = 0x0; ++ ipv6BackupGatewayPrefixValue.clear(); + } + }; + |