enb_config.c 13.3 KB
Newer Older
1 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 28 29 30 31 32 33 34 35 36
/*******************************************************************************

 Eurecom OpenAirInterface
 Copyright(c) 1999 - 2014 Eurecom

 This program is free software; you can redistribute it and/or modify it
 under the terms and conditions of the GNU General Public License,
 version 2, as published by the Free Software Foundation.

 This program is distributed in the hope 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
 this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

 The full GNU General Public License is included in this distribution in
 the file called "COPYING".

 Contact Information
 Openair Admin: openair_admin@eurecom.fr
 Openair Tech : openair_tech@eurecom.fr
 Forums       : http://forums.eurecom.fr/openairinterface
 Address      : EURECOM, Campus SophiaTech, 450 Route des Chappes
 06410 Biot FRANCE

 *******************************************************************************/

#include <string.h>
#include <libconfig.h>

#include "log.h"
#include "assertions.h"
#include "enb_config.h"
winckel's avatar
winckel committed
37 38 39 40
#if defined(OAI_EMU)
# include "OCG.h"
# include "OCG_extern.h"
#endif
41 42 43 44 45 46 47 48 49 50
#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"

51
int enb_config_init(char* lib_config_file_name_pP, Enb_properties_t **enb_properties) {
52 53 54 55 56 57

  config_t          cfg;
  config_setting_t *setting;
  config_setting_t *setting_mme_addresses;
  config_setting_t *setting_mme_address;
  config_setting_t *setting_enb;
58 59 60 61 62 63 64
  int               num_enb_properties = 0;
  int               enb_properties_index = 0;
  int               num_enbs;
  int               num_mme_address;
  int               i;
  int               j;
  int               parse_error = 0;
65 66 67 68 69 70 71
  long int          enb_id;
  const char*       cell_type;
  long int          tac;
  const char*       enb_name;
  long int          mcc;
  long int          mnc;
  const char*       default_drx;
72 73
  const char*       frame_type;
  const char*       prefix_type;
74
  long long int     downlink_frequency;
75
  long int          uplink_frequency_offset;
76 77 78 79
  char*             ipv4;
  char*             ipv6;
  char*             active;
  char*             preference;
80
  const char*       active_enb[MAX_ENB];
81

82 83
  memset((char*)enb_properties, 0 , MAX_ENB * sizeof(Enb_properties_t*));
  memset((char*)active_enb,     0 , MAX_ENB * sizeof(char*));
84 85 86

  config_init(&cfg);

winckel's avatar
winckel committed
87 88 89 90 91 92 93
  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))
      {
          LOG_E(ENB_APP, "%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg));
          config_destroy(&cfg);
94
          AssertFatal (0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
winckel's avatar
winckel committed
95 96 97
      }
  }
  else
98
  {
winckel's avatar
winckel committed
99
      LOG_E(ENB_APP, "No eNB configuration file provided!\n");
100
      config_destroy(&cfg);
winckel's avatar
winckel committed
101
      AssertFatal (0, "No eNB configuration file provided!\n");
102 103 104 105 106 107 108 109 110 111 112 113 114 115
  }

  // 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]);
116
          num_enb_properties += 1;
117 118 119 120 121 122 123 124 125 126 127 128
      }
  }

  /* Output a list of all eNBs. */
  setting = config_lookup(&cfg, ENB_CONFIG_STRING_ENB_LIST);
  if(setting != NULL)
  {
      enb_properties_index = 0;
      parse_error      = 0;
      num_enbs = config_setting_length(setting);
      for (i = 0; i < num_enbs; i++) {
          setting_enb = config_setting_get_elem(setting, i);
129 130 131 132 133 134 135 136 137 138

          if(! config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_ENB_ID, &enb_id)) {
              uint32_t hash;

              /* Calculate a default eNB ID */
              hash = s1ap_generate_eNB_id ();
              enb_id = i + (hash & 0xFFFF8);
          }

          if(  !(       config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE,           &cell_type)
139 140 141 142 143 144 145
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME,            &enb_name)
                     && config_setting_lookup_int   (setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE,  &tac)
                     && config_setting_lookup_int   (setting_enb, ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE, &mcc)
                     && config_setting_lookup_int   (setting_enb, ENB_CONFIG_STRING_MOBILE_NETWORK_CODE, &mnc)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_DEFAULT_PAGING_DRX,  &default_drx)
                )
            ) {
146
              AssertError (0, parse_error ++,
winckel's avatar
winckel committed
147
                      "Failed to parse eNB configuration file %s, %u th enb\n",
148 149 150
                      lib_config_file_name_pP, i);
          }
          // search if in active list
151
          for (j=0; j < num_enb_properties; j++) {
152
              if (strcmp(active_enb[j], enb_name) == 0) {
153
                  enb_properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t));
154

155
                  enb_properties[enb_properties_index]->eNB_id   = enb_id;
156
                  if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) {
157
                      enb_properties[enb_properties_index]->cell_type = CELL_MACRO_ENB;
158
                  } else  if (strcmp(cell_type, "CELL_HOME_ENB") == 0) {
159
                      enb_properties[enb_properties_index]->cell_type = CELL_HOME_ENB;
160
                  } else {
161 162 163
                      AssertError (0, parse_error ++,
                              "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);
164
                  }
165 166 167 168
                  enb_properties[enb_properties_index]->eNB_name = strdup(enb_name);
                  enb_properties[enb_properties_index]->tac      = (uint16_t)tac;
                  enb_properties[enb_properties_index]->mcc      = (uint16_t)mcc;
                  enb_properties[enb_properties_index]->mnc      = (uint16_t)mnc;
169 170

                  if (strcmp(default_drx, "PAGING_DRX_32") == 0) {
171
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_32;
172
                  } else  if (strcmp(default_drx, "PAGING_DRX_64") == 0) {
173
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_64;
174
                  } else  if (strcmp(default_drx, "PAGING_DRX_128") == 0) {
175
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_128;
176
                  } else  if (strcmp(default_drx, "PAGING_DRX_256") == 0) {
177
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_256;
178
                  } else {
179 180 181 182 183 184 185 186
                      AssertError (0, parse_error ++,
                              "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) {
187
                          enb_properties[enb_properties_index]->frame_type = FDD;
188
                      } else  if (strcmp(frame_type, "TDD") == 0) {
189
                          enb_properties[enb_properties_index]->frame_type = TDD;
190 191 192 193 194 195
                      } else {
                          AssertError (0, parse_error ++,
                                  "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 {
196
                      enb_properties[enb_properties_index]->frame_type = FDD; // Default frame type
197 198 199 200
                  }

                  if(config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_PREFIX_TYPE, &prefix_type)) {
                      if (strcmp(prefix_type, "NORMAL") == 0) {
201
                          enb_properties[enb_properties_index]->prefix_type = NORMAL;
202
                      } else  if (strcmp(prefix_type, "EXTENDED") == 0) {
203
                          enb_properties[enb_properties_index]->prefix_type = EXTENDED;
204 205 206 207 208 209
                      } else {
                          AssertError (0, parse_error ++,
                                  "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 {
210
                      enb_properties[enb_properties_index]->prefix_type = NORMAL; // Default prefix type
211 212
                  }

213
                  if(config_setting_lookup_int64(setting_enb, ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, &downlink_frequency)) {
214
                      enb_properties[enb_properties_index]->downlink_frequency = downlink_frequency;
215
                  } else {
216
                      enb_properties[enb_properties_index]->downlink_frequency = 2680000000UL; // Default downlink frequency
217 218 219
                  }

                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, &uplink_frequency_offset)) {
220
                      enb_properties[enb_properties_index]->uplink_frequency_offset = uplink_frequency_offset;
221
                  } else {
222
                      enb_properties[enb_properties_index]->uplink_frequency_offset = -120000000; // Default uplink frequency offset
223 224 225 226
                  }

                  setting_mme_addresses = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_MME_IP_ADDRESS);
                  num_mme_address     = config_setting_length(setting_mme_addresses);
227
                  enb_properties[enb_properties_index]->nb_mme = 0;
228 229 230 231 232 233 234 235 236
                  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)
                            )
                        ) {
237 238
                          AssertError (0, parse_error ++,
                                  "Failed to parse eNB configuration file %s, %u th enb %u th mme address !\n",
239 240
                                  lib_config_file_name_pP, i, j);
                      }
241
                      enb_properties[enb_properties_index]->nb_mme += 1;
242

243 244
                      enb_properties[enb_properties_index]->mme_ip_address[j].ipv4_address = strdup(ipv4);
                      enb_properties[enb_properties_index]->mme_ip_address[j].ipv6_address = strdup(ipv6);
245
                      if (strcmp(active, "yes") == 0) {
246
                          enb_properties[enb_properties_index]->mme_ip_address[j].active = 1;
winckel's avatar
winckel committed
247 248 249
#if defined(ENABLE_USE_MME)
                          EPC_MODE_ENABLED = 1;
#endif
250 251 252
                      } // else { (calloc)

                      if (strcmp(preference, "ipv4") == 0) {
253
                          enb_properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
254
                      } else if (strcmp(preference, "ipv6") == 0) {
255
                          enb_properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
256
                      } else if (strcmp(preference, "no") == 0) {
257 258
                          enb_properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
                          enb_properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
259 260 261 262 263 264 265 266
                      }
                  }
                  enb_properties_index += 1;
                  break;
              }
          }
      }
  }
267
  AssertError (enb_properties_index == num_enb_properties, parse_error ++,
268
          "Failed to parse eNB configuration file %s, mismatch between %u active eNBs and %u corresponding defined eNBs !\n",
269
          lib_config_file_name_pP, num_enb_properties, enb_properties_index);
270 271 272 273

  AssertFatal (parse_error == 0,
               "Failed to parse eNB configuration file %s, found %d error%s !\n",
               lib_config_file_name_pP, parse_error, parse_error > 1 ? "s" : "");
274
  return num_enb_properties;
275
}