From 7a7f0126a7e76d7c455b9de06135a308ac370369 Mon Sep 17 00:00:00 2001 From: Ratan Gupta Date: Wed, 7 Mar 2018 12:31:05 +0530 Subject: SetLan: Apply the network changes once the timer expires Start the timer once the set in progress parameter set to set complete as part of Set LAN Configuration Parameters command. Resolves openbmc/openbmc#2932 Resolves openbmc/openbmc#2993 Change-Id: Ie6f3b331531da23c74fa44bb52fa1ddccffabd13 Signed-off-by: Ratan Gupta --- ipmid.cpp | 3 ++ transporthandler.cpp | 87 +++++++++++++++++++++++++++++++--------------------- transporthandler.hpp | 18 +++++++++++ 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/ipmid.cpp b/ipmid.cpp index a05992b..91bbbee 100644 --- a/ipmid.cpp +++ b/ipmid.cpp @@ -42,6 +42,9 @@ sdbusPtr sdbusp; using cmdManagerPtr = std::unique_ptr; cmdManagerPtr cmdManager; +// Global timer for network changes +std::unique_ptr networkTimer = nullptr; + // Command and handler tuple. Used when clients ask the command to be put // into host message queue using CommandHandler = phosphor::host::command::CommandHandler; diff --git a/transporthandler.cpp b/transporthandler.cpp index bbc6ae5..8bf0d43 100644 --- a/transporthandler.cpp +++ b/transporthandler.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,6 +8,7 @@ #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" +#include "timer.hpp" #include "transporthandler.hpp" #include "utils.hpp" #include "net.hpp" @@ -22,16 +24,7 @@ #include #endif -/** @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)); +extern std::unique_ptr networkTimer; const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; @@ -40,6 +33,7 @@ std::map> channelConfig; using namespace phosphor::logging; using namespace sdbusplus::xyz::openbmc_project::Common::Error; + namespace fs = std::experimental::filesystem; void register_netfn_transport_functions() __attribute__((constructor)); @@ -391,6 +385,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; + using namespace std::chrono_literals; + + // time to wait before applying the network changes. + constexpr auto networkTimeout = 10000000us; // 10 sec + char ipaddr[INET_ADDRSTRLEN]; char netmask[INET_ADDRSTRLEN]; char gateway[INET_ADDRSTRLEN]; @@ -498,11 +497,19 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, entry("GATEWAY=%s", channelConf->gateway.c_str()), entry("VLAN=%d", channelConf->vlanID)); - log("Use Set Channel Access command to apply"); + if (!networkTimer) + { + log("Network timer is not instantiated"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + + // start/restart the timer + networkTimer->startTimer(networkTimeout); } else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress { channelConf->lan_set_in_progress = SET_IN_PROGRESS; + channelConf->flush = true; } } break; @@ -632,15 +639,8 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, return rc; } -ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, - ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context) +void applyChanges(int channel) { - ipmi_ret_t rc = IPMI_CC_OK; - std::string ipaddress; std::string gateway; uint8_t prefix {}; @@ -649,25 +649,16 @@ 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 - (request); - int channel = requestData->channelNumber & CHANNEL_MASK; - auto ethdevice = ipmi::network::ChanneltoEthernet(channel); if (ethdevice.empty()) { - return IPMI_CC_INVALID_FIELD_REQUEST; + log("Unable to get the interface name", + entry("CHANNEL=%d", channel)); + return; } 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 { sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); @@ -729,9 +720,8 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, entry("INTERFACE=%s", ipmi::network::ETHERNET_INTERFACE)); commit(); - rc = IPMI_CC_UNSPECIFIED_ERROR; channelConf->clear(); - return rc; + return; } networkInterfacePath = ancestorMap.begin()->first; @@ -938,15 +928,42 @@ ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, entry("IPSRC=%d", channelConf->ipsrc)); commit(); - rc = IPMI_CC_UNSPECIFIED_ERROR; } channelConf->clear(); - return rc; +} + +void commitNetworkChanges() +{ + for (const auto &channel : channelConfig) + { + if (channel.second->flush) + { + applyChanges(channel.first); + } + } +} + +void createNetworkTimer() +{ + if (!networkTimer) + { + std::function networkTimerCallback( + std::bind(&commitNetworkChanges)); + + networkTimer = + std::make_unique( + ipmid_get_sd_event_connection(), + networkTimerCallback); + } + } void register_netfn_transport_functions() { + // As this timer is only for transport handler + // so creating it here. + createNetworkTimer(); // printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD); ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard, diff --git a/transporthandler.hpp b/transporthandler.hpp index 42bf717..f440403 100644 --- a/transporthandler.hpp +++ b/transporthandler.hpp @@ -47,6 +47,7 @@ struct ChannelConfig_t // vlan id is in 12 bits and the 16th bit is for enable mask. uint32_t vlanID = ipmi::network::VLAN_ID_MASK; uint8_t lan_set_in_progress = SET_COMPLETE; + bool flush = false; void clear() { @@ -57,6 +58,7 @@ struct ChannelConfig_t vlanID = ipmi::network::VLAN_ID_MASK; ipsrc = ipmi::network::IPOrigin::UNSPECIFIED; lan_set_in_progress = SET_COMPLETE; + flush = false; } }; @@ -66,3 +68,19 @@ struct ChannelConfig_t // @param[in] channel the channel // @return the ChannelConfig_t pointer. struct ChannelConfig_t* getChannelConfig(int channel); + +/** @brief Iterate over all the channelconfig and if + * user has given the data for a channel then + * apply the network changes for that channel. + */ +void commitNetworkChanges(); + +/* @brief Apply the network changes which is there in the + * network cache for a given channel which gets filled + * through setLan command. If some of the network + * parameter was not given by the setLan then this function + * gets the value of that parameter which is already + * configured on the system. + * @param[in] channel: channel number. + */ +void applyChanges(int channel); -- cgit v1.2.1