enb_config.c 13.4 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

          if(! config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_ENB_ID, &enb_id)) {
131 132
              /* Calculate a default eNB ID */
# if defined(ENABLE_USE_MME)
133 134 135 136
              uint32_t hash;

              hash = s1ap_generate_eNB_id ();
              enb_id = i + (hash & 0xFFFF8);
137 138 139
# else
              enb_id = i;
# endif
140 141 142
          }

          if(  !(       config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE,           &cell_type)
143 144 145 146 147 148 149
                     && 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)
                )
            ) {
150
              AssertError (0, parse_error ++,
winckel's avatar
winckel committed
151
                      "Failed to parse eNB configuration file %s, %u th enb\n",
152 153 154
                      lib_config_file_name_pP, i);
          }
          // search if in active list
155
          for (j=0; j < num_enb_properties; j++) {
156
              if (strcmp(active_enb[j], enb_name) == 0) {
157
                  enb_properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t));
158

159
                  enb_properties[enb_properties_index]->eNB_id   = enb_id;
160
                  if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) {
161
                      enb_properties[enb_properties_index]->cell_type = CELL_MACRO_ENB;
162
                  } else  if (strcmp(cell_type, "CELL_HOME_ENB") == 0) {
163
                      enb_properties[enb_properties_index]->cell_type = CELL_HOME_ENB;
164
                  } else {
165 166 167
                      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);
168
                  }
169 170 171 172
                  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;
173 174

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

                  if(config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_PREFIX_TYPE, &prefix_type)) {
                      if (strcmp(prefix_type, "NORMAL") == 0) {
205
                          enb_properties[enb_properties_index]->prefix_type = NORMAL;
206
                      } else  if (strcmp(prefix_type, "EXTENDED") == 0) {
207
                          enb_properties[enb_properties_index]->prefix_type = EXTENDED;
208 209 210 211 212 213
                      } 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 {
214
                      enb_properties[enb_properties_index]->prefix_type = NORMAL; // Default prefix type
215 216
                  }

217
                  if(config_setting_lookup_int64(setting_enb, ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, &downlink_frequency)) {
218
                      enb_properties[enb_properties_index]->downlink_frequency = downlink_frequency;
219
                  } else {
220
                      enb_properties[enb_properties_index]->downlink_frequency = 2680000000UL; // Default downlink frequency
221 222 223
                  }

                  if(config_setting_lookup_int(setting_enb, ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, &uplink_frequency_offset)) {
224
                      enb_properties[enb_properties_index]->uplink_frequency_offset = uplink_frequency_offset;
225
                  } else {
226
                      enb_properties[enb_properties_index]->uplink_frequency_offset = -120000000; // Default uplink frequency offset
227 228 229 230
                  }

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

247 248
                      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);
249
                      if (strcmp(active, "yes") == 0) {
250
                          enb_properties[enb_properties_index]->mme_ip_address[j].active = 1;
winckel's avatar
winckel committed
251 252 253
#if defined(ENABLE_USE_MME)
                          EPC_MODE_ENABLED = 1;
#endif
254 255 256
                      } // else { (calloc)

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

  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" : "");
278
  return num_enb_properties;
279
}