enb_config.c 29.3 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

gauthier's avatar
gauthier committed
28
*******************************************************************************/
nikaeinn's avatar
nikaeinn committed
29

gauthier's avatar
gauthier committed
30 31 32 33 34 35 36
/*
                                enb_config.c
                             -------------------
  AUTHOR  : Lionel GAUTHIER, Laurent Winckel
  COMPANY : EURECOM
  EMAIL   : Lionel.Gauthier@eurecom.fr
*/
37 38 39

#include <string.h>
#include <libconfig.h>
40
#include <inttypes.h>
41

42
#include "log.h"
43 44
#include "assertions.h"
#include "enb_config.h"
winckel's avatar
winckel committed
45 46 47 48
#if defined(OAI_EMU)
# include "OCG.h"
# include "OCG_extern.h"
#endif
49 50 51 52 53 54 55 56 57 58
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
#   include "sctp_eNB_task.h"
# endif
#endif

#include "LAYER2/MAC/extern.h"

59 60 61 62 63 64 65 66 67 68 69 70 71 72
#define ENB_CONFIG_STRING_ACTIVE_ENBS                   "Active_eNBs"

#define ENB_CONFIG_STRING_ENB_LIST                      "eNBs"
#define ENB_CONFIG_STRING_ENB_ID                        "eNB_ID"
#define ENB_CONFIG_STRING_CELL_TYPE                     "cell_type"
#define ENB_CONFIG_STRING_ENB_NAME                      "eNB_name"

#define ENB_CONFIG_STRING_TRACKING_AREA_CODE            "tracking_area_code"
#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE           "mobile_country_code"
#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE           "mobile_network_code"

#define ENB_CONFIG_STRING_DEFAULT_PAGING_DRX            "default_paging_drx"

#define ENB_CONFIG_STRING_FRAME_TYPE                    "frame_type"
73 74
#define ENB_CONFIG_STRING_TDD_CONFIG                    "tdd_config"
#define ENB_CONFIG_STRING_TDD_CONFIG_S                  "tdd_config_s"
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#define ENB_CONFIG_STRING_PREFIX_TYPE                   "prefix_type"
#define ENB_CONFIG_STRING_EUTRA_BAND                    "eutra_band"
#define ENB_CONFIG_STRING_DOWNLINK_FREQUENCY            "downlink_frequency"
#define ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET       "uplink_frequency_offset"

#define ENB_CONFIG_STRING_MME_IP_ADDRESS                "mme_ip_address"
#define ENB_CONFIG_STRING_MME_IPV4_ADDRESS              "ipv4"
#define ENB_CONFIG_STRING_MME_IPV6_ADDRESS              "ipv6"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE         "active"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE     "preference"

#define ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG     "NETWORK_INTERFACES"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME   "ENB_IPV4_ADDRESS_FOR_S1_MME"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U    "ENB_INTERFACE_NAME_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U         "ENB_IPV4_ADDRESS_FOR_S1U"

gauthier's avatar
gauthier committed
92 93 94 95 96 97 98

#define ENB_CONFIG_STRING_ASN1_VERBOSITY                      "Asn1_verbosity"
#define ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE                 "none"
#define ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING             "annoying"
#define ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO                 "info"


99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#define KHz (1000UL)
#define MHz (1000 * KHz)

typedef struct eutra_band_s
{
    int16_t             band;
    uint32_t            ul_min;
    uint32_t            ul_max;
    uint32_t            dl_min;
    uint32_t            dl_max;
    lte_frame_type_t    frame_type;
} eutra_band_t;

static const eutra_band_t eutra_bands[] =
{
    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},

    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},

    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
};

141
static Enb_properties_array_t enb_properties;
142

143 144 145 146 147 148 149 150
static void enb_config_display(void) {
    int i;

    printf( "\n----------------------------------------------------------------------\n");
    printf( " ENB CONFIG FILE CONTENT LOADED (TBC):\n");
    printf( "----------------------------------------------------------------------\n");
    for (i = 0; i < enb_properties.number; i++) {
        printf( "ENB CONFIG no %u:\n\n", i);
151 152 153 154 155 156 157 158 159 160
        printf( "\teNB name:     \t%s:\n",enb_properties.properties[i]->eNB_name);
        printf( "\teNB ID:       \t%u:\n",enb_properties.properties[i]->eNB_id);
        printf( "\tCell type:    \t%s:\n",enb_properties.properties[i]->cell_type == CELL_MACRO_ENB ? "CELL_MACRO_ENB":"CELL_HOME_ENB");
        printf( "\tTAC:          \t%u:\n",enb_properties.properties[i]->tac);
        printf( "\tMCC:          \t%u:\n",enb_properties.properties[i]->mcc);
        printf( "\tMNC:          \t%u:\n",enb_properties.properties[i]->mnc);
	printf( "\teutra band:   \t%d:\n",enb_properties.properties[i]->eutra_band);
        printf( "\tdownlink freq:\t%u:\n",enb_properties.properties[i]->downlink_frequency);
        printf( "\tuplink freq:  \t%d:\n",enb_properties.properties[i]->uplink_frequency_offset);

161 162 163 164 165
        printf( "\n--------------------------------------------------------\n");
    }
}


166 167 168 169 170 171 172
static int enb_check_band_frequencies(char* lib_config_file_name_pP,
                                      int enb_properties_index,
                                      int16_t band,
                                      uint32_t downlink_frequency,
                                      int32_t uplink_frequency_offset,
                                      lte_frame_type_t frame_type)
{
173
    int errors = 0;
174 175 176 177 178 179 180 181 182 183 184

    if (band > 0)
    {
        int band_index;

        for (band_index = 0; band_index < sizeof (eutra_bands) / sizeof (eutra_bands[0]); band_index++)
        {
            if (band == eutra_bands[band_index].band)
            {
                uint32_t uplink_frequency = downlink_frequency + uplink_frequency_offset;

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
                AssertError (eutra_bands[band_index].dl_min < downlink_frequency, errors ++,
                             "Failed to parse eNB configuration file %s, enb %d downlink frequency %u too low (%u) for band %d!",
                             lib_config_file_name_pP, enb_properties_index, downlink_frequency, eutra_bands[band_index].dl_min, band);
                AssertError (downlink_frequency < eutra_bands[band_index].dl_max, errors ++,
                             "Failed to parse eNB configuration file %s, enb %d downlink frequency %u too high (%u) for band %d!",
                             lib_config_file_name_pP, enb_properties_index, downlink_frequency, eutra_bands[band_index].dl_max, band);

                AssertError (eutra_bands[band_index].ul_min < uplink_frequency, errors ++,
                             "Failed to parse eNB configuration file %s, enb %d uplink frequency %u too low (%u) for band %d!",
                             lib_config_file_name_pP, enb_properties_index, uplink_frequency, eutra_bands[band_index].ul_min, band);
                AssertError (uplink_frequency < eutra_bands[band_index].ul_max, errors ++,
                             "Failed to parse eNB configuration file %s, enb %d uplink frequency %u too high (%u) for band %d!",
                             lib_config_file_name_pP, enb_properties_index, uplink_frequency, eutra_bands[band_index].ul_max, band);

                AssertError (eutra_bands[band_index].frame_type == frame_type, errors ++,
                             "Failed to parse eNB configuration file %s, enb %d invalid frame type (%d/%d) for band %d!",
                             lib_config_file_name_pP, enb_properties_index, eutra_bands[band_index].frame_type, frame_type, band);
202 203 204
            }
        }
    }
205
    return errors;
206 207
}

gauthier's avatar
gauthier committed
208 209 210 211 212
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
extern int asn_debug;
extern int asn1_xer_print;
#endif

213
const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) {
214
  config_t          cfg;
gauthier's avatar
gauthier committed
215 216 217 218 219 220 221
  config_setting_t *setting                       = NULL;
  config_setting_t *subsetting                    = NULL;
  config_setting_t *setting_mme_addresses         = NULL;
  config_setting_t *setting_mme_address           = NULL;
  config_setting_t *setting_enb                   = NULL;
  int               num_enb_properties            = 0;
  int               enb_properties_index          = 0;
222 223 224 225
  int               num_enbs;
  int               num_mme_address;
  int               i;
  int               j;
gauthier's avatar
gauthier committed
226 227 228
  int               parse_errors                  = 0;
  long int          enb_id                        = 0;
  const char*       cell_type                     = NULL;
nikaeinn's avatar
nikaeinn committed
229
  const char*       tac                           = 0;
gauthier's avatar
gauthier committed
230
  const char*       enb_name                      = NULL;
nikaeinn's avatar
nikaeinn committed
231 232
  const char*       mcc                           = 0;
  const char*       mnc                           = 0;
gauthier's avatar
gauthier committed
233
  const char*       default_drx                   = NULL;
234
  const char*       frame_type;
235 236
  long int          tdd_config;
  long int          tdd_config_s;
237
  const char*       prefix_type;
238
  long int          eutra_band;
239
  long long int     downlink_frequency;
240
  long int          uplink_frequency_offset;
gauthier's avatar
gauthier committed
241 242 243 244
  char*             ipv4                          = NULL;
  char*             ipv6                          = NULL;
  char*             active                        = NULL;
  char*             preference                    = NULL;
245
  const char*       active_enb[MAX_ENB];
gauthier's avatar
gauthier committed
246 247 248 249 250 251
  char*             enb_interface_name_for_S1U    = NULL;
  char*             enb_ipv4_address_for_S1U      = NULL;
  char*             enb_interface_name_for_S1_MME = NULL;
  char*             enb_ipv4_address_for_S1_MME   = NULL;
  char             *address                       = NULL;
  char             *cidr                          = NULL;
gauthier's avatar
gauthier committed
252
  char             *astring                       = NULL;
253

254
  memset((char*) (enb_properties.properties), 0 , MAX_ENB * sizeof(Enb_properties_t *));
255
  memset((char*)active_enb,     0 , MAX_ENB * sizeof(char*));
256 257 258

  config_init(&cfg);

winckel's avatar
winckel committed
259 260 261 262 263 264
  if(lib_config_file_name_pP != NULL)
  {
      /* Read the file. If there is an error, report it and exit. */
      if(! config_read_file(&cfg, lib_config_file_name_pP))
      {
          config_destroy(&cfg);
265
          AssertFatal (0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
winckel's avatar
winckel committed
266 267 268
      }
  }
  else
269 270
  {
      config_destroy(&cfg);
winckel's avatar
winckel committed
271
      AssertFatal (0, "No eNB configuration file provided!\n");
272 273
  }

gauthier's avatar
gauthier committed
274 275 276
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
  if(  (config_lookup_string( &cfg, ENB_CONFIG_STRING_ASN1_VERBOSITY, (const char **)&astring) )) {
      if (strcasecmp(astring , ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
277
          asn_debug      = 0;
gauthier's avatar
gauthier committed
278 279 280 281 282 283 284 285 286 287 288 289 290
          asn1_xer_print = 0;
      } else if (strcasecmp(astring , ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
          asn_debug      = 1;
          asn1_xer_print = 1;
      } else if (strcasecmp(astring , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
          asn_debug      = 1;
          asn1_xer_print = 2;
      } else {
          asn_debug      = 0;
          asn1_xer_print = 0;
      }
  }
#endif
291 292 293 294 295 296 297 298 299 300 301 302
  // Get list of active eNBs, (only these will be configured)
  setting = config_lookup(&cfg, ENB_CONFIG_STRING_ACTIVE_ENBS);
  if(setting != NULL)
  {
      num_enbs = config_setting_length(setting);
      for (i = 0; i < num_enbs; i++) {
          setting_enb   = config_setting_get_elem(setting, i);
          active_enb[i] = config_setting_get_string (setting_enb);
          AssertFatal (active_enb[i] != NULL,
                       "Failed to parse config file %s, %uth attribute %s \n",
                       lib_config_file_name_pP, i, ENB_CONFIG_STRING_ACTIVE_ENBS);
          active_enb[i] = strdup(active_enb[i]);
303
          num_enb_properties += 1;
304 305 306 307 308 309 310 311
      }
  }

  /* Output a list of all eNBs. */
  setting = config_lookup(&cfg, ENB_CONFIG_STRING_ENB_LIST);
  if(setting != NULL)
  {
      enb_properties_index = 0;
312
      parse_errors      = 0;
313 314 315
      num_enbs = config_setting_length(setting);
      for (i = 0; i < num_enbs; i++) {
          setting_enb = config_setting_get_elem(setting, i);
316 317

          if(! config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_ENB_ID, &enb_id)) {
318 319
              /* Calculate a default eNB ID */
# if defined(ENABLE_USE_MME)
320 321 322 323
              uint32_t hash;

              hash = s1ap_generate_eNB_id ();
              enb_id = i + (hash & 0xFFFF8);
324 325 326
# else
              enb_id = i;
# endif
327 328 329
          }

          if(  !(       config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE,           &cell_type)
330
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME,            &enb_name)
nikaeinn's avatar
nikaeinn committed
331 332 333
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE,  &tac)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE, &mcc)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_MOBILE_NETWORK_CODE, &mnc)
334
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_DEFAULT_PAGING_DRX,  &default_drx)
335
			
336 337
                )
            ) {
338
              AssertError (0, parse_errors ++,
winckel's avatar
winckel committed
339
                      "Failed to parse eNB configuration file %s, %u th enb\n",
340 341 342
                      lib_config_file_name_pP, i);
          }
          // search if in active list
343
          for (j=0; j < num_enb_properties; j++) {
344
              if (strcmp(active_enb[j], enb_name) == 0) {
345
                  enb_properties.properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t));
346

347
                  enb_properties.properties[enb_properties_index]->eNB_id   = enb_id;
348
                  if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) {
349
                      enb_properties.properties[enb_properties_index]->cell_type = CELL_MACRO_ENB;
350
                  } else  if (strcmp(cell_type, "CELL_HOME_ENB") == 0) {
351
                      enb_properties.properties[enb_properties_index]->cell_type = CELL_HOME_ENB;
352
                  } else {
353
                      AssertError (0, parse_errors ++,
354 355
                              "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
                              lib_config_file_name_pP, i, cell_type);
356
                  }
nikaeinn's avatar
nikaeinn committed
357 358 359 360 361
                  enb_properties.properties[enb_properties_index]->eNB_name         = strdup(enb_name);
                  enb_properties.properties[enb_properties_index]->tac              = (uint16_t)atoi(tac);
                  enb_properties.properties[enb_properties_index]->mcc              = (uint16_t)atoi(mcc);
                  enb_properties.properties[enb_properties_index]->mnc              = (uint16_t)atoi(mnc);
                  enb_properties.properties[enb_properties_index]->mnc_digit_length = strlen(mnc);
362 363

                  if (strcmp(default_drx, "PAGING_DRX_32") == 0) {
364
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_32;
365
                  } else  if (strcmp(default_drx, "PAGING_DRX_64") == 0) {
366
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_64;
367
                  } else  if (strcmp(default_drx, "PAGING_DRX_128") == 0) {
368
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_128;
369
                  } else  if (strcmp(default_drx, "PAGING_DRX_256") == 0) {
370
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_256;
371
                  } else {
372
                      AssertError (0, parse_errors ++,
373 374 375 376 377 378 379
                              "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for default_drx choice: PAGING_DRX_32..PAGING_DRX_256 !\n",
                              lib_config_file_name_pP, i, default_drx);
                  }

                  // Parse optional physical parameters
                  if(config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_FRAME_TYPE, &frame_type)) {
                      if (strcmp(frame_type, "FDD") == 0) {
380
                          enb_properties.properties[enb_properties_index]->frame_type = FDD;
381
                      } else  if (strcmp(frame_type, "TDD") == 0) {
382
                          enb_properties.properties[enb_properties_index]->frame_type = TDD;
383
                      } else {
384
                          AssertError (0, parse_errors ++,
385 386 387 388
                                  "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
                                  lib_config_file_name_pP, i, frame_type);
                      }
                  } else {
389
                      enb_properties.properties[enb_properties_index]->frame_type = FDD; // Default frame type
390 391
                  }

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_TDD_CONFIG, &tdd_config)) {
                      enb_properties.properties[enb_properties_index]->tdd_config = tdd_config;
                      AssertError (tdd_config <= TDD_Config__subframeAssignment_sa6, parse_errors ++,
                              "Failed to parse eNB configuration file %s, enb %d illegal tdd_config %ld (should be 0-%d)!",
                              lib_config_file_name_pP, i, tdd_config, TDD_Config__subframeAssignment_sa6);
                  } else {
                      enb_properties.properties[enb_properties_index]->tdd_config = 3; // Default TDD sub-frame configuration
                  }

                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_TDD_CONFIG_S, &tdd_config_s)) {
                      enb_properties.properties[enb_properties_index]->tdd_config_s = tdd_config_s;
                      AssertError (tdd_config_s <= TDD_Config__specialSubframePatterns_ssp8, parse_errors ++,
                              "Failed to parse eNB configuration file %s, enb %d illegal tdd_config_s %ld (should be 0-%d)!",
                              lib_config_file_name_pP, i, tdd_config_s, TDD_Config__specialSubframePatterns_ssp8);
                  } else {
                      enb_properties.properties[enb_properties_index]->tdd_config_s = 0; // Default TDD S-sub-frame configuration
                  }

410 411
                  if(config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_PREFIX_TYPE, &prefix_type)) {
                      if (strcmp(prefix_type, "NORMAL") == 0) {
412
                          enb_properties.properties[enb_properties_index]->prefix_type = NORMAL;
413
                      } else  if (strcmp(prefix_type, "EXTENDED") == 0) {
414
                          enb_properties.properties[enb_properties_index]->prefix_type = EXTENDED;
415
                      } else {
416
                          AssertError (0, parse_errors ++,
417 418 419 420
                                  "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for prefix_type choice: NORMAL or EXTENDED !\n",
                                  lib_config_file_name_pP, i, prefix_type);
                      }
                  } else {
421
                      enb_properties.properties[enb_properties_index]->prefix_type = NORMAL; // Default prefix type
422 423
                  }

424 425
                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_EUTRA_BAND, &eutra_band)) {
                      enb_properties.properties[enb_properties_index]->eutra_band = eutra_band;
426
                      printf( "\teutra band:\t%d\n",enb_properties.properties[enb_properties_index]->eutra_band);
427 428
                  } else {
                      enb_properties.properties[enb_properties_index]->eutra_band = 7; // Default band
429
                      printf( "\teutra band:\t%d (default)\n",enb_properties.properties[enb_properties_index]->eutra_band);
430 431
                  }

432 433 434
                  if(config_setting_lookup_int64(setting_enb, ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, &downlink_frequency)) {
                      enb_properties.properties[enb_properties_index]->downlink_frequency = (uint32_t) downlink_frequency;
                      printf( "\tdownlink freq:\t%u\n",enb_properties.properties[enb_properties_index]->downlink_frequency);
435
                  } else {
436
                      enb_properties.properties[enb_properties_index]->downlink_frequency = 2680000000UL; // Default downlink frequency
437
                      printf( "\tdownlink freq:\t%u (default)\n",enb_properties.properties[enb_properties_index]->downlink_frequency);
438
                  }
439
                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, &uplink_frequency_offset)) {
440
                      enb_properties.properties[enb_properties_index]->uplink_frequency_offset = (unsigned int) uplink_frequency_offset;
441
                      printf( "\tuplink freq offset:\t%ld\n",enb_properties.properties[enb_properties_index]->uplink_frequency_offset);
442
                  } else {
443 444 445 446 447 448
                      // Default uplink frequency offset
                      if (enb_properties.properties[enb_properties_index]->frame_type == FDD) {
                          enb_properties.properties[enb_properties_index]->uplink_frequency_offset = -120000000;
                      } else {
                          enb_properties.properties[enb_properties_index]->uplink_frequency_offset = 0;
                      }
449
                      printf( "\tuplink freq offset:\t%ld (default)\n",enb_properties.properties[enb_properties_index]->uplink_frequency_offset);
450
                  }
451

452
                  parse_errors += enb_check_band_frequencies(lib_config_file_name_pP,
gauthier's avatar
gauthier committed
453 454 455 456 457
                                             enb_properties_index,
                                             enb_properties.properties[enb_properties_index]->eutra_band,
                                             enb_properties.properties[enb_properties_index]->downlink_frequency,
                                             enb_properties.properties[enb_properties_index]->uplink_frequency_offset,
                                             enb_properties.properties[enb_properties_index]->frame_type);
458

459 460
                  setting_mme_addresses = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_MME_IP_ADDRESS);
                  num_mme_address     = config_setting_length(setting_mme_addresses);
461
                  enb_properties.properties[enb_properties_index]->nb_mme = 0;
462 463 464 465 466 467 468 469 470
                  for (j = 0; j < num_mme_address; j++) {
                      setting_mme_address = config_setting_get_elem(setting_mme_addresses, j);
                      if(  !(
                              config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IPV4_ADDRESS, (const char **)&ipv4)
                              && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IPV6_ADDRESS, (const char **)&ipv6)
                              && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE, (const char **)&active)
                              && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE, (const char **)&preference)
                            )
                        ) {
471
                          AssertError (0, parse_errors ++,
472
                                  "Failed to parse eNB configuration file %s, %u th enb %u th mme address !\n",
473 474
                                  lib_config_file_name_pP, i, j);
                      }
475
                      enb_properties.properties[enb_properties_index]->nb_mme += 1;
476

477 478
                      enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4_address = strdup(ipv4);
                      enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6_address = strdup(ipv6);
479
                      if (strcmp(active, "yes") == 0) {
480
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].active = 1;
winckel's avatar
winckel committed
481 482 483
#if defined(ENABLE_USE_MME)
                          EPC_MODE_ENABLED = 1;
#endif
484 485 486
                      } // else { (calloc)

                      if (strcmp(preference, "ipv4") == 0) {
487
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
488
                      } else if (strcmp(preference, "ipv6") == 0) {
489
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
490
                      } else if (strcmp(preference, "no") == 0) {
491 492
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
493 494
                      }
                  }
gauthier's avatar
gauthier committed
495 496 497
                  subsetting = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
                  if(subsetting != NULL) {
                      if(  (
498
                              config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME,
gauthier's avatar
gauthier committed
499
                                      (const char **)&enb_interface_name_for_S1_MME)
500
                           && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME,
gauthier's avatar
gauthier committed
501
                                   (const char **)&enb_ipv4_address_for_S1_MME)
502
                           && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U,
gauthier's avatar
gauthier committed
503
                                   (const char **)&enb_interface_name_for_S1U)
504
                           && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U,
gauthier's avatar
gauthier committed
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
                                   (const char **)&enb_ipv4_address_for_S1U)
                         )
                     ){
                          enb_properties.properties[enb_properties_index]->enb_interface_name_for_S1U = strdup(enb_interface_name_for_S1U);
                          cidr = enb_ipv4_address_for_S1U;
                          address = strtok(cidr, "/");
                          if (address) {
                              IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_S1U, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" );
                          }

                          enb_properties.properties[enb_properties_index]->enb_interface_name_for_S1_MME = strdup(enb_interface_name_for_S1_MME);
                          cidr = enb_ipv4_address_for_S1_MME;
                          address = strtok(cidr, "/");
                          if (address) {
                              IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR eNB S1_MME !\n" );
                          }
                      }
                  }
523 524 525 526 527 528
                  enb_properties_index += 1;
                  break;
              }
          }
      }
  }
529 530
  enb_properties.number = num_enb_properties;

531
  AssertError (enb_properties_index == num_enb_properties, parse_errors ++,
532
          "Failed to parse eNB configuration file %s, mismatch between %u active eNBs and %u corresponding defined eNBs !\n",
533
          lib_config_file_name_pP, num_enb_properties, enb_properties_index);
534

535
  AssertFatal (parse_errors == 0,
536
               "Failed to parse eNB configuration file %s, found %d error%s !\n",
537
               lib_config_file_name_pP, parse_errors, parse_errors > 1 ? "s" : "");
538
  enb_config_display();
539
  return &enb_properties;
gauthier's avatar
gauthier committed
540

541 542 543 544
}

const Enb_properties_array_t *enb_config_get(void) {
    return &enb_properties;
545
}
546