Cell and Network slicing configuration over o1.
[o-du/l2.git] / src / o1 / NrCellDuCb.cpp
diff --git a/src/o1/NrCellDuCb.cpp b/src/o1/NrCellDuCb.cpp
new file mode 100644 (file)
index 0000000..62a2fb9
--- /dev/null
@@ -0,0 +1,397 @@
+/*******************************************************************************
+################################################################################
+#   Copyright (c) [2020-2021] [HCL Technologies Ltd.]                          #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+*******************************************************************************/
+
+/* This file contains NrCellDu get and update handler . It handles
+   get and change callback for NrCellDu yang module  */
+
+#include <sstream>
+#include "NrCellDuCb.hpp"
+#include "NrCellInfo.hpp"
+#include "NrCellList.hpp"
+
+#define XPATH_MAX_LEN 256
+#define MAX_PLMN_MEMBER 4
+
+using namespace std;
+
+//Global variable
+NRCellDU cellParams;
+ManagedElement managedElement;
+int plmnListNum = 0;
+
+/*******************************************************************
+ *
+ * @brief override oper_get_items to handle callback
+ *
+ * @details
+ *
+ *    Function : oper_get_items
+ *
+ *    Functionality:
+ *      - override oper_get_items to handle callback
+ *
+ *
+ * @params[in] sysrepo::S_Session session, const char *module_name,
+ *             const char *path, const char *request_xpath,
+ *             uint32_t request_id, libyang::S_Data_Node &parent,
+ *             void *private_data
+ * @return SR_ERR_OK/SR_ERR_NOK
+ ******************************************************************/
+
+int NrCellDuCb::oper_get_items(sysrepo::S_Session session, \
+                                       const char *module_name, \
+                                       const char *path, \
+                                       const char *request_xpath, \
+                                       uint32_t request_id, \
+                                       libyang::S_Data_Node &parent, \
+                                       void *private_data)
+{
+   O1_LOG("\nO1 NrCellCb : Callback called for path=%s on get request", path);
+   libyang::S_Context ctx = session->get_context();
+   libyang::S_Module modMe = ctx->get_module(module_name);
+
+   //first create root of the tree then add nodes and leaves and fill data
+   parent.reset(new libyang::Data_Node(ctx, MANAGED_ELEMENT_MODULE_PATH, \
+                nullptr, LYD_ANYDATA_CONSTSTRING, 0));
+   libyang::S_Data_Node id(new libyang::Data_Node(parent, modMe, "id", \
+                  managedElement.meId));
+   libyang::S_Module modGnbdu = ctx->get_module(GNB_DU_FUNTION_MODULE_NAME);
+   libyang::S_Data_Node gnbdu(new libyang::Data_Node(parent, modGnbdu, \
+                                  "GNBDUFunction"));
+   libyang::S_Data_Node id1 (new libyang::Data_Node(gnbdu, modGnbdu, "id", \
+                  managedElement.gnbId));
+   libyang::S_Module mod = ctx->get_module(NR_CELL_DU_MODULE_NAME);
+   libyang::S_Data_Node nrCellDu(new libyang::Data_Node(gnbdu, mod, \
+                                  "NRCellDU"));
+   id.reset(new libyang::Data_Node(nrCellDu, mod, "id", \
+                  managedElement.nrCellDuId));
+   libyang::S_Data_Node attributes(new libyang::Data_Node(nrCellDu, mod, \
+                                  "attributes"));
+
+   libyang::S_Data_Node name;
+   libyang::S_Data_Node operational_state;
+   libyang::S_Data_Node cell_state;
+   libyang::S_Data_Node administrative_state;
+
+   NrCellList & cellList  = NrCellList::instance();
+   NrCellInfo cellInfo;
+   const NrCellList::CellOpStateMap & cellOpStateMap = cellList.getCellOpStateList();
+   //read the data from CellOpStateMap
+   std::map<uint16_t, NrCellInfo>::const_iterator it;
+   for(it = cellOpStateMap.begin(); it !=cellOpStateMap.end(); it++)
+   {
+      O1_LOG("\nO1 NrCellCb : cellId = %d, opState=%d, cellState=%d", \
+              it->first, (int) it->second.getOpState(), (int) it->second.getCellState());
+      operational_state.reset(new libyang::Data_Node(attributes, mod, \
+                        "operationalState", \
+                        cellInfo.enumToOperationalStateString(it->second.getOpState()).c_str()));
+      cell_state.reset(new libyang::Data_Node(attributes, mod, "cellState", \
+                       cellInfo.enumToCellStateString(it->second.getCellState()).c_str()));
+   }
+   return SR_ERR_OK;
+}
+
+/*******************************************************************
+ *
+ * @brief convert administrative state string to enum
+ *
+ * @details
+ *
+ *    Function : administrativeStateToEnum
+ *
+ *    Functionality:
+ *      - convert administrative state string to enum
+ *
+ *
+ * @params[in] string AdminState
+ * @return Enum AdminState
+ ******************************************************************/
+
+AdminState NrCellDuCb::administrativeStateToEnum(string &val)
+{
+   AdminState state;
+   if (val=="LOCKED") {
+      state = LOCKED;
+   }
+   else if(val=="UNLOCKED") {
+      state = UNLOCKED;
+   }
+   else if(val=="SHUTTING_DOWN") {
+      state = SHUTTING_DOWN;
+   }
+   return state;
+}
+
+/*******************************************************************
+ *
+ * @brief fill the parameters value into the structure instance
+ *
+ * @details
+ *
+ *    Function : updateParams
+ *
+ *    Functionality:
+ *      - fill the parameters value into the structure instance
+ *
+ *
+ * @params[in] string leaf, string val
+ * @return void
+ ******************************************************************/
+
+
+void NrCellDuCb::updateParams(string &parent, string &leaf, string &val)
+{
+   int memberNum = plmnListNum/MAX_PLMN_MEMBER;
+   if(parent.find("attribute") != string::npos)
+   {
+      if(leaf == "cellLocalId"){
+         cellParams.cellLocalId = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.cellLocalId);
+      }
+      else if(leaf == "administrativeState"){
+         cellParams.administrativeState = administrativeStateToEnum(val);
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.administrativeState);
+      }
+     else if(leaf == "nRPCI"){
+         cellParams.nRPCI = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.nRPCI);
+      }
+      else if(leaf == "nRTAC"){
+         cellParams.nRTAC = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.nRTAC);
+      }
+      else if(leaf == "arfcnDL"){
+         cellParams.arfcnDL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.arfcnDL);
+      }
+      else if(leaf == "arfcnUL"){
+         cellParams.arfcnUL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.arfcnUL);
+      }
+      else if(leaf == "arfcnSUL"){
+         cellParams.arfcnSUL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.arfcnSUL);
+      }
+      else if(leaf == "ssbFrequency"){
+         cellParams.ssbFrequency = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.ssbFrequency);
+      }
+      else if(leaf == "ssbPeriodicity"){
+         cellParams.ssbPeriodicity = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.ssbPeriodicity);
+      }
+      else if(leaf == "ssbSubCarrierSpacing"){
+         cellParams.ssbSubCarrierSpacing = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.ssbSubCarrierSpacing);
+      }
+      else if(leaf == "ssbOffset"){
+         cellParams.ssbOffset = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.ssbOffset);
+      }
+      else if(leaf == "ssbDuration"){
+         cellParams.ssbDuration = atoi(val.c_str());
+        O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.ssbDuration);
+      }
+      else if(leaf == "bSChannelBwUL"){
+         cellParams.bSChannelBwUL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.bSChannelBwUL);
+      }
+      else if(leaf == "bSChannelBwDL"){
+         cellParams.bSChannelBwDL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.bSChannelBwDL);
+      }
+      else if(leaf == "bSChannelBwSUL"){
+         cellParams.bSChannelBwSUL = atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : val = %d", cellParams.bSChannelBwSUL);
+      }
+   }
+   else if(parent.find("pLMNInfoList") != string::npos && memberNum < MAX_SUPPORTED_PLMN)
+   {
+         if(leaf == "mcc")
+         {
+            memset(cellParams.plmnList[memberNum].mcc, \
+                  '\0', MCC_LEN);
+            cellParams.plmnList[memberNum].mcc[0] = stoi(val.substr(0,1).c_str(),0,10);
+            cellParams.plmnList[memberNum].mcc[1] = stoi(val.substr(1,1).c_str(),0,10);
+            cellParams.plmnList[memberNum].mcc[2] = stoi(val.substr(2,1).c_str(),0,10);
+            O1_LOG("\nO1 NrCellDuCb : cellParams.plmnList[%d].mcc[2]  = %c",
+                  memberNum, cellParams.plmnList[memberNum].mcc[2]);
+         }
+        else if(leaf == "mnc")
+         {
+           memset(cellParams.plmnList[memberNum].mnc, \
+                  '\0', MNC_LEN);
+            cellParams.plmnList[memberNum].mnc[0] = stoi(val.substr(0,1).c_str(),0,10);
+            cellParams.plmnList[memberNum].mnc[1] = stoi(val.substr(1,1).c_str(),0,10);
+            cellParams.plmnList[memberNum].mnc[2] = stoi(val.substr(2,1).c_str(),0,10);
+            O1_LOG("\nO1 NrCellDuCb : cellParams.plmnList[%d].mnc[1]  = %c",
+                  memberNum, cellParams.plmnList[memberNum].mnc[1]);
+         }
+         else if(leaf == "sst")
+         {
+            cellParams.plmnList[memberNum].sst = \
+                   atoi(val.c_str());
+         O1_LOG("\nO1 NrCellDuCb : cellParams.plmnList[%d].sst  = %d", \
+                        memberNum, cellParams.plmnList[memberNum].sst);
+         }
+         else if(leaf == "sd")
+          {
+            memset(cellParams.plmnList[memberNum].sd, \
+                  '\0', SD_LEN);
+
+            cellParams.plmnList[memberNum].sd[0] = \
+                    stoi(val.substr(0,2).c_str(),0,16);
+            cellParams.plmnList[memberNum].sd[1] = \
+                    stoi(val.substr(2,2).c_str(),0,16);
+            cellParams.plmnList[memberNum].sd[2] = \
+                    stoi(val.substr(4,2).c_str(),0,16);
+            O1_LOG("\nO1 NrCellDuCb : cellParams.plmnList[%d].sd[2]  = %d",
+                    memberNum, cellParams.plmnList[memberNum].sd[SD_LEN-1]);
+         }
+         plmnListNum++;
+      }
+    else if(parent.find("ManagedElement") != string::npos)
+    {
+         if(leaf == "id")
+         {
+            strncpy(managedElement.meId, val.c_str(), strlen(val.c_str()));
+            O1_LOG("\nO1 NrCellDuCb : ManagedElement id  = %s", managedElement.meId);
+         }
+    }
+    else if(parent.find("GNBDUFunction") != string::npos)
+    {
+         if(leaf == "id")
+         {
+            strncpy(managedElement.gnbId, val.c_str(), strlen(val.c_str()));
+            O1_LOG("\nO1 NrCellDuCb : GNBDUFuntion id  = %s", managedElement.gnbId);
+         }
+    }
+    else if(parent.find("NRCellDu") != string::npos)
+    {
+         if(leaf == "id")
+         {
+            strncpy(managedElement.nrCellDuId, val.c_str(), strlen(val.c_str()));
+            O1_LOG("\nO1 NrCellDuCb : NRCELLDU id  = %s", managedElement.nrCellDuId);
+         }
+    }
+}
+
+/*******************************************************************
+ *
+ * @brief set cell parameters
+ *
+ * @details
+ *
+ *    Function : configureCell
+ *
+ *    Functionality:
+ *      - pass the cell Parameters to ODU high stack
+ *
+ *
+ * @params[in] void
+ * @return success/failure
+ ******************************************************************/
+
+bool NrCellDuCb::configureCell()
+{
+   O1_LOG("\nO1 rannetworkCb : configcell");
+#ifndef ODU_TEST_STUB
+   if( setCellParam() != ROK)
+   {
+      O1_LOG("\nO1 rannetworkCb : fail to set cell configuration in DU");
+      return false;
+   }
+   return true;
+#else
+   return true;
+#endif
+}
+
+/*******************************************************************
+ *
+ * @brief override module_change to handle callback
+ *
+ * @details
+ *
+ *    Function : module_change
+ *
+ *    Functionality:
+ *      - override module_change to handle callback of modification of
+ *        o-ran-sc-du-hello-world yang module
+ *
+ *
+ * @params[in] sysrepo::S_Session session, const char *module_name,
+ *             const char *xpath, sr_event_t event, uint32_t request_id,
+ *             void *private_data
+ * @return SR_ERR_OK        - success
+ *         SR_ERR_INTERNAL  - failure
+ ******************************************************************/
+
+int NrCellDuCb::module_change(sysrepo::S_Session sess, \
+                                    const char *module_name, \
+                                    const char *xpath, \
+                                    sr_event_t event, \
+                                    uint32_t request_id, \
+                                    void *private_data)
+{
+   O1_LOG("\nO1 NrCellDuCb : Notification edit sucessful");
+
+   char change_path[XPATH_MAX_LEN];
+   plmnListNum = 0;
+
+   try {
+      O1_LOG("\nO1 NrCellDuCbCb : Notification %s", NetconfUtils::evToStr(event));
+      if (SR_EV_CHANGE == event)
+      {
+         snprintf(change_path, XPATH_MAX_LEN, "/%s:*//.", module_name);
+         auto it = sess->get_changes_iter(change_path);
+         while (auto change = sess->get_change_next(it)) {
+         //NetconfUtils::printChange(change); //enable only for debugging
+
+        if(nullptr != change->new_val())
+         {
+               //O1_LOG("\nO1 NrCellDuCb : Parameter value has been \
+changed val=%s", change->new_val()->val_to_string().c_str());
+               string val = change->new_val()->val_to_string();
+               string parent, leaf;
+
+              NetconfUtils::getLeafInfo(change->new_val()->to_string(), \
+                                        parent, leaf);
+               O1_LOG("\nO1 NrCellDuCb : parent = [%s], leaf = [%s]", \
+                        parent.c_str(), leaf.c_str());
+               updateParams(parent, leaf ,val);
+            }
+         }
+         if(!configureCell())
+        {
+            O1_LOG("\nO1 NrCellDuCb : configcell failed");
+           return SR_ERR_INTERNAL;
+        }
+
+      }
+   }
+   catch( const std::exception& e ) {
+      O1_LOG("\nO1 rannetworkCb exception : %s\n", e.what());
+   }
+
+   return SR_ERR_OK;
+}
+
+/**********************************************************************
+         End of file
+**********************************************************************/