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"

winckel's avatar
winckel committed
51
static Enb_properties_array_t enb_properties;
52

winckel's avatar
winckel committed
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

winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
158
                  enb_properties.properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t));
159

winckel's avatar
winckel committed
160
                  enb_properties.properties[enb_properties_index]->eNB_id   = enb_id;
161
                  if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) {
winckel's avatar
winckel committed
162
                      enb_properties.properties[enb_properties_index]->cell_type = CELL_MACRO_ENB;
163
                  } else  if (strcmp(cell_type, "CELL_HOME_ENB") == 0) {
winckel's avatar
winckel committed
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
                  }
winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
176
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_32;
177
                  } else  if (strcmp(default_drx, "PAGING_DRX_64") == 0) {
winckel's avatar
winckel committed
178
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_64;
179
                  } else  if (strcmp(default_drx, "PAGING_DRX_128") == 0) {
winckel's avatar
winckel committed
180
                      enb_properties.properties[enb_properties_index]->default_drx = PAGING_DRX_128;
181
                  } else  if (strcmp(default_drx, "PAGING_DRX_256") == 0) {
winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
192
                          enb_properties.properties[enb_properties_index]->frame_type = FDD;
193
                      } else  if (strcmp(frame_type, "TDD") == 0) {
winckel's avatar
winckel committed
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 {
winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
206
                          enb_properties.properties[enb_properties_index]->prefix_type = NORMAL;
207
                      } else  if (strcmp(prefix_type, "EXTENDED") == 0) {
winckel's avatar
winckel committed
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 {
winckel's avatar
winckel committed
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)) {
winckel's avatar
winckel committed
219
                      enb_properties.properties[enb_properties_index]->downlink_frequency = downlink_frequency;
220
                  } else {
winckel's avatar
winckel committed
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)) {
winckel's avatar
winckel committed
225
                      enb_properties.properties[enb_properties_index]->uplink_frequency_offset = uplink_frequency_offset;
226
                  } else {
winckel's avatar
winckel committed
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);
winckel's avatar
winckel committed
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);
                      }
winckel's avatar
winckel committed
246
                      enb_properties.properties[enb_properties_index]->nb_mme += 1;
247

winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
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) {
winckel's avatar
winckel committed
258
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1;
259
                      } else if (strcmp(preference, "ipv6") == 0) {
winckel's avatar
winckel committed
260
                          enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1;
261
                      } else if (strcmp(preference, "no") == 0) {
winckel's avatar
winckel committed
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;
              }
          }
      }
  }
winckel's avatar
winckel committed
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" : "");
winckel's avatar
winckel committed
281 282 283 284 285 286

  return &enb_properties;
}

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