xref: /openbmc/phosphor-fan-presence/control/json/actions/net_target_decrease.cpp (revision 64b5ac203518568ec8b7569d0e785352278f2472)
145c44ea0SMatthew Barth /**
245c44ea0SMatthew Barth  * Copyright © 2021 IBM Corporation
345c44ea0SMatthew Barth  *
445c44ea0SMatthew Barth  * Licensed under the Apache License, Version 2.0 (the "License");
545c44ea0SMatthew Barth  * you may not use this file except in compliance with the License.
645c44ea0SMatthew Barth  * You may obtain a copy of the License at
745c44ea0SMatthew Barth  *
845c44ea0SMatthew Barth  *     http://www.apache.org/licenses/LICENSE-2.0
945c44ea0SMatthew Barth  *
1045c44ea0SMatthew Barth  * Unless required by applicable law or agreed to in writing, software
1145c44ea0SMatthew Barth  * distributed under the License is distributed on an "AS IS" BASIS,
1245c44ea0SMatthew Barth  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1345c44ea0SMatthew Barth  * See the License for the specific language governing permissions and
1445c44ea0SMatthew Barth  * limitations under the License.
1545c44ea0SMatthew Barth  */
1645c44ea0SMatthew Barth #include "net_target_decrease.hpp"
1745c44ea0SMatthew Barth 
1845c44ea0SMatthew Barth #include "../manager.hpp"
1945c44ea0SMatthew Barth #include "../zone.hpp"
2045c44ea0SMatthew Barth #include "action.hpp"
2145c44ea0SMatthew Barth #include "group.hpp"
2245c44ea0SMatthew Barth 
2345c44ea0SMatthew Barth #include <nlohmann/json.hpp>
24*64b5ac20SAnwaar Hadi #include <phosphor-logging/lg2.hpp>
2545c44ea0SMatthew Barth 
2645c44ea0SMatthew Barth #include <algorithm>
2745c44ea0SMatthew Barth #include <variant>
2845c44ea0SMatthew Barth 
2945c44ea0SMatthew Barth namespace phosphor::fan::control::json
3045c44ea0SMatthew Barth {
3145c44ea0SMatthew Barth 
3245c44ea0SMatthew Barth using json = nlohmann::json;
3345c44ea0SMatthew Barth 
NetTargetDecrease(const json & jsonObj,const std::vector<Group> & groups)3419c77494SMatthew Barth NetTargetDecrease::NetTargetDecrease(const json& jsonObj,
3519c77494SMatthew Barth                                      const std::vector<Group>& groups) :
3619c77494SMatthew Barth     ActionBase(jsonObj, groups)
3745c44ea0SMatthew Barth {
3845c44ea0SMatthew Barth     setState(jsonObj);
3945c44ea0SMatthew Barth     setDelta(jsonObj);
4045c44ea0SMatthew Barth }
4145c44ea0SMatthew Barth 
run(Zone & zone)426d2476c9SMatthew Barth void NetTargetDecrease::run(Zone& zone)
4345c44ea0SMatthew Barth {
4420afdda3SMatthew Barth     if (!_stateParameter.empty())
4520afdda3SMatthew Barth     {
4620afdda3SMatthew Barth         auto s = Manager::getParameter(_stateParameter);
4720afdda3SMatthew Barth         if (!s)
4820afdda3SMatthew Barth         {
4920afdda3SMatthew Barth             return;
5020afdda3SMatthew Barth         }
5120afdda3SMatthew Barth         _state = *s;
5220afdda3SMatthew Barth     }
5320afdda3SMatthew Barth 
5445c44ea0SMatthew Barth     auto netDelta = zone.getDecDelta();
556d2476c9SMatthew Barth     for (const auto& group : _groups)
566d2476c9SMatthew Barth     {
5745c44ea0SMatthew Barth         for (const auto& member : group.getMembers())
5845c44ea0SMatthew Barth         {
5945c44ea0SMatthew Barth             try
6045c44ea0SMatthew Barth             {
6145c44ea0SMatthew Barth                 auto value = Manager::getObjValueVariant(
6245c44ea0SMatthew Barth                     member, group.getInterface(), group.getProperty());
6345c44ea0SMatthew Barth                 if (std::holds_alternative<int64_t>(value) ||
6445c44ea0SMatthew Barth                     std::holds_alternative<double>(value))
6545c44ea0SMatthew Barth                 {
6645c44ea0SMatthew Barth                     if (value >= _state)
6745c44ea0SMatthew Barth                     {
6845c44ea0SMatthew Barth                         // No decrease allowed for this group
6945c44ea0SMatthew Barth                         netDelta = 0;
7045c44ea0SMatthew Barth                         break;
7145c44ea0SMatthew Barth                     }
7245c44ea0SMatthew Barth                     else
7345c44ea0SMatthew Barth                     {
746d2476c9SMatthew Barth                         // Decrease factor is the difference in configured state
756d2476c9SMatthew Barth                         // to the current value's state
7645c44ea0SMatthew Barth                         uint64_t deltaFactor = 0;
7745c44ea0SMatthew Barth                         if (auto dblPtr = std::get_if<double>(&value))
7845c44ea0SMatthew Barth                         {
7945c44ea0SMatthew Barth                             deltaFactor = static_cast<uint64_t>(
8045c44ea0SMatthew Barth                                 std::get<double>(_state) - *dblPtr);
8145c44ea0SMatthew Barth                         }
8245c44ea0SMatthew Barth                         else
8345c44ea0SMatthew Barth                         {
846d2476c9SMatthew Barth                             deltaFactor = static_cast<uint64_t>(
856d2476c9SMatthew Barth                                 std::get<int64_t>(_state) -
8645c44ea0SMatthew Barth                                 std::get<int64_t>(value));
8745c44ea0SMatthew Barth                         }
8845c44ea0SMatthew Barth 
896d2476c9SMatthew Barth                         // Multiply the decrease factor by the configured delta
906d2476c9SMatthew Barth                         // to get the net decrease delta for the given group
916d2476c9SMatthew Barth                         // member. The lowest net decrease delta of the entire
926d2476c9SMatthew Barth                         // group is the decrease requested.
9345c44ea0SMatthew Barth                         if (netDelta == 0)
9445c44ea0SMatthew Barth                         {
9545c44ea0SMatthew Barth                             netDelta = deltaFactor * _delta;
9645c44ea0SMatthew Barth                         }
9745c44ea0SMatthew Barth                         else
9845c44ea0SMatthew Barth                         {
9945c44ea0SMatthew Barth                             netDelta = std::min(netDelta, deltaFactor * _delta);
10045c44ea0SMatthew Barth                         }
10145c44ea0SMatthew Barth                     }
10245c44ea0SMatthew Barth                 }
10345c44ea0SMatthew Barth                 else if (std::holds_alternative<bool>(value) ||
10445c44ea0SMatthew Barth                          std::holds_alternative<std::string>(value))
10545c44ea0SMatthew Barth                 {
10645c44ea0SMatthew Barth                     // Where a group of booleans or strings equal the state
10745c44ea0SMatthew Barth                     // provided, request a decrease of the configured delta
10845c44ea0SMatthew Barth                     if (_state == value)
10945c44ea0SMatthew Barth                     {
11045c44ea0SMatthew Barth                         if (netDelta == 0)
11145c44ea0SMatthew Barth                         {
11245c44ea0SMatthew Barth                             netDelta = _delta;
11345c44ea0SMatthew Barth                         }
11445c44ea0SMatthew Barth                         else
11545c44ea0SMatthew Barth                         {
11645c44ea0SMatthew Barth                             netDelta = std::min(netDelta, _delta);
11745c44ea0SMatthew Barth                         }
11845c44ea0SMatthew Barth                     }
11945c44ea0SMatthew Barth                 }
12045c44ea0SMatthew Barth                 else
12145c44ea0SMatthew Barth                 {
12245c44ea0SMatthew Barth                     // Unsupported group member type for this action
123*64b5ac20SAnwaar Hadi                     lg2::error(
124*64b5ac20SAnwaar Hadi                         "Action {ACTION_NAME}: Unsupported group member type "
125*64b5ac20SAnwaar Hadi                         "given. [object = {MEMBER} : {GROUP_INTERFACE} : {GROUP_PROPERTY}]",
126*64b5ac20SAnwaar Hadi                         "ACTION_NAME", ActionBase::getName(), "MEMBER", member,
127*64b5ac20SAnwaar Hadi                         "GROUP_INTERFACE", group.getInterface(),
128*64b5ac20SAnwaar Hadi                         "GROUP_PROPERTY", group.getProperty());
12945c44ea0SMatthew Barth                 }
13045c44ea0SMatthew Barth             }
13145c44ea0SMatthew Barth             catch (const std::out_of_range& oore)
13245c44ea0SMatthew Barth             {
13345c44ea0SMatthew Barth                 // Property value not found, netDelta unchanged
13445c44ea0SMatthew Barth             }
13545c44ea0SMatthew Barth         }
13645c44ea0SMatthew Barth         // Update group's decrease allowed state
13745c44ea0SMatthew Barth         zone.setDecreaseAllow(group.getName(), !(netDelta == 0));
1386d2476c9SMatthew Barth     }
13945c44ea0SMatthew Barth     // Request target decrease to occur on decrease interval
14045c44ea0SMatthew Barth     zone.requestDecrease(netDelta);
14145c44ea0SMatthew Barth }
14245c44ea0SMatthew Barth 
setState(const json & jsonObj)14345c44ea0SMatthew Barth void NetTargetDecrease::setState(const json& jsonObj)
14445c44ea0SMatthew Barth {
14520afdda3SMatthew Barth     if (jsonObj.contains("state"))
14645c44ea0SMatthew Barth     {
14745c44ea0SMatthew Barth         _state = getJsonValue(jsonObj["state"]);
14845c44ea0SMatthew Barth     }
14920afdda3SMatthew Barth     else if (jsonObj.contains("state_parameter_name"))
15020afdda3SMatthew Barth     {
15120afdda3SMatthew Barth         _stateParameter = jsonObj["state_parameter_name"].get<std::string>();
15220afdda3SMatthew Barth     }
15320afdda3SMatthew Barth     else
15420afdda3SMatthew Barth     {
15520afdda3SMatthew Barth         throw ActionParseError{
15620afdda3SMatthew Barth             ActionBase::getName(),
15720afdda3SMatthew Barth             "Missing required state or state_parameter_name value"};
15820afdda3SMatthew Barth     }
15920afdda3SMatthew Barth }
16045c44ea0SMatthew Barth 
setDelta(const json & jsonObj)16145c44ea0SMatthew Barth void NetTargetDecrease::setDelta(const json& jsonObj)
16245c44ea0SMatthew Barth {
16345c44ea0SMatthew Barth     if (!jsonObj.contains("delta"))
16445c44ea0SMatthew Barth     {
16545c44ea0SMatthew Barth         throw ActionParseError{ActionBase::getName(),
16645c44ea0SMatthew Barth                                "Missing required delta value"};
16745c44ea0SMatthew Barth     }
16845c44ea0SMatthew Barth     _delta = jsonObj["delta"].get<uint64_t>();
16945c44ea0SMatthew Barth }
17045c44ea0SMatthew Barth 
17145c44ea0SMatthew Barth } // namespace phosphor::fan::control::json
172