/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
 *
 * 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.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*
  enb_config.c
  -------------------
  AUTHOR  : Lionel GAUTHIER, navid nikaein, Laurent Winckel
  COMPANY : EURECOM
  EMAIL   : Lionel.Gauthier@eurecom.fr, navid.nikaein@eurecom.fr
*/

#include <string.h>
#include <inttypes.h>
#include <dlfcn.h>

#include "common/utils/LOG/log.h"
#include "assertions.h"
#include "enb_config.h"
#include "UTIL/OTG/otg.h"
#include "UTIL/OTG/otg_externs.h"
#include "intertask_interface.h"
#include "s1ap_eNB.h"
#include "sctp_eNB_task.h"
#include "common/ran_context.h"
#include "sctp_default_values.h"
#include "LTE_SystemInformationBlockType2.h"
#include "uper_decoder.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "PHY/phy_extern.h"
#include "PHY/INIT/phy_init.h"
#include "radio/ETHERNET/ethernet_lib.h"
#include "nfapi_vnf.h"
#include "nfapi_pnf.h"
#include "executables/lte-softmodem.h"
#include "L1_paramdef.h"
#include "MACRLC_paramdef.h"
#include "common/config/config_userapi.h"
#include "RRC_config_tools.h"
#include "enb_paramdef.h"
#include "executables/thread-common.h"
#include <openair3/ocp-gtpu/gtp_itf.h>

extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw);
extern char *parallel_config;
extern char *worker_config;

RAN_CONTEXT_t RC;

void RCconfig_L1(void) {
  int               i,j;
  paramdef_t L1_Params[] = L1PARAMS_DESC;
  paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0};

  if (RC.eNB == NULL) {
    RC.eNB                       = (PHY_VARS_eNB ** *)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB **));
    LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
    memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB **));
    RC.nb_L1_CC = malloc((1+RC.nb_L1_inst)*sizeof(int));
  }

  config_getlist(config_get_if(), &L1_ParamList, L1_Params, sizeofArray(L1_Params), NULL);

  if (L1_ParamList.numelt > 0) {
    for (j = 0; j < RC.nb_L1_inst; j++) {
      RC.nb_L1_CC[j] = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr);

      if (RC.eNB[j] == NULL) {
        RC.eNB[j]  = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB *));
        LOG_I(PHY,"RC.eNB[%d] = %p\n",j,RC.eNB[j]);
        memset(RC.eNB[j],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB *));
      }

      for (i=0; i<RC.nb_L1_CC[j]; i++) {
        if (RC.eNB[j][i] == NULL) {
          RC.eNB[j][i] = (PHY_VARS_eNB *)calloc(1, sizeof(PHY_VARS_eNB));
          LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",j,i,RC.eNB[j][i]);
          RC.eNB[j][i]->Mod_id  = j;
          RC.eNB[j][i]->CC_id   = i;
        }
      }

      if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
      } else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
        RC.eNB[j][0]->eth_params_n.local_if_name            = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
        RC.eNB[j][0]->eth_params_n.my_addr                  = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
        RC.eNB[j][0]->eth_params_n.remote_addr              = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
        RC.eNB[j][0]->eth_params_n.my_portc                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
        RC.eNB[j][0]->eth_params_n.remote_portc             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
        RC.eNB[j][0]->eth_params_n.my_portd                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
        RC.eNB[j][0]->eth_params_n.remote_portd             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
        RC.eNB[j][0]->eth_params_n.transp_preference        = ETH_UDP_MODE;
        RC.nb_macrlc_inst = 1;  // This is used by mac_top_init_eNB()
        // This is used by init_eNB_afterRU()
        RC.nb_CC = (int *)malloc((1+RC.nb_inst)*sizeof(int));
        RC.nb_CC[0]=1;
        RC.nb_inst =1; // feptx_prec uses num_eNB but phy_init_RU uses nb_inst
        LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_inst=1 this is because phy_init_RU() uses that to index and not RC.num_eNB - why the 2 similar variables?\n", __FUNCTION__);
        LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_CC[0]=%d for init_eNB_afterRU()\n", __FUNCTION__, RC.nb_CC[0]);
        LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_macrlc_inst:%d because used by mac_top_init_eNB()\n", __FUNCTION__, RC.nb_macrlc_inst);
        mac_top_init_eNB();
        configure_nfapi_pnf(RC.eNB[j][0]->eth_params_n.remote_addr, RC.eNB[j][0]->eth_params_n.remote_portc, RC.eNB[j][0]->eth_params_n.my_addr, RC.eNB[j][0]->eth_params_n.my_portd,
                            RC.eNB[j][0]->eth_params_n     .remote_portd);
      } else { // other midhaul
      }

      // PRACH/PUCCH parameters
      RC.eNB[j][0]->prach_DTX_threshold    = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD_IDX].iptr);
      RC.eNB[j][0]->pucch1_DTX_threshold   = *(L1_ParamList.paramarray[j][L1_PUCCH1_DTX_THRESHOLD_IDX].iptr);
      RC.eNB[j][0]->pucch1ab_DTX_threshold = *(L1_ParamList.paramarray[j][L1_PUCCH1AB_DTX_THRESHOLD_IDX].iptr);

      for (int ce_level=0; ce_level<4; ce_level++) {
        RC.eNB[j][0]->prach_DTX_threshold_emtc[ce_level]    = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_EMTC0_THRESHOLD_IDX+ce_level].iptr);
        RC.eNB[j][0]->pucch1_DTX_threshold_emtc[ce_level]   = *(L1_ParamList.paramarray[j][L1_PUCCH1_DTX_EMTC0_THRESHOLD_IDX+ce_level].iptr);
        RC.eNB[j][0]->pucch1ab_DTX_threshold_emtc[ce_level] = *(L1_ParamList.paramarray[j][L1_PUCCH1AB_DTX_EMTC0_THRESHOLD_IDX+ce_level].iptr);
      }


      RC.eNB[j][0]->pusch_signal_threshold    = *(L1_ParamList.paramarray[j][L1_PUSCH_SIGNAL_THRESHOLD_IDX].iptr);
      LOG_I(ENB_APP,"PUSCH singal threshold = %d \n",RC.eNB[j][0]->pusch_signal_threshold);
    }// j=0..num_inst

    LOG_I(ENB_APP,"Initializing northbound interface for L1\n");
    l1_north_init_eNB();
  } else {
    LOG_I(PHY,"No " CONFIG_STRING_L1_LIST " configuration found");
    // need to create some structures for VNF
    j = 0;
    RC.nb_L1_CC = malloc((1+RC.nb_L1_inst)*sizeof(int));
    RC.nb_L1_CC[j]=1;

    if (RC.eNB[j] == NULL) {
      RC.eNB[j]                       = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB **));
      LOG_I(PHY,"RC.eNB[%d] = %p\n",j,RC.eNB[j]);
      memset(RC.eNB[j],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
    }

    for (i=0; i<RC.nb_L1_CC[j]; i++) {
      if (RC.eNB[j][i] == NULL) {
        RC.eNB[j][i] = (PHY_VARS_eNB *)malloc(sizeof(PHY_VARS_eNB));
        memset((void *)RC.eNB[j][i],0,sizeof(PHY_VARS_eNB));
        LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",j,i,RC.eNB[j][i]);
        RC.eNB[j][i]->Mod_id  = j;
        RC.eNB[j][i]->CC_id   = i;
      }
    }
  }
}

void RCconfig_macrlc(void)
{
  int               j;
  paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
  paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
  config_getlist(config_get_if(), &MacRLC_ParamList, MacRLC_Params, sizeofArray(MacRLC_Params), NULL);
  config_getlist(config_get_if(), &MacRLC_ParamList, MacRLC_Params, sizeofArray(MacRLC_Params), NULL);

  if ( MacRLC_ParamList.numelt > 0) {
    RC.nb_macrlc_inst=MacRLC_ParamList.numelt;
    mac_top_init_eNB();
    RC.nb_mac_CC = (int *)malloc(RC.nb_macrlc_inst*sizeof(int));

    for (j = 0; j < RC.nb_macrlc_inst; j++) {
      RC.mac[j]->puSch10xSnr = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCH10xSNR_IDX ].iptr);
      RC.mac[j]->puCch10xSnr = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCH10xSNR_IDX ].iptr);
      RC.mac[j]->ue_multiple_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UE_MULTIPLE_MAX_IDX ].iptr);
      RC.mac[j]->use_mcs_offset = *(MacRLC_ParamList.paramarray[j][MACRLC_USE_MCS_OFFSET_IDX ].iptr);
      RC.mac[j]->bler_lower = *(MacRLC_ParamList.paramarray[j][MACRLC_BLER_TARGET_LOWER_IDX ].dblptr);
      RC.mac[j]->bler_upper = *(MacRLC_ParamList.paramarray[j][MACRLC_BLER_TARGET_UPPER_IDX ].dblptr);
      RC.mac[j]->max_ul_rb_index = *(MacRLC_ParamList.paramarray[j][MACRLC_MAX_UL_RB_INDEX_IDX ].iptr);
      RC.nb_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr);
      LOG_I(ENB_APP,"MAC instance %d parameters : pusch_snr %lf, pucch_snr %lf, ue_multiple_max %d, use_mcs_offset %d, bler_lower %lf, bler_upper %lf,max_ul_rb_index %d\n",
	j,
	RC.mac[j]->puSch10xSnr/10.0,
	RC.mac[j]->puCch10xSnr/10.0,
	RC.mac[j]->ue_multiple_max,
	RC.mac[j]->use_mcs_offset,
	RC.mac[j]->bler_lower,
	RC.mac[j]->bler_upper,
	RC.mac[j]->max_ul_rb_index);
      if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) {
        // check number of instances is same as RRC/PDCP
        LOG_I(ENB_APP,"Configuring local RRC for MACRLC\n");
      } else { // other midhaul
        AssertFatal(1==0,"MACRLC %d: %s unknown northbound midhaul\n",j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr));
      }

      if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_L1") == 0) {
      } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "nfapi") == 0) {
        RC.mac[j]->eth_params_s.local_if_name            = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_IF_NAME_IDX].strptr));
        RC.mac[j]->eth_params_s.my_addr                  = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_ADDRESS_IDX].strptr));
        RC.mac[j]->eth_params_s.remote_addr              = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_ADDRESS_IDX].strptr));
        RC.mac[j]->eth_params_s.my_portc                 = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTC_IDX].iptr);
        RC.mac[j]->eth_params_s.remote_portc             = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTC_IDX].iptr);
        RC.mac[j]->eth_params_s.my_portd                 = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTD_IDX].iptr);
        RC.mac[j]->eth_params_s.remote_portd             = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr);
        RC.mac[j]->eth_params_s.transp_preference        = ETH_UDP_MODE;
        LOG_I(ENB_APP,"**************** vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc);
        configure_nfapi_vnf(RC.mac[j]->eth_params_s.my_addr, RC.mac[j]->eth_params_s.my_portc,RC.mac[j]->eth_params_s.remote_addr,RC.mac[j]->eth_params_s.remote_portd,RC.mac[j]->eth_params_s.my_portd);
        LOG_I(ENB_APP,"**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc);
      } else { // other midhaul
        AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
      }

      if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr), "default") == 0) {
        global_scheduler_mode=SCHED_MODE_DEFAULT;
        LOG_I(ENB_APP,"sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr));
      } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr), "fairRR") == 0) {
        global_scheduler_mode=SCHED_MODE_FAIR_RR;
        printf("sched mode = fairRR %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr));
      } else {
        global_scheduler_mode=SCHED_MODE_DEFAULT;
        printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr));
      }

      char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr;
      void *d = dlsym(NULL, s);
      AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s);
      // release default, add new
      pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl;
      dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
      dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
      dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
      LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name);
    }// j=0..num_inst
  } /*else {// MacRLC_ParamList.numelt > 0 // ignore it

    AssertFatal (0,
                 "No " CONFIG_STRING_MACRLC_LIST " configuration found");
  }*/
}

int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) {
  int               num_enbs                      = 0;
  int               j,k                           = 0;
  int32_t enb_id = 0;
  int32_t           offsetMaxLimit                = 0;
  int32_t           cycleNb                       = 0;

  RrcConfigurationReq *RRCcfg = &rrc->configuration;
  ccparams_lte_t ccparams_lte;
  ccparams_sidelink_t SLconfig;
  ccparams_eMTC_t eMTCconfig;
  memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
  memset((void *)&SLconfig,0,sizeof(ccparams_sidelink_t));
  memset((void *)&eMTCconfig,0,sizeof(ccparams_eMTC_t));
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramdef_t ENBParams[]  = ENBPARAMS_DESC;
  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
  checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
  paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS,NULL,0};
  paramdef_t eMTCParams[]              = EMTCPARAMS_DESC((&eMTCconfig));
  checkedparam_t config_check_eMTCparams[] = EMTCPARAMS_CHECK;
  srb1_params_t srb1_params;
  memset((void *)&srb1_params,0,sizeof(srb1_params_t));
  paramdef_t SRB1Params[] = SRB1PARAMS_DESC(srb1_params);
  paramdef_t SLParams[]   = CCPARAMS_SIDELINK_DESC(SLconfig);

  /* map parameter checking array instances to parameter definition array instances */
  for (int I = 0; I < sizeofArray(CCsParams); I++) {
    CCsParams[I].chkPptr = &(config_check_CCparams[I]);
  }

  for (int I = 0; I < sizeofArray(CCsParams); I++) {
    eMTCParams[I].chkPptr = &(config_check_eMTCparams[I]);
  }

  /* get global parameters, defined outside any section in the config file */
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  num_enbs = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;
  AssertFatal (i<num_enbs,
               "Failed to parse config file no %uth element in %s \n",i, ENB_CONFIG_STRING_ACTIVE_ENBS);

  if (num_enbs>0) {
    // Output a list of all eNBs.
    config_getlist(config_get_if(), &ENBParamList, ENBParams, sizeofArray(ENBParams), NULL);

    if (ENBParamList.paramarray[i][ENB_ENB_ID_IDX].uptr == NULL) {
      // Calculate a default eNB ID
      if (EPC_MODE_ENABLED) {
        uint32_t hash;
        hash = s1ap_generate_eNB_id ();
        enb_id = i + (hash & 0xFFFF8);
      } else {
        enb_id = i;
      }
    } else {
      enb_id = *(ENBParamList.paramarray[i][ENB_ENB_ID_IDX].uptr);
    }

    LOG_I(RRC,"Instance %d: Southbound Transport %s\n",i,*(ENBParamList.paramarray[i][ENB_TRANSPORT_S_PREFERENCE_IDX].strptr));

    rrc->nr_cellid        = (uint64_t)*(ENBParamList.paramarray[i][ENB_NRCELLID_IDX].u64ptr);

    // search if in active list

    for (k=0; k <num_enbs ; k++) {
      if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[k], *(ENBParamList.paramarray[i][ENB_ENB_NAME_IDX].strptr)) == 0) {
        char enbpath[MAX_OPTNAME_SIZE + 8];
        sprintf(enbpath,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
        paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
        paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
        /* map parameter checking array instances to parameter definition array instances */
        checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;

        for (int I = 0; I < sizeofArray(PLMNParams); ++I)
          PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);

        // In the configuration file it is in seconds. For RRC it has to be in milliseconds
        RRCcfg->rrc_inactivity_timer_thres = (*ENBParamList.paramarray[i][ENB_RRC_INACTIVITY_THRES_IDX].uptr) * 1000;
        RRCcfg->cell_identity = enb_id;
        RRCcfg->tac = *ENBParamList.paramarray[i][ENB_TRACKING_AREA_CODE_IDX].uptr;
        AssertFatal(!ENBParamList.paramarray[i][ENB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr
                    && !ENBParamList.paramarray[i][ENB_MOBILE_NETWORK_CODE_IDX_OLD].strptr,
                    "It seems that you use an old configuration file. Please change the existing\n"
                    "    tracking_area_code  =  \"1\";\n"
                    "    mobile_country_code =  \"208\";\n"
                    "    mobile_network_code =  \"93\";\n"
                    "to\n"
                    "    tracking_area_code  =  1; // no string!!\n"
                    "    plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
        config_getlist(config_get_if(), &PLMNParamList, PLMNParams, sizeofArray(PLMNParams), enbpath);

        if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
          AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
                      PLMNParamList.numelt);

        RRCcfg->num_plmn = PLMNParamList.numelt;

        for (int l = 0; l < PLMNParamList.numelt; ++l) {
          RRCcfg->mcc[l] = *PLMNParamList.paramarray[l][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
          RRCcfg->mnc[l] = *PLMNParamList.paramarray[l][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
          RRCcfg->mnc_digit_length[l] = *PLMNParamList.paramarray[l][ENB_MNC_DIGIT_LENGTH].u8ptr;
          AssertFatal(RRCcfg->mnc_digit_length[l] == 3 || RRCcfg->mnc[l] < 100, "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n", RRCcfg->mnc[l]);
        }

        /* measurement reports enabled? */
        if (ENBParamList.paramarray[i][ENB_ENABLE_MEASUREMENT_REPORTS].strptr != NULL &&
            *(ENBParamList.paramarray[i][ENB_ENABLE_MEASUREMENT_REPORTS].strptr) != NULL &&
            !strcmp(*(ENBParamList.paramarray[i][ENB_ENABLE_MEASUREMENT_REPORTS].strptr), "yes"))
          RRCcfg->enable_measurement_reports = 1;
        else
          RRCcfg->enable_measurement_reports = 0;

        /* x2 enabled? */
        if (ENBParamList.paramarray[i][ENB_ENABLE_X2].strptr != NULL &&
            *(ENBParamList.paramarray[i][ENB_ENABLE_X2].strptr) != NULL &&
            !strcmp(*(ENBParamList.paramarray[i][ENB_ENABLE_X2].strptr), "yes"))
          RRCcfg->enable_x2 = 1;
        else
          RRCcfg->enable_x2 = 0;

       /* m2 enabled */
       if (ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr != NULL &&
            *(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr) != NULL &&
            !strcmp(*(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr), "yes"))
         RRCcfg->eMBMS_M2_configured = 1;
        else
          RRCcfg->eMBMS_M2_configured = 0;

        // Parse optional physical parameters
        config_getlist(config_get_if(), &CCsParamList, NULL, 0, enbpath);
        LOG_I(RRC,"num component carriers %d \n",CCsParamList.numelt);

        if ( CCsParamList.numelt> 0) {
          char ccspath[MAX_OPTNAME_SIZE*2 + 16];

          for (j = 0; j < CCsParamList.numelt ; j++) {
            sprintf(ccspath,"%s.%s.[%i]",enbpath,ENB_CONFIG_STRING_COMPONENT_CARRIERS,j);
            LOG_I(RRC,
                  "enb_config::RCconfig_RRC() parameter number: %d, total number of parameters: %zd, ccspath: %s \n \n",
                  j,
                  sizeofArray(CCsParams),
                  ccspath);
            config_get(config_get_if(), CCsParams, sizeofArray(CCsParams), ccspath);
            // printf("Component carrier %d\n",component_carrier);
            //  Cell params, MIB/SIB1
            RRCcfg->tdd_config[j] = ccparams_lte.tdd_config;
            AssertFatal (ccparams_lte.tdd_config <= LTE_TDD_Config__subframeAssignment_sa6,
                         "Failed to parse eNB configuration file %s, enb %u illegal tdd_config %d (should be 0-%d)!",
                         RC.config_file_name, i, ccparams_lte.tdd_config, LTE_TDD_Config__subframeAssignment_sa6);
            RRCcfg->tdd_config_s[j] = ccparams_lte.tdd_config_s;
            AssertFatal (ccparams_lte.tdd_config_s <= LTE_TDD_Config__specialSubframePatterns_ssp8,
                         "Failed to parse eNB configuration file %s, enb %u illegal tdd_config_s %d (should be 0-%d)!",
                         RC.config_file_name, i, ccparams_lte.tdd_config_s, LTE_TDD_Config__specialSubframePatterns_ssp8);

            if (!ccparams_lte.prefix_type)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: NORMAL,EXTENDED!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PREFIX_TYPE);
            else if (strcmp(ccparams_lte.prefix_type, "NORMAL") == 0) {
              RRCcfg->prefix_type[j] = NORMAL;
            } else  if (strcmp(ccparams_lte.prefix_type, "EXTENDED") == 0) {
              RRCcfg->prefix_type[j] = EXTENDED;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for prefix_type choice: NORMAL or EXTENDED !\n",
                           RC.config_file_name, i, ccparams_lte.prefix_type);
            }

            if (!ccparams_lte.pbch_repetition)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: TRUE,FALSE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PBCH_REPETITION);
            else if (strcmp(ccparams_lte.pbch_repetition, "TRUE") == 0) {
              RRCcfg->pbch_repetition[j] = 1;
            } else  if (strcmp(ccparams_lte.pbch_repetition, "FALSE") == 0) {
              RRCcfg->pbch_repetition[j] = 0;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pbch_repetition choice: TRUE or FALSE !\n",
                           RC.config_file_name, i, ccparams_lte.pbch_repetition);
            }

            RRCcfg->eutra_band[j] = ccparams_lte.eutra_band;
            RRCcfg->downlink_frequency[j] = (uint32_t)ccparams_lte.downlink_frequency;
            RRCcfg->uplink_frequency_offset[j] = (unsigned int)ccparams_lte.uplink_frequency_offset;
            RRCcfg->Nid_cell[j] = ccparams_lte.Nid_cell;

            if (ccparams_lte.Nid_cell>503) {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
                           RC.config_file_name, i, ccparams_lte.Nid_cell);
            }

            RRCcfg->N_RB_DL[j] = ccparams_lte.N_RB_DL;

            if ((ccparams_lte.N_RB_DL!=6) &&
                (ccparams_lte.N_RB_DL!=15) &&
                (ccparams_lte.N_RB_DL!=25) &&
                (ccparams_lte.N_RB_DL!=50) &&
                (ccparams_lte.N_RB_DL!=75) &&
                (ccparams_lte.N_RB_DL!=100)) {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
                           RC.config_file_name, i, ccparams_lte.N_RB_DL);
            }

            if (strcmp(ccparams_lte.frame_type, "FDD") == 0) {
              RRCcfg->frame_type[j] = FDD;
            } else  if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
              RRCcfg->frame_type[j] = TDD;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
                           RC.config_file_name, i, ccparams_lte.frame_type);
            }

            if (config_check_band_frequencies(j, RRCcfg->eutra_band[j], RRCcfg->downlink_frequency[j], RRCcfg->uplink_frequency_offset[j], RRCcfg->frame_type[j])) {
              AssertFatal(0, "error calling enb_check_band_frequencies\n");
            }

            if ((ccparams_lte.nb_antenna_ports <1) || (ccparams_lte.nb_antenna_ports > 2))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for nb_antenna_ports choice: 1..2 !\n",
                           RC.config_file_name, i, ccparams_lte.nb_antenna_ports);

            RRCcfg->nb_antenna_ports[j] = ccparams_lte.nb_antenna_ports;

            // Radio Resource Configuration (SIB2)
            RRCcfg->radioresourceconfig[j].prach_root = ccparams_lte.prach_root;

            if ((ccparams_lte.prach_root <0) || (ccparams_lte.prach_root > 1023))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for prach_root choice: 0..1023 !\n",
                           RC.config_file_name, i, ccparams_lte.prach_root);

            RRCcfg->radioresourceconfig[j].prach_config_index = ccparams_lte.prach_config_index;

            if ((ccparams_lte.prach_config_index <0) || (ccparams_lte.prach_config_index > 63))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for prach_config_index choice: 0..1023 !\n",
                           RC.config_file_name, i, ccparams_lte.prach_config_index);

            if (!ccparams_lte.prach_high_speed)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PRACH_HIGH_SPEED);
            else if (strcmp(ccparams_lte.prach_high_speed, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].prach_high_speed = true;
            } else if (strcmp(ccparams_lte.prach_high_speed, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].prach_high_speed = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for prach_config choice: ENABLE,DISABLE !\n",
                           RC.config_file_name, i, ccparams_lte.prach_high_speed);

            RRCcfg->radioresourceconfig[j].prach_zero_correlation = ccparams_lte.prach_zero_correlation;

            if ((ccparams_lte.prach_zero_correlation <0) ||
                (ccparams_lte.prach_zero_correlation > 15))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for prach_zero_correlation choice: 0..15!\n",
                           RC.config_file_name, i, ccparams_lte.prach_zero_correlation);

            RRCcfg->radioresourceconfig[j].prach_freq_offset = ccparams_lte.prach_freq_offset;

            if ((ccparams_lte.prach_freq_offset <0) ||
                (ccparams_lte.prach_freq_offset > 94))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for prach_freq_offset choice: 0..94!\n",
                           RC.config_file_name, i, ccparams_lte.prach_freq_offset);

            RRCcfg->radioresourceconfig[j].pucch_delta_shift = ccparams_lte.pucch_delta_shift - 1;

            if ((ccparams_lte.pucch_delta_shift <1) ||
                (ccparams_lte.pucch_delta_shift > 3))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pucch_delta_shift choice: 1..3!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_delta_shift);

            RRCcfg->radioresourceconfig[j].pucch_nRB_CQI = ccparams_lte.pucch_nRB_CQI;

            if ((ccparams_lte.pucch_nRB_CQI <0) ||
                (ccparams_lte.pucch_nRB_CQI > 98))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pucch_nRB_CQI choice: 0..98!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_nRB_CQI);

            RRCcfg->radioresourceconfig[j].pucch_nCS_AN = ccparams_lte.pucch_nCS_AN;

            if ((ccparams_lte.pucch_nCS_AN <0) ||
                (ccparams_lte.pucch_nCS_AN > 7))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pucch_nCS_AN choice: 0..7!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_nCS_AN);

            RRCcfg->radioresourceconfig[j].pucch_n1_AN = ccparams_lte.pucch_n1_AN;

            if ((ccparams_lte.pucch_n1_AN <0) ||
                (ccparams_lte.pucch_n1_AN > 2047))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pucch_n1_AN choice: 0..2047!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_n1_AN);

            RRCcfg->radioresourceconfig[j].pdsch_referenceSignalPower = ccparams_lte.pdsch_referenceSignalPower;

            if ((ccparams_lte.pdsch_referenceSignalPower <-60) ||
                (ccparams_lte.pdsch_referenceSignalPower > 50))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pdsch_referenceSignalPower choice:-60..50!\n",
                           RC.config_file_name, i, ccparams_lte.pdsch_referenceSignalPower);

            RRCcfg->radioresourceconfig[j].pdsch_p_b = ccparams_lte.pdsch_p_b;

            if ((ccparams_lte.pdsch_p_b <0) ||
                (ccparams_lte.pdsch_p_b > 3))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pdsch_p_b choice: 0..3!\n",
                           RC.config_file_name, i, ccparams_lte.pdsch_p_b);

            RRCcfg->radioresourceconfig[j].pusch_n_SB = ccparams_lte.pusch_n_SB;

            if ((ccparams_lte.pusch_n_SB <1) ||
                (ccparams_lte.pusch_n_SB > 4))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pusch_n_SB choice: 1..4!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_n_SB);

            if (!ccparams_lte.pusch_hoppingMode)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: interSubframe,intraAndInterSubframe!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_HOPPINGMODE);
            else if (strcmp(ccparams_lte.pusch_hoppingMode,"interSubFrame")==0) {
              RRCcfg->radioresourceconfig[j].pusch_hoppingMode = LTE_PUSCH_ConfigCommon__pusch_ConfigBasic__hoppingMode_interSubFrame;
            } else if (strcmp(ccparams_lte.pusch_hoppingMode,"intraAndInterSubFrame")==0) {
              RRCcfg->radioresourceconfig[j].pusch_hoppingMode = LTE_PUSCH_ConfigCommon__pusch_ConfigBasic__hoppingMode_intraAndInterSubFrame;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_hoppingMode choice: interSubframe,intraAndInterSubframe!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_hoppingMode);

            RRCcfg->radioresourceconfig[j].pusch_hoppingOffset = ccparams_lte.pusch_hoppingOffset;

            if ((ccparams_lte.pusch_hoppingOffset<0) ||
                (ccparams_lte.pusch_hoppingOffset>98))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_hoppingOffset choice: 0..98!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_hoppingMode);

            if (!ccparams_lte.pusch_enable64QAM)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_ENABLE64QAM);
            else if (strcmp(ccparams_lte.pusch_enable64QAM, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_enable64QAM = true;
            } else if (strcmp(ccparams_lte.pusch_enable64QAM, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_enable64QAM = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_enable64QAM choice: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_enable64QAM);

            if (!ccparams_lte.pusch_groupHoppingEnabled)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_GROUP_HOPPING_EN);
            else if (strcmp(ccparams_lte.pusch_groupHoppingEnabled, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_groupHoppingEnabled = true;
            } else if (strcmp(ccparams_lte.pusch_groupHoppingEnabled, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_groupHoppingEnabled = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_groupHoppingEnabled choice: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_groupHoppingEnabled);

            RRCcfg->radioresourceconfig[j].pusch_groupAssignment = ccparams_lte.pusch_groupAssignment;

            if ((ccparams_lte.pusch_groupAssignment<0)||
                (ccparams_lte.pusch_groupAssignment>29))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pusch_groupAssignment choice: 0..29!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_groupAssignment);

            if (!ccparams_lte.pusch_sequenceHoppingEnabled)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_SEQUENCE_HOPPING_EN);
            else if (strcmp(ccparams_lte.pusch_sequenceHoppingEnabled, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_sequenceHoppingEnabled = true;
            } else if (strcmp(ccparams_lte.pusch_sequenceHoppingEnabled, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].pusch_sequenceHoppingEnabled = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_sequenceHoppingEnabled choice: ENABLE,DISABLE!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_sequenceHoppingEnabled);

            RRCcfg->radioresourceconfig[j].pusch_nDMRS1 = ccparams_lte.pusch_nDMRS1; // cyclic_shift in RRC!

            if ((ccparams_lte.pusch_nDMRS1 <0) ||
                (ccparams_lte.pusch_nDMRS1>7))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pusch_nDMRS1 choice: 0..7!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_nDMRS1);

            if (strcmp(ccparams_lte.phich_duration,"NORMAL")==0) {
              RRCcfg->radioresourceconfig[j].phich_duration = LTE_PHICH_Config__phich_Duration_normal;
            } else if (strcmp(ccparams_lte.phich_duration,"EXTENDED")==0) {
              RRCcfg->radioresourceconfig[j].phich_duration = LTE_PHICH_Config__phich_Duration_extended;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for phich_duration choice: NORMAL,EXTENDED!\n",
                           RC.config_file_name, i, ccparams_lte.phich_duration);

            if (strcmp(ccparams_lte.phich_resource,"ONESIXTH")==0) {
              RRCcfg->radioresourceconfig[j].phich_resource = LTE_PHICH_Config__phich_Resource_oneSixth;
            } else if (strcmp(ccparams_lte.phich_resource,"HALF")==0) {
              RRCcfg->radioresourceconfig[j].phich_resource = LTE_PHICH_Config__phich_Resource_half;
            } else if (strcmp(ccparams_lte.phich_resource,"ONE")==0) {
              RRCcfg->radioresourceconfig[j].phich_resource = LTE_PHICH_Config__phich_Resource_one;
            } else if (strcmp(ccparams_lte.phich_resource,"TWO")==0) {
              RRCcfg->radioresourceconfig[j].phich_resource = LTE_PHICH_Config__phich_Resource_two;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for phich_resource choice: ONESIXTH,HALF,ONE,TWO!\n",
                           RC.config_file_name, i, ccparams_lte.phich_resource);

            printf("phich.resource %ld (%s), phich.duration %ld (%s)\n",
                   RRCcfg->radioresourceconfig[j].phich_resource,
                   ccparams_lte.phich_resource,
                   RRCcfg->radioresourceconfig[j].phich_duration,
                   ccparams_lte.phich_duration);

            if (strcmp(ccparams_lte.srs_enable, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].srs_enable = true;
            } else if (strcmp(ccparams_lte.srs_enable, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].srs_enable = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n",
                           RC.config_file_name, i, ccparams_lte.srs_enable);

            if (RRCcfg->radioresourceconfig[j].srs_enable == true) {
              RRCcfg->radioresourceconfig[j].srs_BandwidthConfig = ccparams_lte.srs_BandwidthConfig;

              if ((ccparams_lte.srs_BandwidthConfig < 0) ||
                  (ccparams_lte.srs_BandwidthConfig >7))
                AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value %d for srs_BandwidthConfig choice: 0...7\n",
                             RC.config_file_name, i, ccparams_lte.srs_BandwidthConfig);

              RRCcfg->radioresourceconfig[j].srs_SubframeConfig = ccparams_lte.srs_SubframeConfig;

              if ((ccparams_lte.srs_SubframeConfig<0) ||
                  (ccparams_lte.srs_SubframeConfig>15))
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for srs_SubframeConfig choice: 0..15 !\n",
                             RC.config_file_name, i, ccparams_lte.srs_SubframeConfig);

              if (strcmp(ccparams_lte.srs_ackNackST, "ENABLE") == 0) {
                RRCcfg->radioresourceconfig[j].srs_ackNackST = true;
              } else if (strcmp(ccparams_lte.srs_ackNackST, "DISABLE") == 0) {
                RRCcfg->radioresourceconfig[j].srs_ackNackST = false;
              } else
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n",
                             RC.config_file_name, i, ccparams_lte.srs_ackNackST);

              if (strcmp(ccparams_lte.srs_MaxUpPts, "ENABLE") == 0) {
                RRCcfg->radioresourceconfig[j].srs_MaxUpPts = true;
              } else if (strcmp(ccparams_lte.srs_MaxUpPts, "DISABLE") == 0) {
                RRCcfg->radioresourceconfig[j].srs_MaxUpPts = false;
              } else
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_MaxUpPts choice: ENABLE,DISABLE !\n",
                             RC.config_file_name, i, ccparams_lte.srs_MaxUpPts);
            }

            RRCcfg->radioresourceconfig[j].pusch_p0_Nominal = ccparams_lte.pusch_p0_Nominal;

            if ((ccparams_lte.pusch_p0_Nominal<-126) ||
                (ccparams_lte.pusch_p0_Nominal>24))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pusch_p0_Nominal choice: -126..24 !\n",
                           RC.config_file_name, i, ccparams_lte.pusch_p0_Nominal);

            if (strcmp(ccparams_lte.pusch_alpha,"AL0")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al0;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL04")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al04;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL05")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al05;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL06")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al06;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL07")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al07;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL08")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al08;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL09")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al09;
            } else if (strcmp(ccparams_lte.pusch_alpha,"AL1")==0) {
              RRCcfg->radioresourceconfig[j].pusch_alpha = LTE_Alpha_r12_al1;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_Alpha choice: AL0,AL04,AL05,AL06,AL07,AL08,AL09,AL1!\n",
                           RC.config_file_name, i, ccparams_lte.pusch_alpha);

            RRCcfg->radioresourceconfig[j].pucch_p0_Nominal = ccparams_lte.pucch_p0_Nominal;

            if ((ccparams_lte.pucch_p0_Nominal<-127) ||
                (ccparams_lte.pucch_p0_Nominal>-96))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pucch_p0_Nominal choice: -127..-96 !\n",
                           RC.config_file_name, i, ccparams_lte.pucch_p0_Nominal);

            RRCcfg->radioresourceconfig[j].msg3_delta_Preamble = ccparams_lte.msg3_delta_Preamble;

            if ((ccparams_lte.msg3_delta_Preamble<-1) ||
                (ccparams_lte.msg3_delta_Preamble>6))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for msg3_delta_Preamble choice: -1..6 !\n",
                           RC.config_file_name, i, ccparams_lte.msg3_delta_Preamble);

            if (strcmp(ccparams_lte.pucch_deltaF_Format1,"deltaF_2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1_deltaF_2;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format1,"deltaF0")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1_deltaF0;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format1,"deltaF2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1_deltaF2;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_deltaF_Format1 choice: deltaF_2,dltaF0,deltaF2!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_deltaF_Format1);

            if (strcmp(ccparams_lte.pucch_deltaF_Format1b,"deltaF1")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1b_deltaF1;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format1b,"deltaF3")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1b_deltaF3;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format1b,"deltaF5")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format1b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format1b_deltaF5;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_deltaF_Format1b choice: deltaF1,dltaF3,deltaF5!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_deltaF_Format1b);

            if (strcmp(ccparams_lte.pucch_deltaF_Format2,"deltaF_2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2_deltaF_2;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2,"deltaF0")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2_deltaF0;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2,"deltaF1")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2_deltaF1;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2,"deltaF2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2 = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2_deltaF2;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_deltaF_Format2 choice: deltaF_2,dltaF0,deltaF1,deltaF2!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_deltaF_Format2);

            if (strcmp(ccparams_lte.pucch_deltaF_Format2a,"deltaF_2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2a = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2a_deltaF_2;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2a,"deltaF0")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2a = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2a_deltaF0;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2a,"deltaF2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2a = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2a_deltaF2;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_deltaF_Format2a choice: deltaF_2,dltaF0,deltaF2!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_deltaF_Format2a);

            if (strcmp(ccparams_lte.pucch_deltaF_Format2b,"deltaF_2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2b_deltaF_2;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2b,"deltaF0")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2b_deltaF0;
            } else if (strcmp(ccparams_lte.pucch_deltaF_Format2b,"deltaF2")==0) {
              RRCcfg->radioresourceconfig[j].pucch_deltaF_Format2b = LTE_DeltaFList_PUCCH__deltaF_PUCCH_Format2b_deltaF2;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pucch_deltaF_Format2b choice: deltaF_2,dltaF0,deltaF2!\n",
                           RC.config_file_name, i, ccparams_lte.pucch_deltaF_Format2b);

            RRCcfg->radioresourceconfig[j].rach_numberOfRA_Preambles = (ccparams_lte.rach_numberOfRA_Preambles / 4) - 1;

            if ((ccparams_lte.rach_numberOfRA_Preambles <4) ||
                (ccparams_lte.rach_numberOfRA_Preambles>64) ||
                ((ccparams_lte.rach_numberOfRA_Preambles&3)!=0))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_numberOfRA_Preambles choice: 4,8,12,...,64!\n",
                           RC.config_file_name, i, ccparams_lte.rach_numberOfRA_Preambles);

            if (strcmp(ccparams_lte.rach_preamblesGroupAConfig, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].rach_preamblesGroupAConfig = true;
              RRCcfg->radioresourceconfig[j].rach_sizeOfRA_PreamblesGroupA = (ccparams_lte.rach_sizeOfRA_PreamblesGroupA / 4) - 1;

              if ((ccparams_lte.rach_numberOfRA_Preambles <4) ||
                  (ccparams_lte.rach_numberOfRA_Preambles>60) ||
                  ((ccparams_lte.rach_numberOfRA_Preambles&3)!=0))
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_sizeOfRA_PreamblesGroupA choice: 4,8,12,...,60!\n",
                             RC.config_file_name, i, ccparams_lte.rach_sizeOfRA_PreamblesGroupA);

              switch (ccparams_lte.rach_messageSizeGroupA) {
                case 56:
                  RRCcfg->radioresourceconfig[j].rach_messageSizeGroupA = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messageSizeGroupA_b56;
                  break;

                case 144:
                  RRCcfg->radioresourceconfig[j].rach_messageSizeGroupA = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messageSizeGroupA_b144;
                  break;

                case 208:
                  RRCcfg->radioresourceconfig[j].rach_messageSizeGroupA = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messageSizeGroupA_b208;
                  break;

                case 256:
                  RRCcfg->radioresourceconfig[j].rach_messageSizeGroupA = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messageSizeGroupA_b256;
                  break;

                default:
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_messageSizeGroupA choice: 56,144,208,256!\n",
                               RC.config_file_name, i, ccparams_lte.rach_messageSizeGroupA);
                  break;
              }

              if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"minusinfinity")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_minusinfinity;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB0")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB0;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB5")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB5;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB8")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB8;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB10")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB10;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB12")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB12;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB15")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB15;
              } else if (strcmp(ccparams_lte.rach_messagePowerOffsetGroupB,"dB18")==0) {
                RRCcfg->radioresourceconfig[j].rach_messagePowerOffsetGroupB = LTE_RACH_ConfigCommon__preambleInfo__preamblesGroupAConfig__messagePowerOffsetGroupB_dB18;
              } else
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for rach_messagePowerOffsetGroupB choice: minusinfinity,dB0,dB5,dB8,dB10,dB12,dB15,dB18!\n",
                             RC.config_file_name, i, ccparams_lte.rach_messagePowerOffsetGroupB);
            } else if (strcmp(ccparams_lte.rach_preamblesGroupAConfig, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].rach_preamblesGroupAConfig = false;
            } else
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for rach_preamblesGroupAConfig choice: ENABLE,DISABLE !\n",
                           RC.config_file_name, i, ccparams_lte.rach_preamblesGroupAConfig);

            RRCcfg->radioresourceconfig[j].rach_preambleInitialReceivedTargetPower = (ccparams_lte.rach_preambleInitialReceivedTargetPower + 120) / 2;

            if ((ccparams_lte.rach_preambleInitialReceivedTargetPower<-120) ||
                (ccparams_lte.rach_preambleInitialReceivedTargetPower>-90) ||
                ((ccparams_lte.rach_preambleInitialReceivedTargetPower&1)!=0))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_preambleInitialReceivedTargetPower choice: -120,-118,...,-90 !\n",
                           RC.config_file_name, i, ccparams_lte.rach_preambleInitialReceivedTargetPower);

            RRCcfg->radioresourceconfig[j].rach_powerRampingStep = ccparams_lte.rach_powerRampingStep / 2;

            if ((ccparams_lte.rach_powerRampingStep<0) ||
                (ccparams_lte.rach_powerRampingStep>6) ||
                ((ccparams_lte.rach_powerRampingStep&1)!=0))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_powerRampingStep choice: 0,2,4,6 !\n",
                           RC.config_file_name, i, ccparams_lte.rach_powerRampingStep);

            switch (ccparams_lte.rach_preambleTransMax) {
              case 3:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n3;
                break;

              case 4:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n4;
                break;

              case 5:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n5;
                break;

              case 6:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n6;
                break;

              case 7:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n7;
                break;

              case 8:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n8;
                break;

              case 10:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n10;
                break;

              case 20:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n20;
                break;

              case 50:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n50;
                break;

              case 100:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n100;
                break;

              case 200:
                RRCcfg->radioresourceconfig[j].rach_preambleTransMax = LTE_PreambleTransMax_n200;
                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_preambleTransMax choice: 3,4,5,6,7,8,10,20,50,100,200!\n",
                             RC.config_file_name, i, ccparams_lte.rach_preambleTransMax);
                break;
            }

            RRCcfg->radioresourceconfig[j].rach_raResponseWindowSize = (ccparams_lte.rach_raResponseWindowSize == 10) ? 7 : ccparams_lte.rach_raResponseWindowSize - 2;

            if ((ccparams_lte.rach_raResponseWindowSize<0)||
                (ccparams_lte.rach_raResponseWindowSize==9)||
                (ccparams_lte.rach_raResponseWindowSize>10))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_raResponseWindowSize choice: 2,3,4,5,6,7,8,10!\n",
                           RC.config_file_name, i, ccparams_lte.rach_preambleTransMax);

            RRCcfg->radioresourceconfig[j].rach_macContentionResolutionTimer = (ccparams_lte.rach_macContentionResolutionTimer / 8) - 1;

            if ((ccparams_lte.rach_macContentionResolutionTimer<8) ||
                (ccparams_lte.rach_macContentionResolutionTimer>64) ||
                ((ccparams_lte.rach_macContentionResolutionTimer&7)!=0))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_macContentionResolutionTimer choice: 8,16,...,56,64!\n",
                           RC.config_file_name, i, ccparams_lte.rach_preambleTransMax);

            RRCcfg->radioresourceconfig[j].rach_maxHARQ_Msg3Tx = ccparams_lte.rach_maxHARQ_Msg3Tx;

            if ((ccparams_lte.rach_maxHARQ_Msg3Tx<0) ||
                (ccparams_lte.rach_maxHARQ_Msg3Tx>8))
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for rach_maxHARQ_Msg3Tx choice: 1..8!\n",
                           RC.config_file_name, i, ccparams_lte.rach_preambleTransMax);

            switch (ccparams_lte.pcch_defaultPagingCycle) {
              case 32:
                RRCcfg->radioresourceconfig[j].pcch_defaultPagingCycle = LTE_PCCH_Config__defaultPagingCycle_rf32;
                break;

              case 64:
                RRCcfg->radioresourceconfig[j].pcch_defaultPagingCycle = LTE_PCCH_Config__defaultPagingCycle_rf64;
                break;

              case 128:
                RRCcfg->radioresourceconfig[j].pcch_defaultPagingCycle = LTE_PCCH_Config__defaultPagingCycle_rf128;
                break;

              case 256:
                RRCcfg->radioresourceconfig[j].pcch_defaultPagingCycle = LTE_PCCH_Config__defaultPagingCycle_rf256;
                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for pcch_defaultPagingCycle choice: 32,64,128,256!\n",
                             RC.config_file_name, i, ccparams_lte.pcch_defaultPagingCycle);
                break;
            }

            if (strcmp(ccparams_lte.pcch_nB, "fourT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_fourT;
            } else if (strcmp(ccparams_lte.pcch_nB, "twoT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_twoT;
            } else if (strcmp(ccparams_lte.pcch_nB, "oneT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_oneT;
            } else if (strcmp(ccparams_lte.pcch_nB, "halfT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_halfT;
            } else if (strcmp(ccparams_lte.pcch_nB, "quarterT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_quarterT;
            } else if (strcmp(ccparams_lte.pcch_nB, "oneEighthT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_oneEighthT;
            } else if (strcmp(ccparams_lte.pcch_nB, "oneSixteenthT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_oneSixteenthT;
            } else if (strcmp(ccparams_lte.pcch_nB, "oneThirtySecondT") == 0) {
              RRCcfg->radioresourceconfig[j].pcch_nB = LTE_PCCH_Config__nB_oneThirtySecondT;
            } else {
              AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pcch_nB choice: fourT,twoT,oneT,halfT,quarterT,oneighthT,oneSixteenthT,oneThirtySecondT !\n",
                           RC.config_file_name,
                           i,
                           ccparams_lte.pcch_nB);
            }

            if (strcmp(ccparams_lte.drx_Config_present, "prNothing") == 0) {
              RRCcfg->radioresourceconfig[j].drx_Config_present = LTE_DRX_Config_PR_NOTHING;
            } else if (strcmp(ccparams_lte.drx_Config_present, "prRelease") == 0) {
              RRCcfg->radioresourceconfig[j].drx_Config_present = LTE_DRX_Config_PR_release;
            } else if (strcmp(ccparams_lte.drx_Config_present, "prSetup") == 0) {
              RRCcfg->radioresourceconfig[j].drx_Config_present = LTE_DRX_Config_PR_setup;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for drx_Config_present choice: prNothing, prRelease, prSetup!\n",
                           RC.config_file_name, i, ccparams_lte.drx_Config_present);
            }

            if (strcmp(ccparams_lte.drx_onDurationTimer, "psf1") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf1;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf2") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf2;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf3") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf3;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf4") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf4;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf5") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf5;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf6") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf6;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf8") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf8;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf10") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf10;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf20") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf20;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf30") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf30;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf40") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf40;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf50") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf50;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf60") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf60;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf80") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf80;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf100") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf100;
            } else if (strcmp(ccparams_lte.drx_onDurationTimer, "psf200") == 0) {
              RRCcfg->radioresourceconfig[j].drx_onDurationTimer = (long)LTE_DRX_Config__setup__onDurationTimer_psf200;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for drx_onDurationTimer choice !\n",
                           RC.config_file_name, i, ccparams_lte.drx_onDurationTimer);
              break;
            }

            if (strcmp(ccparams_lte.drx_InactivityTimer, "psf1") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf1;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf2") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf2;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf3") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf3;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf4") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf4;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf5") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf5;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf6") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf6;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf8") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf8;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf10") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf10;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf20") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf20;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf30") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf30;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf40") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf40;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf50") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf50;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf60") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf60;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf80") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf80;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf100") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf100;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf200") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf200;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf300") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf300;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf500") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf500;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf750") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf750;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf1280") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf1280;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf1920") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf1920;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf2560") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf2560;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "psf0-v1020") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_psf0_v1020;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare9") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare9;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare8") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare8;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare7") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare7;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare6") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare6;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare5") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare5;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare4") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare4;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare3") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare3;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare2") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare2;
            } else if (strcmp(ccparams_lte.drx_InactivityTimer, "spare1") == 0) {
              RRCcfg->radioresourceconfig[j].drx_InactivityTimer = (long)LTE_DRX_Config__setup__drx_InactivityTimer_spare1;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for drx_InactivityTimer choice !\n",
                           RC.config_file_name, i, ccparams_lte.drx_InactivityTimer);
              break;
            }

            RRCcfg->radioresourceconfig[j].ue_multiple_max = ccparams_lte.ue_multiple_max;

            if (!ccparams_lte.mbms_dedicated_serving_cell)
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u define %s: TRUE,FALSE!\n",
                           RC.config_file_name, i, ENB_CONFIG_STRING_MBMS_DEDICATED_SERVING_CELL);
            else if (strcmp(ccparams_lte.mbms_dedicated_serving_cell, "ENABLE") == 0) {
              RRCcfg->radioresourceconfig[j].mbms_dedicated_serving_cell = true;
            } else  if (strcmp(ccparams_lte.mbms_dedicated_serving_cell, "DISABLE") == 0) {
              RRCcfg->radioresourceconfig[j].mbms_dedicated_serving_cell = false;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for mbms_dedicated_serving_cell choice: TRUE or FALSE !\n",
                           RC.config_file_name, i, ccparams_lte.mbms_dedicated_serving_cell);
            }

            switch (ccparams_lte.N_RB_DL) {
              case 25:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 4))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..4!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              case 50:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 8))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..8!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              case 100:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 16))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..16!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for N_RB_DL choice: 25,50,100 !\n",
                             RC.config_file_name, i, ccparams_lte.N_RB_DL);
                break;
            }

            if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf1") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf1;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf2") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf2;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf4") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf4;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf6") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf6;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf8") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf8;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf16") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf16;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf24") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf24;
            } else if (strcmp(ccparams_lte.drx_RetransmissionTimer, "psf33") == 0) {
              RRCcfg->radioresourceconfig[j].drx_RetransmissionTimer = (long)LTE_DRX_Config__setup__drx_RetransmissionTimer_psf33;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for drx_RetransmissionTimer choice !\n",
                           RC.config_file_name, i, ccparams_lte.drx_RetransmissionTimer);
              break;
            }

            if (ccparams_lte.drx_longDrx_CycleStartOffset_present == NULL || strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prNothing") == 0) {
              RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_NOTHING;
            } else {
              if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf10") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf10;
                offsetMaxLimit = 10;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf20") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf20;
                offsetMaxLimit = 20;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf32") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf32;
                offsetMaxLimit = 32;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf40") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf40;
                offsetMaxLimit = 40;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf64") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf64;
                offsetMaxLimit = 64;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf80") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf80;
                offsetMaxLimit = 80;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf128") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf128;
                offsetMaxLimit = 128;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf160") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf160;
                offsetMaxLimit = 160;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf256") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf256;
                offsetMaxLimit = 256;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf320") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf320;
                offsetMaxLimit = 320;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf512") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf512;
                offsetMaxLimit = 512;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf640") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf640;
                offsetMaxLimit = 640;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf1024") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1024;
                offsetMaxLimit = 1024;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf1280") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1280;
                offsetMaxLimit = 1280;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf2048") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2048;
                offsetMaxLimit = 2048;
              } else if (strcmp(ccparams_lte.drx_longDrx_CycleStartOffset_present, "prSf2560") == 0) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset_present = LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2560;
                offsetMaxLimit = 2560;
              } else {
                AssertFatal (0,
                             "Failed to parse eNB configuration file \"%s\", enb %u unknown string value \"%s\" for drx_longDrx_CycleStartOffset_present choice !\n",
                             RC.config_file_name, i, ccparams_lte.drx_longDrx_CycleStartOffset_present);
              }

              if (ccparams_lte.drx_longDrx_CycleStartOffset >= 0 && ccparams_lte.drx_longDrx_CycleStartOffset < offsetMaxLimit) {
                RRCcfg->radioresourceconfig[j].drx_longDrx_CycleStartOffset = ccparams_lte.drx_longDrx_CycleStartOffset;
              } else {
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u incoherent value \"%d\" for drx_longDrx_CycleStartOffset !\n",
                             RC.config_file_name, i, ccparams_lte.drx_longDrx_CycleStartOffset);
              }
            }

            if  (strcmp(ccparams_lte.drx_shortDrx_Cycle, "") == 0 || ccparams_lte.drx_shortDrx_ShortCycleTimer == 0) {
              if  (strcmp(ccparams_lte.drx_shortDrx_Cycle, "") != 0 || ccparams_lte.drx_shortDrx_ShortCycleTimer != 0) {
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u incoherent values \"%s\" -  \"%d\" for drx_shortDrx_Cycle or drx_shortDrx_ShortCycleTimer choice !\n",
                             RC.config_file_name, i, ccparams_lte.drx_shortDrx_Cycle, ccparams_lte.drx_shortDrx_ShortCycleTimer);
              } else {
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = -1;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_ShortCycleTimer = 0;
              }
            } else {
              if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf2") == 0) {
                cycleNb = 2;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf2;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf5") == 0) {
                cycleNb = 5;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf5;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf8") == 0) {
                cycleNb = 8;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf8;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf10") == 0) {
                cycleNb = 10;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf10;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf16") == 0) {
                cycleNb = 16;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf16;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf20") == 0) {
                cycleNb = 20;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf20;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf32") == 0) {
                cycleNb = 32;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf32;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf40") == 0) {
                cycleNb = 40;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf40;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf64") == 0) {
                cycleNb = 64;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf64;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf80") == 0) {
                cycleNb = 80;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf80;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf128") == 0) {
                cycleNb = 128;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf128;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf160") == 0) {
                cycleNb = 160;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf160;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf256") == 0) {
                cycleNb = 256;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf256;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf320") == 0) {
                cycleNb = 320;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf320;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf512") == 0) {
                cycleNb = 512;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf512;
              } else if (strcmp(ccparams_lte.drx_shortDrx_Cycle, "sf640") == 0) {
                cycleNb = 640;
                RRCcfg->radioresourceconfig[j].drx_shortDrx_Cycle = LTE_DRX_Config__setup__shortDRX__shortDRX_Cycle_sf640;
              } else {
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u incoherent value \"%s\" for drx_shortDrx_Cycle !\n",
                             RC.config_file_name, i, ccparams_lte.drx_shortDrx_Cycle);
              }

              if (cycleNb > 0 && (offsetMaxLimit % cycleNb != 0 || cycleNb == offsetMaxLimit)) {
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u incompatible (not multiple) values \"%d\" -  \"%d\" for drx_shortDrx_Cycle and drx_longDrx_CycleStartOffset choice !\n",
                             RC.config_file_name, i, cycleNb, offsetMaxLimit);
              }

              if (ccparams_lte.drx_shortDrx_ShortCycleTimer >= 1 && ccparams_lte.drx_shortDrx_ShortCycleTimer <= 16 ) {
                RRCcfg->radioresourceconfig[j].drx_shortDrx_ShortCycleTimer = ccparams_lte.drx_shortDrx_ShortCycleTimer;
              } else {
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for drx_shortDrx_ShortCycleTimer choice !\n",
                             RC.config_file_name, i, ccparams_lte.drx_shortDrx_ShortCycleTimer );
              }
            }

            switch (ccparams_lte.bcch_modificationPeriodCoeff) {
              case 2:
                RRCcfg->radioresourceconfig[j].bcch_modificationPeriodCoeff = LTE_BCCH_Config__modificationPeriodCoeff_n2;
                break;

              case 4:
                RRCcfg->radioresourceconfig[j].bcch_modificationPeriodCoeff = LTE_BCCH_Config__modificationPeriodCoeff_n4;
                break;

              case 8:
                RRCcfg->radioresourceconfig[j].bcch_modificationPeriodCoeff = LTE_BCCH_Config__modificationPeriodCoeff_n8;
                break;

              case 16:
                RRCcfg->radioresourceconfig[j].bcch_modificationPeriodCoeff = LTE_BCCH_Config__modificationPeriodCoeff_n16;
                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for bcch_modificationPeriodCoeff choice: 2,4,8,16",
                             RC.config_file_name, i, ccparams_lte.bcch_modificationPeriodCoeff);
                break;
            }

            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_t300 = ccparams_lte.ue_TimersAndConstants_t300;
            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_t301 = ccparams_lte.ue_TimersAndConstants_t301;
            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_t310 = ccparams_lte.ue_TimersAndConstants_t310;
            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_t311 = ccparams_lte.ue_TimersAndConstants_t311;
            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_n310 = ccparams_lte.ue_TimersAndConstants_n310;
            RRCcfg->radioresourceconfig[j].ue_TimersAndConstants_n311 = ccparams_lte.ue_TimersAndConstants_n311;

            switch (ccparams_lte.ue_TransmissionMode) {
              case 1:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm1;
                break;

              case 2:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm2;
                break;

              case 3:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm3;
                break;

              case 4:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm4;
                break;

              case 5:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm5;
                break;

              case 6:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm6;
                break;

              case 7:
                RRCcfg->radioresourceconfig[j].ue_TransmissionMode = LTE_AntennaInfoDedicated__transmissionMode_tm7;
                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_TransmissionMode choice: 1,2,3,4,5,6,7",
                             RC.config_file_name, i, ccparams_lte.ue_TransmissionMode);
                break;
            }

            RRCcfg->radioresourceconfig[j].ue_multiple_max = ccparams_lte.ue_multiple_max;

            switch (ccparams_lte.N_RB_DL) {
              case 25:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 4))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..4!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              case 50:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 8))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..8!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              case 100:
                if ((ccparams_lte.ue_multiple_max < 1) ||
                    (ccparams_lte.ue_multiple_max > 16))
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for ue_multiple_max choice: 1..16!\n",
                               RC.config_file_name, i, ccparams_lte.ue_multiple_max);

                break;

              default:
                AssertFatal (0,
                             "Failed to parse eNB configuration file %s, enb %u unknown value \"%d\" for N_RB_DL choice: 25,50,100 !\n",
                             RC.config_file_name, i, ccparams_lte.N_RB_DL);
                break;
            }

            // eMBMS configuration
            RRCcfg->eMBMS_configured = 0;
            printf("No eMBMS configuration, skipping it\n");
            // eMTC configuration
            char brparamspath[MAX_OPTNAME_SIZE*2 + 160];
            sprintf(brparamspath,"%s.%s", ccspath, ENB_CONFIG_STRING_EMTC_PARAMETERS);
            config_get(config_get_if(), eMTCParams, sizeofArray(eMTCParams), brparamspath);
            RRCcfg->eMTC_configured = eMTCconfig.eMTC_configured & 1;

            if (eMTCconfig.eMTC_configured > 0)
              fill_eMTC_configuration(RRCcfg, &eMTCconfig, i, j, RC.config_file_name, brparamspath);
            else                            printf("No eMTC configuration, skipping it\n");

            // Sidelink configuration
            char SLparamspath[MAX_OPTNAME_SIZE*2 + 160];
            sprintf(SLparamspath,"%s.%s", ccspath, ENB_CONFIG_STRING_SL_PARAMETERS);
            config_get(config_get_if(), SLParams, sizeofArray(SLParams), SLparamspath);
            // Sidelink Resource pool information
            RRCcfg->SL_configured = SLconfig.sidelink_configured & 1;

            if (SLconfig.sidelink_configured == 1)
              fill_SL_configuration(RRCcfg, &SLconfig, i, j, RC.config_file_name);
            else                                 printf("No SL configuration skipping it\n");
          }

          RRCcfg->nr_scg_ssb_freq = ccparams_lte.nr_scg_ssb_freq;

          char srb1path[MAX_OPTNAME_SIZE*2 + 8];
          sprintf(srb1path,"%s.%s",enbpath,ENB_CONFIG_STRING_SRB1);
          config_get(config_get_if(), SRB1Params, sizeofArray(SRB1Params), srb1path);

          switch (srb1_params.srb1_max_retx_threshold) {
            case 1:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t1;
              break;

            case 2:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t2;
              break;

            case 3:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t3;
              break;

            case 4:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t4;
              break;

            case 6:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t6;
              break;

            case 8:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t8;
              break;

            case 16:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t16;
              break;

            case 32:
              rrc->srb1_max_retx_threshold = LTE_UL_AM_RLC__maxRetxThreshold_t32;
              break;

            default:
              AssertFatal (0,
                           "Bad config value when parsing eNB configuration file %s, enb %u  srb1_max_retx_threshold %d!\n",
                           RC.config_file_name, i, srb1_params.srb1_max_retx_threshold);
          }

          switch (srb1_params.srb1_poll_pdu) {
            case 4:
              rrc->srb1_poll_pdu = LTE_PollPDU_p4;
              break;

            case 8:
              rrc->srb1_poll_pdu = LTE_PollPDU_p8;
              break;

            case 16:
              rrc->srb1_poll_pdu = LTE_PollPDU_p16;
              break;

            case 32:
              rrc->srb1_poll_pdu = LTE_PollPDU_p32;
              break;

            case 64:
              rrc->srb1_poll_pdu = LTE_PollPDU_p64;
              break;

            case 128:
              rrc->srb1_poll_pdu = LTE_PollPDU_p128;
              break;

            case 256:
              rrc->srb1_poll_pdu = LTE_PollPDU_p256;
              break;

            default:
              if (srb1_params.srb1_poll_pdu >= 10000)
                rrc->srb1_poll_pdu = LTE_PollPDU_pInfinity;
              else
                AssertFatal (0,
                             "Bad config value when parsing eNB configuration file %s, enb %u  srb1_poll_pdu %d!\n",
                             RC.config_file_name, i, srb1_params.srb1_poll_pdu);
          }

          rrc->srb1_poll_byte             = srb1_params.srb1_poll_byte;

          switch (srb1_params.srb1_poll_byte) {
            case 25:
              rrc->srb1_poll_byte = LTE_PollByte_kB25;
              break;

            case 50:
              rrc->srb1_poll_byte = LTE_PollByte_kB50;
              break;

            case 75:
              rrc->srb1_poll_byte = LTE_PollByte_kB75;
              break;

            case 100:
              rrc->srb1_poll_byte = LTE_PollByte_kB100;
              break;

            case 125:
              rrc->srb1_poll_byte = LTE_PollByte_kB125;
              break;

            case 250:
              rrc->srb1_poll_byte = LTE_PollByte_kB250;
              break;

            case 375:
              rrc->srb1_poll_byte = LTE_PollByte_kB375;
              break;

            case 500:
              rrc->srb1_poll_byte = LTE_PollByte_kB500;
              break;

            case 750:
              rrc->srb1_poll_byte = LTE_PollByte_kB750;
              break;

            case 1000:
              rrc->srb1_poll_byte = LTE_PollByte_kB1000;
              break;

            case 1250:
              rrc->srb1_poll_byte = LTE_PollByte_kB1250;
              break;

            case 1500:
              rrc->srb1_poll_byte = LTE_PollByte_kB1500;
              break;

            case 2000:
              rrc->srb1_poll_byte = LTE_PollByte_kB2000;
              break;

            case 3000:
              rrc->srb1_poll_byte = LTE_PollByte_kB3000;
              break;

            default:
              if (srb1_params.srb1_poll_byte >= 10000)
                rrc->srb1_poll_byte = LTE_PollByte_kBinfinity;
              else
                AssertFatal (0,
                             "Bad config value when parsing eNB configuration file %s, enb %u  srb1_poll_byte %d!\n",
                             RC.config_file_name, i, srb1_params.srb1_poll_byte);
          }

          if (srb1_params.srb1_timer_poll_retransmit <= 250) {
            rrc->srb1_timer_poll_retransmit = (srb1_params.srb1_timer_poll_retransmit - 5)/5;
          } else if (srb1_params.srb1_timer_poll_retransmit <= 500) {
            rrc->srb1_timer_poll_retransmit = (srb1_params.srb1_timer_poll_retransmit - 300)/50 + 50;
          } else {
            AssertFatal (0,
                         "Bad config value when parsing eNB configuration file %s, enb %u  srb1_timer_poll_retransmit %d!\n",
                         RC.config_file_name, i, srb1_params.srb1_timer_poll_retransmit);
          }

          if (srb1_params.srb1_timer_status_prohibit <= 250) {
            rrc->srb1_timer_status_prohibit = srb1_params.srb1_timer_status_prohibit/5;
          } else if ((srb1_params.srb1_timer_poll_retransmit >= 300) && (srb1_params.srb1_timer_poll_retransmit <= 500)) {
            rrc->srb1_timer_status_prohibit = (srb1_params.srb1_timer_status_prohibit - 300)/50 + 51;
          } else {
            AssertFatal (0,
                         "Bad config value when parsing eNB configuration file %s, enb %u  srb1_timer_status_prohibit %d!\n",
                         RC.config_file_name, i, srb1_params.srb1_timer_status_prohibit);
          }

          switch (srb1_params.srb1_timer_reordering) {
            case 0:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms0;
              break;

            case 5:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms5;
              break;

            case 10:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms10;
              break;

            case 15:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms15;
              break;

            case 20:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms20;
              break;

            case 25:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms25;
              break;

            case 30:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms30;
              break;

            case 35:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms35;
              break;

            case 40:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms40;
              break;

            case 45:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms45;
              break;

            case 50:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms50;
              break;

            case 55:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms55;
              break;

            case 60:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms60;
              break;

            case 65:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms65;
              break;

            case 70:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms70;
              break;

            case 75:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms75;
              break;

            case 80:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms80;
              break;

            case 85:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms85;
              break;

            case 90:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms90;
              break;

            case 95:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms95;
              break;

            case 100:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms100;
              break;

            case 110:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms110;
              break;

            case 120:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms120;
              break;

            case 130:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms130;
              break;

            case 140:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms140;
              break;

            case 150:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms150;
              break;

            case 160:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms160;
              break;

            case 170:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms170;
              break;

            case 180:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms180;
              break;

            case 190:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms190;
              break;

            case 200:
              rrc->srb1_timer_reordering = LTE_T_Reordering_ms200;
              break;

            default:
              AssertFatal (0,
                           "Bad config value when parsing eNB configuration file %s, enb %u  srb1_timer_reordering %d!\n",
                           RC.config_file_name, i, srb1_params.srb1_timer_reordering);
          }
        }
      }
    }
  }

  return 0;
}

int RCconfig_gtpu(void ) {
  int               num_enbs                      = 0;
  char             *enb_interface_name_for_S1U    = NULL;
  char             *enb_ipv4_address_for_S1U      = NULL;
  uint16_t enb_port_for_S1U = 0;
  char             *address                       = NULL;
  char             *cidr                          = NULL;
  char gtpupath[MAX_OPTNAME_SIZE*2 + 8];
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramdef_t GTPUParams[]  = GTPUPARAMS_DESC;
  LOG_I(GTPU,"Configuring GTPu\n");
  /* get number of active eNodeBs */
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  num_enbs = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;
  AssertFatal (num_enbs >0,
               "Failed to parse config file no active eNodeBs in %s \n", ENB_CONFIG_STRING_ACTIVE_ENBS);
  sprintf(gtpupath,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,0,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
  config_get(config_get_if(), GTPUParams, sizeofArray(GTPUParams), gtpupath);
  cidr = enb_ipv4_address_for_S1U;
  address = strtok(cidr, "/");

  if (address) {
    MessageDef *message;
    AssertFatal((message = itti_alloc_new_message(TASK_ENB_APP, 0, GTPV1U_REQ))!=NULL,"");
    IPV4_STR_ADDR_TO_INT_NWBO ( address, GTPV1U_REQ(message).localAddr, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" );
    LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_REQ(message).localAddr);
    GTPV1U_REQ(message).localPort = enb_port_for_S1U;
    strcpy(GTPV1U_REQ(message).localAddrStr,address);
    sprintf(GTPV1U_REQ(message).localPortStr,"%d", enb_port_for_S1U);
    itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
  } else
    LOG_E(GTPU,"invalid address for S1U\n");

  return 0;
}

int RCconfig_M2(MessageDef *msg_p, uint32_t i) {
  int   I, J, j, k, l;
  int   enb_id;
  char *address = NULL;
  char *cidr    = NULL;
  ccparams_lte_t ccparams_lte;
  memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramdef_t ENBParams[]  = ENBPARAMS_DESC;
  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
  /* get global parameters, defined outside any section in the config file */
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
  paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};

 // ccparams_MCE_t MCEconfig;
 // memset((void *)&MCEconfig,0,sizeof(ccparams_MCE_t));
 // paramdef_t MCEParams[]              = MCEPARAMS_DESC((&MCEconfig));
 // checkedparam_t config_check_MCEparams[] = MCEPARAMS_CHECK;


  /* map parameter checking array instances to parameter definition array instances */
  for (I = 0; I < sizeofArray(CCsParams); I++) {
    CCsParams[I].chkPptr = &(config_check_CCparams[I]);
  }

  AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
              "Failed to parse config file %s, %uth attribute %s \n",
              RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);

  if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
    // Output a list of all eNBs.
    config_getlist(config_get_if(), &ENBParamList, ENBParams, sizeofArray(ENBParams), NULL);

    if (ENBParamList.numelt > 0) {
      for (k = 0; k < ENBParamList.numelt; k++) {
        if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
          // Calculate a default eNB ID
          if (EPC_MODE_ENABLED) {
            uint32_t hash;
            hash = s1ap_generate_eNB_id ();
            enb_id = k + (hash & 0xFFFF8);
          } else {
            enb_id = k;
          }
        } else {
          enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
        }

        // search if in active list
        for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
          if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
            paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
            paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
            /* map parameter checking array instances to parameter definition array instances */
            checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;

            for (int I = 0; I < sizeofArray(PLMNParams); ++I)
              PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);

            paramdef_t M2Params[]  = M2PARAMS_DESC;
            paramlist_def_t M2ParamList = {ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS,NULL,0};
            paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
            paramdef_t NETParams[]  =  NETPARAMS_DESC;
            paramdef_t MBMSConfigParams[]  = MBMS_CONFIG_PARAMS_DESC;
            paramdef_t MBMSParams[]  = MBMSPARAMS_DESC;
           paramlist_def_t MBMSConfigParamList = {ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,NULL,0};
           paramlist_def_t MBMSParamList = {ENB_CONFIG_STRING_MBMS_SERVICE_AREA_LIST,NULL,0};
            /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
            /* this is most probably a problem with the config module */
            char aprefix[MAX_OPTNAME_SIZE*80 + 8];
            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
            /* Some default/random parameters */
            M2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;

            if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
              M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
              M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
            } else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
                           RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
            }

            M2AP_REGISTER_ENB_REQ (msg_p).eNB_name         = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
            M2AP_REGISTER_ENB_REQ (msg_p).tac              = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr;
            config_getlist(config_get_if(), &PLMNParamList, PLMNParams, sizeofArray(PLMNParams), aprefix);

            //            char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
            //            sprintf(aprefix2,"%s.[%i].%s.[0]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST);
            //            config_getlist(config_get_if(),&MBMSParamList, MBMSParams, sizeofArray(MBMSParams),
            //            aprefix2);
            //         if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
            //              AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
            //                          MBMSParamList.numelt);
            //         M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_service_area_list = MBMSParamList.numelt;
            //         for(J=0; J<MBMSParamList.numelt;J++){
            //             M2AP_REGISTER_ENB_REQ (msg_p).mbms_service_area_list[J] =
            //             *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
            //         }
            //

            char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
            sprintf(aprefix2,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
            config_getlist(config_get_if(), &MBMSConfigParamList, MBMSConfigParams, sizeofArray(MBMSConfigParams), aprefix2);
            if (MBMSConfigParamList.numelt < 1 || MBMSConfigParamList.numelt > 8)
              AssertFatal(0, "The number of MBMS Config Data must be in [1,8], but is %d\n",
                          MBMSConfigParamList.numelt);
            M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_configuration_data_list = MBMSConfigParamList.numelt;
           for(int I=0; I < MBMSConfigParamList.numelt; I++){

                   sprintf(aprefix2,"%s.[%i].%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,I);
                   config_getlist(config_get_if(), &MBMSParamList, MBMSParams, sizeofArray(MBMSParams), aprefix2);
                   if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
                     AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
                                 MBMSParamList.numelt);
                   M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].num_mbms_service_area_list = MBMSParamList.numelt;
                   for(J=0; J<MBMSParamList.numelt;J++){
                       M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].mbms_service_area_list[J] = *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
                   }

          }


            if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
              AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
                          PLMNParamList.numelt);

            if (PLMNParamList.numelt > 1)
              LOG_W(M2AP, "M2AP currently handles only one PLMN, ignoring the others!\n");

            M2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
            M2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
            M2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr;
            AssertFatal(M2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3
                        || M2AP_REGISTER_ENB_REQ(msg_p).mnc < 100,
                        "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
                        M2AP_REGISTER_ENB_REQ(msg_p).mnc);
            /* CC params */
            config_getlist(config_get_if(), &CCsParamList, NULL, 0, aprefix);
            M2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt;

            if (CCsParamList.numelt > 0) {
              //char ccspath[MAX_OPTNAME_SIZE*2 + 16];
              for (J = 0; J < CCsParamList.numelt ; J++) {
                sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J);
                config_get(config_get_if(), CCsParams, sizeofArray(CCsParams), aprefix);
                M2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band;
                M2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency;
                M2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset;
                M2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell;

                if (ccparams_lte.Nid_cell>503) {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
                               RC.config_file_name, k, ccparams_lte.Nid_cell);
                }

                M2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL;

                if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
                               RC.config_file_name, k, ccparams_lte.N_RB_DL);
                }

                if (strcmp(ccparams_lte.frame_type, "FDD") == 0) {
                  M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
                } else  if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
                  M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
                } else {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
                               RC.config_file_name, k, ccparams_lte.frame_type);
                }

                M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL);
                M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);
              }
            }

            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
            config_getlist(config_get_if(), &M2ParamList, M2Params, sizeofArray(M2Params), aprefix);
            AssertFatal(M2ParamList.numelt <= M2AP_MAX_NB_ENB_IP_ADDRESS,
                        "value of M2ParamList.numelt %d must be lower than M2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase M2AP_MAX_NB_ENB_IP_ADDRESS\n",
                        M2ParamList.numelt,M2AP_MAX_NB_ENB_IP_ADDRESS);
            M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 = 0;

            for (l = 0; l < M2ParamList.numelt; l++) {
              M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 += 1;
              strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4_address,*(M2ParamList.paramarray[l][ENB_M2_IPV4_ADDRESS_IDX].strptr));
              strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6_address,*(M2ParamList.paramarray[l][ENB_M2_IPV6_ADDRESS_IDX].strptr));

              if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 0;
              } else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 0;
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
              } else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
              }
            }
            // timers
            //{
            //  int t_reloc_prep = 0;
            //  int tx2_reloc_overall = 0;
            //  paramdef_t p[] = {
            //    { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 },
            //    { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }
            //  };
            //  config_get(p, sizeofArray(p), aprefix);

            //  if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
            //      tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) {
            //    LOG_E(M2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n");
            //    exit(1);
            //  }

            //  M2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
            //  M2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
            //}
            // SCTP SETTING
            M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
            M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams  = SCTP_IN_STREAMS;

            if (EPC_MODE_ENABLED) {
              sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
              config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
              M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
              M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
            }

            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
            // NETWORK_INTERFACES
            config_get(config_get_if(), NETParams, sizeofArray(NETParams), aprefix);
            M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C = (uint32_t)*(NETParams[ENB_PORT_FOR_M2C_IDX].uptr);

            if ((NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr == NULL) || (M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C == 0)) {
              LOG_E(RRC,"Add eNB IPv4 address and/or port for M2C in the CONF file!\n");
              exit(1);
            }

            cidr = *(NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr);
            address = strtok(cidr, "/");
            M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv6 = 0;
            M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4 = 1;
            strcpy(M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4_address, address);
          }
        }
      }
    }
  }

  return 0;
}

//-----------------------------------------------------------------------------
/*
* Configure the s1ap_register_enb_req in itti message for future
* communications between eNB(s) and MME.
*/
int RCconfig_S1(
  MessageDef *msg_p,
  uint32_t i)
//-----------------------------------------------------------------------------
{
  int enb_id = 0;
  int32_t my_int = 0;
  const char *active_enb[MAX_ENB];
  char *address = NULL;
  char *cidr    = NULL;
  ccparams_lte_t ccparams_lte;
  memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
  // for no gcc warnings
  (void)my_int;
  memset((char *)active_enb, 0, MAX_ENB * sizeof(char *));
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramdef_t ENBParams[] = ENBPARAMS_DESC;
  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST, NULL, 0};
  /* get global parameters, defined outside any section in the config file */
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  AssertFatal (i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
               "Failed to parse config file %s, %uth attribute %s \n",
               RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);

  if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
    // Output a list of all eNBs.
    config_getlist(config_get_if(), &ENBParamList, ENBParams, sizeofArray(ENBParams), NULL);

    if (ENBParamList.numelt > 0) {
      for (int k = 0; k < ENBParamList.numelt; k++) {
        if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
          // Calculate a default eNB ID
          if (EPC_MODE_ENABLED) {
            uint32_t hash = 0;
            hash = s1ap_generate_eNB_id();
            enb_id = k + (hash & 0xFFFF8);
          } else {
            enb_id = k;
          }
        } else {
          enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
        }

        // search if in active list
        for (int j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
          if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
            paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
            paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
            paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
            /* map parameter checking array instances to parameter definition array instances */
            checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;

            for (int I = 0; I < sizeofArray(CCsParams); I++) {
              CCsParams[I].chkPptr = &(config_check_CCparams[I]);
            }

            /* map parameter checking array instances to parameter definition array instances */
            checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;

            for (int I = 0; I < sizeofArray(PLMNParams); ++I) {
              PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
            }

            paramdef_t S1Params[] = S1PARAMS_DESC;
            paramlist_def_t S1ParamList = {ENB_CONFIG_STRING_MME_IP_ADDRESS, NULL, 0};
            paramdef_t SCTPParams[] = SCTPPARAMS_DESC;
            paramdef_t NETParams[] =  NETPARAMS_DESC;
            char aprefix[MAX_OPTNAME_SIZE*2 + 8];
            sprintf(aprefix, "%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k);
            S1AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;

            if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
              S1AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
              S1AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
              // Temporary option to be able to parse an eNB configuration file which is treated as gNB from
              // the X2AP layer and test the setup of an ENDC X2AP connection. To be removed when we are ready to
              // parse an actual gNB configuration file wrt. the X2AP parameters instead.
            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) {
              S1AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_GNB;
            } else {
              AssertFatal(0,
                          "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
                          RC.config_file_name,
                          i,
                          *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
            }

            S1AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
            S1AP_REGISTER_ENB_REQ(msg_p).tac = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr;
            AssertFatal(!ENBParamList.paramarray[k][ENB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr
                        && !ENBParamList.paramarray[k][ENB_MOBILE_NETWORK_CODE_IDX_OLD].strptr,
                        "It seems that you use an old configuration file. Please change the existing\n"
                        "    tracking_area_code  =  \"1\";\n"
                        "    mobile_country_code =  \"208\";\n"
                        "    mobile_network_code =  \"93\";\n"
                        "to\n"
                        "    tracking_area_code  =  1; // no string!!\n"
                        "    plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
            if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff)
            {
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr;
            }
            else
            {
              LOG_E(S1AP, 
                    "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n",
                    *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr);
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5;
            }

            if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff)
            {
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr;
            }
            else
            {
              LOG_E(S1AP, 
                    "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n",
                    *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr);
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5;
            }

            if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff)
            {
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr;
            }
            else
            {
              LOG_E(S1AP, 
                    "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n",
                    *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr);
              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff;
            }

            if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff)
            {
              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr;
            }
            else
            {
              LOG_E(S1AP, 
                    "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n",
                    *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr);
              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180;
            }

            if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff)
            {
              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr;
            }
            else
            {
              LOG_E(S1AP, 
                    "sctp_req_count value in conf file is invalid (%d). Default value is set.\n",
                    *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr);
              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff;
            }
            config_getlist(config_get_if(), &PLMNParamList, PLMNParams, sizeofArray(PLMNParams), aprefix);

            if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) {
              AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
                          PLMNParamList.numelt);
            }

            S1AP_REGISTER_ENB_REQ(msg_p).num_plmn = PLMNParamList.numelt;

            for (int l = 0; l < PLMNParamList.numelt; ++l) {
              S1AP_REGISTER_ENB_REQ(msg_p).mcc[l] = *PLMNParamList.paramarray[l][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
              S1AP_REGISTER_ENB_REQ(msg_p).mnc[l] = *PLMNParamList.paramarray[l][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
              S1AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length[l] = *PLMNParamList.paramarray[l][ENB_MNC_DIGIT_LENGTH].u8ptr;
              AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length[l] == 3
                          || S1AP_REGISTER_ENB_REQ(msg_p).mnc[l] < 100,
                          "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
                          S1AP_REGISTER_ENB_REQ(msg_p).mnc[l]);
            }

            /* Default DRX param */
            /*
            * Here we get the config of the first CC, since the s1ap_register_enb_req_t doesn't support multiple CC.
            * There is a unique value of defaultPagingCycle per eNB (same for multiple cells).
            * Hence, it should be stated somewhere that the value should be the same for every CC, or put the value outside the CC
            * in the conf file.
            */
            sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, 0);
            config_get(config_get_if(), CCsParams, sizeofArray(CCsParams), aprefix);

            switch (ccparams_lte.pcch_defaultPagingCycle) {
              case 32: {
                S1AP_REGISTER_ENB_REQ(msg_p).default_drx = 0;
                break;
              }

              case 64: {
                S1AP_REGISTER_ENB_REQ(msg_p).default_drx = 1;
                break;
              }

              case 128: {
                S1AP_REGISTER_ENB_REQ(msg_p).default_drx = 2;
                break;
              }

              case 256: {
                S1AP_REGISTER_ENB_REQ(msg_p).default_drx = 3;
                break;
              }

              default: {
                LOG_E(S1AP, "Default I-DRX value in conf file is invalid (%i). Should be 32, 64, 128 or 256. \
                       Default DRX set to 32 in MME configuration\n",
                      ccparams_lte.pcch_defaultPagingCycle);
                S1AP_REGISTER_ENB_REQ(msg_p).default_drx = 0;
              }
            }

            /* MME connection params */
            sprintf(aprefix, "%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k);
            config_getlist(config_get_if(), &S1ParamList, S1Params, sizeofArray(S1Params), aprefix);
            S1AP_REGISTER_ENB_REQ (msg_p).nb_mme = 0;

            for (int l = 0; l < S1ParamList.numelt; l++) {
              S1AP_REGISTER_ENB_REQ (msg_p).nb_mme += 1;
              strcpy(S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4_address,*(S1ParamList.paramarray[l][ENB_MME_IPV4_ADDRESS_IDX].strptr));
              strcpy(S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6_address,*(S1ParamList.paramarray[l][ENB_MME_IPV6_ADDRESS_IDX].strptr));

              if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1;
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 0;
              } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 0;
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1;
              } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1;
                S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1;
              }

              if (S1ParamList.paramarray[l][ENB_MME_BROADCAST_PLMN_INDEX].iptr) {
                S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = S1ParamList.paramarray[l][ENB_MME_BROADCAST_PLMN_INDEX].numelt;
              } else {
                S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = 0;
              }

              /* set S1-mme port (sctp) */
              S1AP_REGISTER_ENB_REQ(msg_p).mme_port[l] = *S1ParamList.paramarray[l][ENB_MME_PORT_IDX].u16ptr;

              AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] <= S1AP_REGISTER_ENB_REQ(msg_p).num_plmn,
                          "List of broadcast PLMN to be sent to MME can not be longer than actual "
                          "PLMN list (max %d, but is %d)\n",
                          S1AP_REGISTER_ENB_REQ(msg_p).num_plmn,
                          S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l]);

              for (int el = 0; el < S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l]; ++el) {
                /* UINTARRAY gets mapped to int, see config_libconfig.c:223 */
                S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] = S1ParamList.paramarray[l][ENB_MME_BROADCAST_PLMN_INDEX].iptr[el];
                AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] >= 0
                            && S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] < S1AP_REGISTER_ENB_REQ(msg_p).num_plmn,
                            "index for MME's MCC/MNC (%d) is an invalid index for the registered PLMN IDs (%d)\n",
                            S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el],
                            S1AP_REGISTER_ENB_REQ(msg_p).num_plmn);
              }

              /* if no broadcasst_plmn array is defined, fill default values */
              if (S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] == 0) {
                S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = S1AP_REGISTER_ENB_REQ(msg_p).num_plmn;

                for (int el = 0; el < S1AP_REGISTER_ENB_REQ(msg_p).num_plmn; ++el) {
                  S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] = el;
                }
              }
            }

            // SCTP SETTING
            S1AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
            S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams  = SCTP_IN_STREAMS;

            if (EPC_MODE_ENABLED) {
              sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
              config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
              S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
              S1AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
            }

            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
            // NETWORK_INTERFACES
            config_get(config_get_if(), NETParams, sizeofArray(NETParams), aprefix);
            cidr = *(NETParams[ENB_IPV4_ADDRESS_FOR_S1_MME_IDX].strptr);
            address = strtok(cidr, "/");
            S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv6 = 0;
            S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv4 = 1;
            strcpy(S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv4_address, address);
            break;
          }
        }
      }
    }
  }

  return 0;
}

int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
  int   I, J, j, k, l;
  int   enb_id;
  char *address = NULL;
  char *cidr    = NULL;
  ccparams_lte_t ccparams_lte;
  memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramdef_t ENBParams[]  = ENBPARAMS_DESC;
  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
  /* get global parameters, defined outside any section in the config file */
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
  paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};

  /* map parameter checking array instances to parameter definition array instances */
  for (I = 0; I < sizeofArray(CCsParams); I++) {
    CCsParams[I].chkPptr = &(config_check_CCparams[I]);
  }

  AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
              "Failed to parse config file %s, %uth attribute %s \n",
              RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);

  if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
    // Output a list of all eNBs.
    config_getlist(config_get_if(), &ENBParamList, ENBParams, sizeofArray(ENBParams), NULL);

    if (ENBParamList.numelt > 0) {
      for (k = 0; k < ENBParamList.numelt; k++) {
        if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
          // Calculate a default eNB ID
          if (EPC_MODE_ENABLED) {
            uint32_t hash;
            hash = s1ap_generate_eNB_id ();
            enb_id = k + (hash & 0xFFFF8);
          } else {
            enb_id = k;
          }
        } else {
          enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
        }

        // search if in active list
        for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
          if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
            paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
            paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
            /* map parameter checking array instances to parameter definition array instances */
            checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;

            for (int I = 0; I < sizeofArray(PLMNParams); ++I)
              PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);

            paramdef_t X2Params[]  = X2PARAMS_DESC;
            paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0};
            paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
            paramdef_t NETParams[]  =  NETPARAMS_DESC;
            /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
            /* this is most probably a problem with the config module */
            char aprefix[MAX_OPTNAME_SIZE*80 + 8];
            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
            /* Some default/random parameters */
            X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;

            if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
              X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
              X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
            }else {
              AssertFatal (0,
                           "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
                           RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
            }

            X2AP_REGISTER_ENB_REQ (msg_p).eNB_name         = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
            X2AP_REGISTER_ENB_REQ (msg_p).tac              = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr;
            config_getlist(config_get_if(), &PLMNParamList, PLMNParams, sizeofArray(PLMNParams), aprefix);

            if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
              AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
                          PLMNParamList.numelt);

            if (PLMNParamList.numelt > 1)
              LOG_W(X2AP, "X2AP currently handles only one PLMN, ignoring the others!\n");

            X2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
            X2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
            X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr;
            AssertFatal(X2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3
                        || X2AP_REGISTER_ENB_REQ(msg_p).mnc < 100,
                        "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
                        X2AP_REGISTER_ENB_REQ(msg_p).mnc);
            /* CC params */
            config_getlist(config_get_if(), &CCsParamList, NULL, 0, aprefix);
            X2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt;

            if (CCsParamList.numelt > 0) {
              //char ccspath[MAX_OPTNAME_SIZE*2 + 16];
              for (J = 0; J < CCsParamList.numelt ; J++) {
                sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J);
                config_get(config_get_if(), CCsParams, sizeofArray(CCsParams), aprefix);
                X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band;
                X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency;
                X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset;
                X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell;

                if (ccparams_lte.Nid_cell>503) {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
                               RC.config_file_name, k, ccparams_lte.Nid_cell);
                }

                X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL;

                if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
                               RC.config_file_name, k, ccparams_lte.N_RB_DL);
                }

                if (strcmp(ccparams_lte.frame_type, "FDD") == 0) {
                  X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
                } else  if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
                  X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
                  X2AP_REGISTER_ENB_REQ (msg_p).subframeAssignment[J] = ccparams_lte.tdd_config;
                  X2AP_REGISTER_ENB_REQ (msg_p).specialSubframe[J] = ccparams_lte.tdd_config_s;
                } else {
                  AssertFatal (0,
                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
                               RC.config_file_name, k, ccparams_lte.frame_type);
                }

                X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL);
                X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);
              }
            }

            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
            config_getlist(config_get_if(), &X2ParamList, X2Params, sizeofArray(X2Params), aprefix);
            AssertFatal(X2ParamList.numelt <= X2AP_MAX_NB_ENB_IP_ADDRESS,
                        "value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n",
                        X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS);
            X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0;
            LOG_I(X2AP,"X2ParamList.numelt %d\n",X2ParamList.numelt);
            for (l = 0; l < X2ParamList.numelt; l++) {
              X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1;
              strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr));
              strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr));

              LOG_I(X2AP,"registering with ip : %s\n",*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr));
              if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 0;
              } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 0;
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
              } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
              }
            }

            // timers
            {
              int t_reloc_prep = 0;
              int tx2_reloc_overall = 0;
              int t_dc_prep = 0;
              int t_dc_overall = 0;
              paramdef_t p[] = {
                { "t_reloc_prep", "t_reloc_prep", 0, .iptr=&t_reloc_prep, .defintval=0, TYPE_INT, 0 },
                { "tx2_reloc_overall", "tx2_reloc_overall", 0, .iptr=&tx2_reloc_overall, .defintval=0, TYPE_INT, 0 },
                { "t_dc_prep", "t_dc_prep", 0, .iptr=&t_dc_prep, .defintval=0, TYPE_INT, 0 },
                { "t_dc_overall", "t_dc_overall", 0, .iptr=&t_dc_overall, .defintval=0, TYPE_INT, 0 }
              };
              config_get(config_get_if(), p, sizeofArray(p), aprefix);

              if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
                  tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 ||
                  t_dc_prep <= 0 || t_dc_prep > 10000 ||
                  t_dc_overall <= 0 || t_dc_overall > 20000) {
                LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000] and [0 < t_dc_prep <= 10000] and [0 < t_dc_overall <= 20000]\n");
                exit(1);
              }

              X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
              X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep;
              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall;
            }
            // SCTP SETTING
            X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
            X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams  = SCTP_IN_STREAMS;

            if (EPC_MODE_ENABLED) {
              sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
              config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
              X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
              X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
            }

            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
            // NETWORK_INTERFACES
            config_get(config_get_if(), NETParams, sizeofArray(NETParams), aprefix);
            X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C = (uint32_t)*(NETParams[ENB_PORT_FOR_X2C_IDX].uptr);

            if ((NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr == NULL) || (X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C == 0)) {
             LOG_E(RRC,"Add eNB IPv4 address and/or port for X2C in the CONF file!\n");
             exit(1);
           }

            cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr);
            address = strtok(cidr, "/");
            X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0;
            X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1;
            strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address);
          }
        }
      }
    }
  }

  return 0;
}

int RCconfig_parallel(void) {
  char *parallel_conf = NULL;
  char *worker_conf   = NULL;
  paramdef_t ThreadParams[]  = THREAD_CONF_DESC;
  paramlist_def_t THREADParamList = {THREAD_CONFIG_STRING_THREAD_STRUCT,NULL,0};
  config_getlist(config_get_if(), &THREADParamList, NULL, 0, NULL);

  if(parallel_config == NULL) {
    if(THREADParamList.numelt>0) {
      config_getlist(config_get_if(), &THREADParamList, ThreadParams, sizeofArray(ThreadParams), NULL);
      parallel_conf = strdup(*(THREADParamList.paramarray[0][THREAD_PARALLEL_IDX].strptr));
    } else {
      parallel_conf = strdup("PARALLEL_RU_L1_TRX_SPLIT");
    }

    set_parallel_conf(parallel_conf);
  }

  if(worker_config == NULL) {
    if(THREADParamList.numelt>0) {
      config_getlist(config_get_if(), &THREADParamList, ThreadParams, sizeofArray(ThreadParams), NULL);
      worker_conf   = strdup(*(THREADParamList.paramarray[0][THREAD_WORKER_IDX].strptr));
    } else {
      worker_conf   = strdup("WORKER_ENABLE");
    }

    set_worker_conf(worker_conf);
  }

  free(worker_conf);
  free(parallel_conf);
  return 0;
}

void RCConfig(void) {
  paramlist_def_t MACRLCParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
  paramlist_def_t L1ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
  paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS,NULL,0};
  char aprefix[MAX_OPTNAME_SIZE*2 + 8];
  /* get global parameters, defined outside any section in the config file */
  printf("Getting ENBSParams\n");
  config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
  //EPC_MODE_ENABLED = ((*ENBSParams[ENB_NOS1_IDX].uptr) == 0);
  RC.nb_inst = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;

  if (RC.nb_inst > 0) {
    RC.nb_CC = (int *)malloc((1+RC.nb_inst)*sizeof(int));

    for (int i=0; i<RC.nb_inst; i++) {
      sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,i);
      config_getlist(config_get_if(), &CCsParamList, NULL, 0, aprefix);
      RC.nb_CC[i]    = CCsParamList.numelt;
    }
  }

  config_getlist(config_get_if(), &MACRLCParamList, NULL, 0, NULL);
  RC.nb_macrlc_inst  = MACRLCParamList.numelt;
  AssertFatal(RC.nb_macrlc_inst <= MAX_MAC_INST,
              "Too many macrlc instances %d\n",RC.nb_macrlc_inst);
  // Get num L1 instances
  config_getlist(config_get_if(), &L1ParamList, NULL, 0, NULL);
  RC.nb_L1_inst = L1ParamList.numelt;
  // Get num RU instances
  config_getlist(config_get_if(), &RUParamList, NULL, 0, NULL);
  RC.nb_RU     = RUParamList.numelt;
  RCconfig_parallel();
}

int check_plmn_identity(rrc_eNB_carrier_data_t *carrier,uint16_t mcc,uint16_t mnc,uint8_t mnc_digit_length) {
  AssertFatal(carrier->sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count > 0,
              "plmn info isn't there\n");
  AssertFatal(mnc_digit_length ==2 || mnc_digit_length == 3,
              "impossible mnc_digit_length %d\n",mnc_digit_length);
  LTE_PLMN_IdentityInfo_t *plmn_Identity_info = carrier->sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0];

  // check if mcc is different and return failure if so
  if (mcc !=
      (*plmn_Identity_info->plmn_Identity.mcc->list.array[0]*100)+
      (*plmn_Identity_info->plmn_Identity.mcc->list.array[1]*10) +
      (*plmn_Identity_info->plmn_Identity.mcc->list.array[2])) return(0);

  // check that mnc digit length is different and return failure if so
  if (mnc_digit_length != plmn_Identity_info->plmn_Identity.mnc.list.count) return 0;

  // check that 2 digit mnc is different and return failure if so
  if (mnc_digit_length == 2 &&
      (mnc !=
       (*plmn_Identity_info->plmn_Identity.mnc.list.array[0]*10) +
       (*plmn_Identity_info->plmn_Identity.mnc.list.array[1]))) return(0);
  else if (mnc_digit_length == 3 &&
           (mnc !=
            (*plmn_Identity_info->plmn_Identity.mnc.list.array[0]*100) +
            (*plmn_Identity_info->plmn_Identity.mnc.list.array[1]*10) +
            (*plmn_Identity_info->plmn_Identity.mnc.list.array[2]))) return(0);

  // if we're here, the mcc/mnc match so return success
  return(1);
}

void extract_and_decode_SI(int inst,int si_ind,uint8_t *si_container,int si_container_length) {
  eNB_RRC_INST *rrc = RC.rrc[inst];
  rrc_eNB_carrier_data_t *carrier = &rrc->carrier[0];
  LTE_BCCH_DL_SCH_Message_t *bcch_message ;
  AssertFatal(si_ind==2,"Can only handle a single SI block for now\n");
  LOG_I(ENB_APP, "rrc inst %d: Trying to decode SI block %d @ %p, length %d\n",inst,si_ind,si_container,si_container_length);
  // point to first SI block
  bcch_message = &carrier->systemInformation;
  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
                            &asn_DEF_LTE_BCCH_DL_SCH_Message,
                            (void **)&bcch_message,
                            (const void *)si_container,
                            si_container_length);

  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0, "[ENB_APP][RRC inst %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n",
                inst,
                dec_rval.consumed );
  }

  if (bcch_message->message.present == LTE_BCCH_DL_SCH_MessageType_PR_c1) {
    switch (bcch_message->message.choice.c1.present) {
      case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
        AssertFatal(1==0,"Should have received SIB1 from CU\n");
        break;

      case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: {
        LTE_SystemInformation_t *si = &bcch_message->message.choice.c1.choice.systemInformation;

        for (int i=0; i<si->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
          LOG_I(ENB_APP,"Extracting SI %d/%d\n",i,si->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count);
          struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
          typeandinfo = si->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];

          switch(typeandinfo->present) {
            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
              carrier->sib2 = &typeandinfo->choice.sib2;
              carrier->SIB23 = (uint8_t *)malloc(64);
              memcpy((void *)carrier->SIB23,(void *)si_container,si_container_length);
              carrier->sizeof_SIB23 = si_container_length;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB2\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3:
              carrier->sib3 = &typeandinfo->choice.sib3;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB3\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4:
              //carrier->sib4 = &typeandinfo->choice.sib4;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB4\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5:
              //carrier->sib5 = &typeandinfo->choice.sib5;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB5\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6:
              //carrier->sib6 = &typeandinfo->choice.sib6;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB6\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7:
              //carrier->sib7 = &typeandinfo->choice.sib7;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB7\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8:
              //carrier->sib8 = &typeandinfo->choice.sib8;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB8\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9:
              //carrier->sib9 = &typeandinfo->choice.sib9;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB9\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10:
              //carrier->sib10 = &typeandinfo->choice.sib10;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB10\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11:
              //carrier->sib11 = &typeandinfo->choice.sib11;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB11\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920:
              //carrier->sib12 = &typeandinfo->choice.sib12;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB12\n", inst);
              break;

            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920:
              carrier->sib13 = &typeandinfo->choice.sib13_v920;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB13\n", inst);
              break;

            //SIB18
            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250:
              carrier->sib18 = &typeandinfo->choice.sib18_v1250;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB18\n", inst);
              break;

            //SIB19
            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250:
              carrier->sib19 = &typeandinfo->choice.sib19_v1250;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB19\n", inst);
              break;

            //SIB21
            case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430:
              carrier->sib21 = &typeandinfo->choice.sib21_v1430;
              LOG_I( ENB_APP, "[RRC %"PRIu8"] Found SIB21\n", inst);
              break;

            default:
              AssertFatal(1==0,"Shouldn't have received this SI %d\n",typeandinfo->present);
              break;
          }
        }

        break;
      }

      case LTE_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
        AssertFatal(0, "Should have received SIB1 from CU\n");
        break;
    }
  } else AssertFatal(1==0,"No SI messages\n");
}

void configure_du_mac(int inst) {
  eNB_RRC_INST *rrc = RC.rrc[inst];
  rrc_eNB_carrier_data_t *carrier = &rrc->carrier[0];
  LOG_I(ENB_APP,"Configuring MAC/L1 %d, carrier->sib2 %p\n",inst,&carrier->sib2->radioResourceConfigCommon);
  rrc_mac_config_req_eNB_t tmp = {0};
  tmp.physCellId = carrier->physCellId;
  tmp.p_eNB = carrier->p_eNB;
  tmp.Ncp = carrier->Ncp;
  tmp.eutra_band = carrier->sib1->freqBandIndicator;
  tmp.dl_CarrierFreq = carrier->dl_CarrierFreq;
  tmp.pbch_repetition = carrier->pbch_repetition;
  tmp.mib = &carrier->mib;
  tmp.radioResourceConfigCommon = &carrier->sib2->radioResourceConfigCommon;
  tmp.LTE_radioResourceConfigCommon_BR = &carrier->sib2_BR->radioResourceConfigCommon;
  tmp.tdd_Config = carrier->sib1->tdd_Config;
  tmp.schedulingInfoList = &carrier->sib1->schedulingInfoList;
  tmp.ul_CarrierFreq = carrier->ul_CarrierFreq;
  tmp.ul_Bandwidth = carrier->sib2->freqInfo.ul_Bandwidth;
  tmp.additionalSpectrumEmission = &carrier->sib2->freqInfo.additionalSpectrumEmission;
  tmp.mbsfn_SubframeConfigList = carrier->sib2->mbsfn_SubframeConfigList;
  tmp.MBMS_Flag = carrier->MBMS_flag;
  tmp.mbsfn_AreaInfoList = &carrier->sib13->mbsfn_AreaInfoList_r9;
  rrc_mac_config_req_eNB(inst, &tmp);
}

void read_config_and_init(void) {

  if (RC.nb_macrlc_inst > 0)
    AssertFatal(RC.nb_macrlc_inst == RC.nb_inst,
                "Number of MACRLC instances %d != number of RRC instances %d\n",
                RC.nb_macrlc_inst, RC.nb_inst);

  RCconfig_L1();
  LOG_I(PHY, "%s() RC.nb_L1_inst: %d\n", __FUNCTION__, RC.nb_L1_inst);
  RCconfig_macrlc();
  LOG_I(MAC, "%s() RC.nb_macrlc_inst: %d\n", __FUNCTION__, RC.nb_macrlc_inst);

  if (RC.nb_L1_inst > 0)
    AssertFatal(l1_north_init_eNB() == 0, "could not initialize L1 north interface\n");

  RC.rrc = malloc(RC.nb_inst * sizeof(eNB_RRC_INST *));
  AssertFatal(RC.rrc, "could not allocate memory for RC.rrc\n");

  for (uint32_t enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
    RC.rrc[enb_id] = malloc(sizeof(eNB_RRC_INST));
    AssertFatal(RC.rrc[enb_id], "RRC context for eNB %u not allocated\n", enb_id);
    memset((void *)RC.rrc[enb_id], 0, sizeof(eNB_RRC_INST));
    RCconfig_RRC(enb_id, RC.rrc[enb_id]);
  }
}
