enb_config.c 13.2 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 129 130 131 132 133 134 135 136 137 138
      }
  }

  /* 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);
          if(  !(
                        config_setting_lookup_int   (setting_enb, ENB_CONFIG_STRING_ENB_ID,              &enb_id)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE,           &cell_type)
                     && 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)
                )
            ) {
139
              AssertError (0, parse_error ++,
winckel's avatar
winckel committed
140
                      "Failed to parse eNB configuration file %s, %u th enb\n",
141 142 143
                      lib_config_file_name_pP, i);
          }
          // search if in active list
144
          for (j=0; j < num_enb_properties; j++) {
145
              if (strcmp(active_enb[j], enb_name) == 0) {
146
                  enb_properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t));
147

148
                  enb_properties[enb_properties_index]->eNB_id   = enb_id;
149
                  if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) {
150
                      enb_properties[enb_properties_index]->cell_type = CELL_MACRO_ENB;
151
                  } else  if (strcmp(cell_type, "CELL_HOME_ENB") == 0) {
152
                      enb_properties[enb_properties_index]->cell_type = CELL_HOME_ENB;
153
                  } else {
154 155 156
                      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);
157
                  }
158 159 160 161
                  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;
162 163

                  if (strcmp(default_drx, "PAGING_DRX_32") == 0) {
164
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_32;
165
                  } else  if (strcmp(default_drx, "PAGING_DRX_64") == 0) {
166
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_64;
167
                  } else  if (strcmp(default_drx, "PAGING_DRX_128") == 0) {
168
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_128;
169
                  } else  if (strcmp(default_drx, "PAGING_DRX_256") == 0) {
170
                      enb_properties[enb_properties_index]->default_drx = PAGING_DRX_256;
171
                  } else {
172 173 174 175 176 177 178 179
                      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) {
180
                          enb_properties[enb_properties_index]->frame_type = FDD;
181
                      } else  if (strcmp(frame_type, "TDD") == 0) {
182
                          enb_properties[enb_properties_index]->frame_type = TDD;
183 184 185 186 187 188
                      } 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 {
189
                      enb_properties[enb_properties_index]->frame_type = FDD; // Default frame type
190 191 192 193
                  }

                  if(config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_PREFIX_TYPE, &prefix_type)) {
                      if (strcmp(prefix_type, "NORMAL") == 0) {
194
                          enb_properties[enb_properties_index]->prefix_type = NORMAL;
195
                      } else  if (strcmp(prefix_type, "EXTENDED") == 0) {
196
                          enb_properties[enb_properties_index]->prefix_type = EXTENDED;
197 198 199 200 201 202
                      } 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 {
203
                      enb_properties[enb_properties_index]->prefix_type = NORMAL; // Default prefix type
204 205
                  }

206
                  if(config_setting_lookup_int64(setting_enb, ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, &downlink_frequency)) {
207
                      enb_properties[enb_properties_index]->downlink_frequency = downlink_frequency;
208
                  } else {
209
                      enb_properties[enb_properties_index]->downlink_frequency = 2680000000UL; // Default downlink frequency
210 211 212
                  }

                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, &uplink_frequency_offset)) {
213
                      enb_properties[enb_properties_index]->uplink_frequency_offset = uplink_frequency_offset;
214
                  } else {
215
                      enb_properties[enb_properties_index]->uplink_frequency_offset = -120000000; // Default uplink frequency offset
216 217 218 219
                  }

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

236 237
                      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);
238
                      if (strcmp(active, "yes") == 0) {
239
                          enb_properties[enb_properties_index]->mme_ip_address[j].active = 1;
winckel's avatar
winckel committed
240 241 242
#if defined(ENABLE_USE_MME)
                          EPC_MODE_ENABLED = 1;
#endif
243 244 245
                      } // else { (calloc)

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

  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" : "");
267
  return num_enb_properties;
268
}