enb_config.c 13.9 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
static Enb_properties_array_t enb_properties;
52

53
const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) {
54 55 56 57 58
  config_t          cfg;
  config_setting_t *setting;
  config_setting_t *setting_mme_addresses;
  config_setting_t *setting_mme_address;
  config_setting_t *setting_enb;
59 60 61 62 63 64 65
  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;
66 67 68 69 70 71 72
  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;
73 74
  const char*       frame_type;
  const char*       prefix_type;
75
  long long int     downlink_frequency;
76
  long int          uplink_frequency_offset;
77 78 79 80
  char*             ipv4;
  char*             ipv6;
  char*             active;
  char*             preference;
81
  const char*       active_enb[MAX_ENB];
82

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

  config_init(&cfg);

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

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

  /* 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);
130 131

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

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

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

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

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

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

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

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

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

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

                      if (strcmp(preference, "ipv4") == 0) {
258
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
259
                      } else if (strcmp(preference, "ipv6") == 0) {
260
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
261
                      } else if (strcmp(preference, "no") == 0) {
262 263
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
264 265 266 267 268 269 270 271
                      }
                  }
                  enb_properties_index += 1;
                  break;
              }
          }
      }
  }
272 273
  enb_properties.number = num_enb_properties;

274
  AssertError (enb_properties_index == num_enb_properties, parse_error ++,
275
          "Failed to parse eNB configuration file %s, mismatch between %u active eNBs and %u corresponding defined eNBs !\n",
276
          lib_config_file_name_pP, num_enb_properties, enb_properties_index);
277 278 279 280

  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" : "");
281 282 283 284 285 286

  return &enb_properties;
}

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