rrc_eNB_S1AP.c 45 KB
Newer Older
winckel's avatar
winckel committed
1
/*******************************************************************************
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


11 12 13 14
    OpenAirInterface is distributed in the hope that 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.
15

16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20

21 22 23
  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
winckel's avatar
winckel committed
27

28
*******************************************************************************/
winckel's avatar
winckel committed
29 30
/*! \file rrc_eNB_S1AP.c
 * \brief rrc S1AP procedures for eNB
31
 * \author Laurent Winckel and Sebastien ROUX and Navid Nikaein and Lionel GAUTHIER
32
 * \date 2013-2014
winckel's avatar
winckel committed
33 34
 * \version 1.0
 * \company Eurecom
35
 * \email: navid.nikaein@eurecom.fr
winckel's avatar
winckel committed
36 37 38 39 40 41 42
 */

#if defined(ENABLE_USE_MME)
# include "defs.h"
# include "extern.h"
# include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
# include "RRC/LITE/MESSAGES/asn1_msg.h"
43 44
# include "RRC/LITE/defs.h"
# include "rrc_eNB_UE_context.h"
winckel's avatar
winckel committed
45
# include "rrc_eNB_S1AP.h"
gauthier's avatar
gauthier committed
46
# include "enb_config.h"
winckel's avatar
winckel committed
47 48 49 50 51

# if defined(ENABLE_ITTI)
#   include "asn1_conversions.h"
#   include "intertask_interface.h"
#   include "pdcp.h"
52
#   include "pdcp_primitives.h"
winckel's avatar
winckel committed
53 54 55 56 57
#   include "s1ap_eNB.h"
# else
#   include "../../S1AP/s1ap_eNB.h"
# endif

58 59 60
#if defined(ENABLE_SECURITY)
#   include "UTIL/OSA/osa_defs.h"
#endif
61
#include "msc.h"
62

winckel's avatar
winckel committed
63 64 65
/* Value to indicate an invalid UE initial id */
static const uint16_t UE_INITIAL_ID_INVALID = 0;

66
/* Masks for S1AP Encryption algorithms, EEA0 is always supported (not coded) */
67 68
static const uint16_t S1AP_ENCRYPTION_EEA1_MASK = 0x8000;
static const uint16_t S1AP_ENCRYPTION_EEA2_MASK = 0x4000;
69 70

/* Masks for S1AP Integrity algorithms, EIA0 is always supported (not coded) */
71 72
static const uint16_t S1AP_INTEGRITY_EIA1_MASK = 0x8000;
static const uint16_t S1AP_INTEGRITY_EIA2_MASK = 0x4000;
73 74 75 76

#ifdef Rel10
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920
#else
77
#ifdef EXMIMO_IOT
78
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia2
79
#else
80 81
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_reserved
#endif
82
#endif
83

winckel's avatar
winckel committed
84 85


86

87
# if defined(ENABLE_ITTI)
88 89 90 91 92 93 94 95 96
//------------------------------------------------------------------------------
struct rrc_ue_s1ap_ids_s*
rrc_eNB_S1AP_get_ue_ids(
  eNB_RRC_INST* const rrc_instance_pP,
  const uint16_t ue_initial_id,
  const uint32_t eNB_ue_s1ap_id
)
//------------------------------------------------------------------------------
{
97 98
  rrc_ue_s1ap_ids_t *result = NULL;
  rrc_ue_s1ap_ids_t *result2 = NULL;
99 100 101 102 103 104 105 106 107
  hashtable_rc_t     h_rc;

  // we assume that a rrc_ue_s1ap_ids_s is initially inserted in initial_id2_s1ap_ids
  if (eNB_ue_s1ap_id > 0) {
	h_rc = hashtable_get(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&result);
  }
  if (ue_initial_id != UE_INITIAL_ID_INVALID) {
    h_rc = hashtable_get(rrc_instance_pP->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&result);
	if  (h_rc == HASH_TABLE_OK) {
108
	  if (eNB_ue_s1ap_id > 0) {
109 110 111 112 113 114 115 116 117 118
	    h_rc = hashtable_get(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&result2);
	    if  (h_rc != HASH_TABLE_OK) {
		  result2 = malloc(sizeof(*result2));
		  if (NULL != result2) {
		    *result2 = *result;
		    result2->eNB_ue_s1ap_id = eNB_ue_s1ap_id;
		    result->eNB_ue_s1ap_id  = eNB_ue_s1ap_id;
            h_rc = hashtable_insert(rrc_instance_pP->s1ap_id2_s1ap_ids,
		    		               (hash_key_t)eNB_ue_s1ap_id,
		    		               result2);
119 120
            if (h_rc != HASH_TABLE_OK) {
              LOG_E(S1AP, "[eNB %u] Error while hashtable_insert in s1ap_id2_s1ap_ids eNB_ue_s1ap_id %u\n",
121
		    		  rrc_instance_pP - eNB_rrc_inst, eNB_ue_s1ap_id);
122
            }
123 124 125 126 127
		  }
		}
	  }
	}
  }
128
  return result;
129
}
130 131 132 133 134 135 136 137
//------------------------------------------------------------------------------
void
rrc_eNB_S1AP_remove_ue_ids(
  eNB_RRC_INST*              const rrc_instance_pP,
  struct rrc_ue_s1ap_ids_s* const ue_ids_pP
)
//------------------------------------------------------------------------------
{
138 139 140
  const uint16_t ue_initial_id  = ue_ids_pP->ue_initial_id;
  const uint32_t eNB_ue_s1ap_id = ue_ids_pP->eNB_ue_s1ap_id;
  hashtable_rc_t h_rc;
141 142 143
  if (rrc_instance_pP == NULL) {
    LOG_E(RRC, "Bad RRC instance\n");
    return;
144 145
  }

146 147 148
  if (ue_ids_pP == NULL) {
    LOG_E(RRC, "Trying to free a NULL S1AP UE IDs\n");
    return;
winckel's avatar
winckel committed
149
  }
150

151 152 153 154
  if (eNB_ue_s1ap_id > 0) {
	h_rc = hashtable_remove(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id);
	if (h_rc != HASH_TABLE_OK) {
	  LOG_W(RRC, "S1AP Did not find entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
155 156
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
157 158 159 160 161 162 163
	}
  }

  if (ue_initial_id != UE_INITIAL_ID_INVALID) {
    h_rc = hashtable_remove(rrc_instance_pP->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id);
	if (h_rc != HASH_TABLE_OK) {
	  LOG_W(RRC, "S1AP Did not find entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
164 165
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
166 167
	}
  }
winckel's avatar
winckel committed
168 169
}

170 171
/*! \fn uint16_t get_next_ue_initial_id(uint8_t mod_id)
 *\brief provide an UE initial ID for S1AP initial communication.
winckel's avatar
winckel committed
172
 *\param mod_id Instance ID of eNB.
173
 *\return the UE initial ID.
winckel's avatar
winckel committed
174
 */
175 176 177 178 179 180
//------------------------------------------------------------------------------
static uint16_t
get_next_ue_initial_id(
  const module_id_t mod_id
)
//------------------------------------------------------------------------------
181
{
182 183
  static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
  ue_initial_id[mod_id]++;
winckel's avatar
winckel committed
184

185 186 187 188
  /* Never use UE_INITIAL_ID_INVALID this is the invalid id! */
  if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) {
    ue_initial_id[mod_id]++;
  }
winckel's avatar
winckel committed
189

190
  return ue_initial_id[mod_id];
191
}
192

193 194


winckel's avatar
winckel committed
195

winckel's avatar
winckel committed
196
/*! \fn uint8_t get_UE_index_from_s1ap_ids(uint8_t mod_id, uint16_t ue_initial_id, uint32_t eNB_ue_s1ap_id)
winckel's avatar
winckel committed
197 198 199 200 201 202 203
 *\brief retrieve UE index in the eNB from the UE initial ID if not equal to UE_INDEX_INVALID or
 *\brief from the eNB_ue_s1ap_id previously transmitted by S1AP.
 *\param mod_id Instance ID of eNB.
 *\param ue_initial_id The UE initial ID sent to S1AP.
 *\param eNB_ue_s1ap_id The value sent by S1AP.
 *\return the UE index or UE_INDEX_INVALID if not found.
 */
204 205 206 207 208 209
static struct rrc_eNB_ue_context_s*
rrc_eNB_get_ue_context_from_s1ap_ids(
  const instance_t  instanceP,
  const uint16_t    ue_initial_idP,
  const uint32_t    eNB_ue_s1ap_idP
)
210
{
211 212 213 214 215 216 217 218
  rrc_ue_s1ap_ids_t* temp = NULL;
  temp =
    rrc_eNB_S1AP_get_ue_ids(
      &eNB_rrc_inst[ENB_INSTANCE_TO_MODULE_ID(instanceP)],
      ue_initial_idP,
      eNB_ue_s1ap_idP);

  if (temp) {
winckel's avatar
winckel committed
219

220 221 222
    return rrc_eNB_get_ue_context(
             &eNB_rrc_inst[ENB_INSTANCE_TO_MODULE_ID(instanceP)],
             temp->ue_rnti);
winckel's avatar
winckel committed
223 224
  }

225
  return NULL;
winckel's avatar
winckel committed
226 227
}

228 229 230 231 232
/*! \fn e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(uint16_t algorithms)
 *\brief analyze available encryption algorithms bit mask and return the relevant one.
 *\param algorithms The bit mask of available algorithms received from S1AP.
 *\return the selected algorithm.
 */
233 234 235
static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(uint16_t algorithms)
{

236 237
#warning "Forced   return SecurityAlgorithmConfig__cipheringAlgorithm_eea0, to be deleted in future"
  return SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
238

239
  if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) {
240
    return SecurityAlgorithmConfig__cipheringAlgorithm_eea2;
241 242 243
  }

  if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) {
244
    return SecurityAlgorithmConfig__cipheringAlgorithm_eea1;
245 246 247 248 249 250 251 252 253 254
  }

  return SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
}

/*! \fn e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
 *\brief analyze available integrity algorithms bit mask and return the relevant one.
 *\param algorithms The bit mask of available algorithms received from S1AP.
 *\return the selected algorithm.
 */
255 256 257
static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
{

258
  if (algorithms & S1AP_INTEGRITY_EIA2_MASK) {
259
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
260 261 262
  }

  if (algorithms & S1AP_INTEGRITY_EIA1_MASK) {
263
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1;
264 265 266 267 268 269 270 271 272 273 274 275
  }

  return INTEGRITY_ALGORITHM_NONE;
}

/*! \fn int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_capabilities_t *security_capabilities)
 *\brief save and analyze available security algorithms bit mask and select relevant ones.
 *\param mod_id Instance ID of eNB.
 *\param ue_index Instance ID of UE in the eNB.
 *\param security_capabilities The security capabilities received from S1AP.
 *\return TRUE if at least one algorithm has been changed else FALSE.
 */
276 277 278 279 280 281
static int
rrc_eNB_process_security(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  security_capabilities_t* security_capabilities_pP
)
282
{
283
  boolean_t                                         changed = FALSE;
284 285 286 287
  e_SecurityAlgorithmConfig__cipheringAlgorithm cipheringAlgorithm;
  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm;

  /* Save security parameters */
288
  ue_context_pP->ue_context.security_capabilities = *security_capabilities_pP;
289

290 291
  // translation
  LOG_D(RRC,
292
        "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %u NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n",
293 294 295 296 297
        ctxt_pP->module_id,
        ue_context_pP->ue_context.security_capabilities.encryption_algorithms,
        ue_context_pP->ue_context.ciphering_algorithm,
        ue_context_pP->ue_context.security_capabilities.integrity_algorithms,
        ue_context_pP->ue_context.integrity_algorithm);
298
  /* Select relevant algorithms */
299
  cipheringAlgorithm = rrc_eNB_select_ciphering (ue_context_pP->ue_context.security_capabilities.encryption_algorithms);
300

301 302
  if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) {
    ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm;
303
    changed = TRUE;
304 305
  }

306
  integrityProtAlgorithm = rrc_eNB_select_integrity (ue_context_pP->ue_context.security_capabilities.integrity_algorithms);
307

308 309
  if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) {
    ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm;
310
    changed = TRUE;
311 312
  }

313 314 315 316 317 318 319
  LOG_I (RRC, "[eNB %d][UE %x] Selected security algorithms (%x): %x, %x, %s\n",
         ctxt_pP->module_id,
         ue_context_pP->ue_context.rnti,
         security_capabilities_pP,
         cipheringAlgorithm,
         integrityProtAlgorithm,
         changed ? "changed" : "same");
320 321 322 323

  return changed;
}

324
/*! \fn void process_eNB_security_key (const protocol_ctxt_t* const ctxt_pP, eNB_RRC_UE_t * const ue_context_pP, uint8_t *security_key)
325
 *\brief save security key.
326 327 328
 *\param ctxt_pP         Running context.
 *\param ue_context_pP   UE context.
 *\param security_key_pP The security key received from S1AP.
329
 */
330 331 332 333 334 335 336
//------------------------------------------------------------------------------
static void process_eNB_security_key (
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  uint8_t*               security_key_pP
)
//------------------------------------------------------------------------------
337
{
338 339 340 341 342
#if defined(ENABLE_SECURITY)
  char ascii_buffer[65];
  uint8_t i;

  /* Saves the security key */
343
  memcpy (ue_context_pP->ue_context.kenb, security_key_pP, SECURITY_KEY_LENGTH);
344 345

  for (i = 0; i < 32; i++) {
346
    sprintf(&ascii_buffer[2 * i], "%02X", ue_context_pP->ue_context.kenb[i]);
347
  }
348

349 350
  ascii_buffer[2 * i] = '\0';

351
  LOG_I (RRC, "[eNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ascii_buffer);
352 353 354
#endif
}

355

356 357 358 359 360 361 362 363
//------------------------------------------------------------------------------
static void
rrc_pdcp_config_security(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  const uint8_t send_security_mode_command
)
//------------------------------------------------------------------------------
364
{
365 366 367

#if defined(ENABLE_SECURITY)

368

369
  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;
370 371 372 373
  uint8_t                            *kRRCenc = NULL;
  uint8_t                            *kRRCint = NULL;
  uint8_t                            *kUPenc = NULL;
  pdcp_t                             *pdcp_p   = NULL;
374
  static int                          print_keys= 1;
375 376
  hashtable_rc_t                      h_rc;
  hash_key_t                          key;
377

378 379
  /* Derive the keys from kenb */
  if (SRB_configList != NULL) {
380 381 382
    derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
                      ue_context_pP->ue_context.kenb,
                      &kUPenc);
383
  }
384

385 386 387 388 389 390
  derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
                     ue_context_pP->ue_context.kenb,
                     &kRRCenc);
  derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
                     ue_context_pP->ue_context.kenb,
                     &kRRCint);
391 392 393

#define DEBUG_SECURITY 1

394 395
#if defined (DEBUG_SECURITY)
#define msg printf
396

397
  if (print_keys ==1 ) {
398 399 400 401
    print_keys =0;
    int i;
    msg("\nKeNB:");

402 403 404
    for(i = 0; i < 32; i++) {
      msg("%02x", ue_context_pP->ue_context.kenb[i]);
    }
405 406 407 408 409

    msg("\n");

    msg("\nKRRCenc:");

410
    for(i = 0; i < 32; i++) {
411
      msg("%02x", kRRCenc[i]);
412
    }
413 414 415 416 417

    msg("\n");

    msg("\nKRRCint:");

418
    for(i = 0; i < 32; i++) {
419
      msg("%02x", kRRCint[i]);
420
    }
421 422 423 424 425

    msg("\n");

  }

426
#endif //DEBUG_SECURITY
427 428
  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
  h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
429 430


431
  if (h_rc == HASH_TABLE_OK) {
432
    pdcp_config_set_security(
433
      ctxt_pP,
434 435 436 437
      pdcp_p,
      DCCH,
      DCCH+2,
      (send_security_mode_command == TRUE)  ?
438 439 440
      0 | (ue_context_pP->ue_context.integrity_algorithm << 4) :
      (ue_context_pP->ue_context.ciphering_algorithm )         |
      (ue_context_pP->ue_context.integrity_algorithm << 4),
441 442 443
      kRRCenc,
      kRRCint,
      kUPenc);
444 445 446 447 448 449
  } else {
    LOG_E(RRC,
          PROTOCOL_RRC_CTXT_UE_FMT"Could not get PDCP instance for SRB DCCH %u\n",
          PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
          DCCH);
  }
450

451
#endif
452 453
}

454 455 456 457 458 459 460
//------------------------------------------------------------------------------
void
rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP
)
//------------------------------------------------------------------------------
461
{
462
  MessageDef      *msg_p         = NULL;
winckel's avatar
winckel committed
463 464 465 466 467
  int e_rab;
  int e_rabs_done = 0;
  int e_rabs_failed = 0;

  msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_RESP);
468
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
469

470 471
  for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) {
    if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) {
winckel's avatar
winckel committed
472
      e_rabs_done++;
473
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
winckel's avatar
winckel committed
474
      // TODO add other information from S1-U when it will be integrated
475 476
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab];
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab];
477 478
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr.length = 4;
    } else {
winckel's avatar
winckel committed
479
      e_rabs_failed++;
480
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
winckel's avatar
winckel committed
481 482 483
      // TODO add cause when it will be integrated
    }
  }
484 485

  MSC_LOG_TX_MESSAGE(
486 487 488 489 490 491 492 493 494
    MSC_RRC_ENB,
    MSC_S1AP_ENB,
    (const char *)&S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p),
    sizeof(s1ap_initial_context_setup_resp_t),
    MSC_AS_TIME_FMT" INITIAL_CONTEXT_SETUP_RESP UE %X eNB_ue_s1ap_id %u e_rabs:%u succ %u fail",
    MSC_AS_TIME_ARGS(ctxt_pP),
    ue_context_pP->ue_id_rnti,
    S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id,
    e_rabs_done, e_rabs_failed);
495

496

winckel's avatar
winckel committed
497 498 499
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs = e_rabs_done;
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed;

500
  itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
501 502 503
}
# endif

504 505 506 507 508 509 510 511
//------------------------------------------------------------------------------
void
rrc_eNB_send_S1AP_UPLINK_NAS(
  const protocol_ctxt_t*    const ctxt_pP,
  rrc_eNB_ue_context_t*             const ue_context_pP,
  UL_DCCH_Message_t*        const ul_dcch_msg
)
//------------------------------------------------------------------------------
512
{
winckel's avatar
winckel committed
513 514 515 516 517
#if defined(ENABLE_ITTI)
  {
    ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;

    if ((ulInformationTransfer->criticalExtensions.present == ULInformationTransfer__criticalExtensions_PR_c1)
518 519 520 521
    && (ulInformationTransfer->criticalExtensions.choice.c1.present
    == ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
    && (ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType.present
    == ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)) {
winckel's avatar
winckel committed
522 523 524 525 526 527 528 529 530 531 532
      /* This message hold a dedicated info NAS payload, forward it to NAS */
      struct ULInformationTransfer_r8_IEs__dedicatedInfoType *dedicatedInfoType =
          &ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType;
      uint32_t pdu_length;
      uint8_t *pdu_buffer;
      MessageDef *msg_p;

      pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size;
      pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf;

      msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UPLINK_NAS);
533
      S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
winckel's avatar
winckel committed
534 535 536
      S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
      S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;

537
      itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
538 539 540 541 542 543 544 545 546 547
    }
  }
#else
  {
    ULInformationTransfer_t *ulInformationTransfer;
    ulInformationTransfer =
    &ul_dcch_msg->message.choice.c1.choice.
    ulInformationTransfer;

    if (ulInformationTransfer->criticalExtensions.present ==
548
    ULInformationTransfer__criticalExtensions_PR_c1) {
winckel's avatar
winckel committed
549
      if (ulInformationTransfer->criticalExtensions.choice.c1.present ==
550
      ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8) {
winckel's avatar
winckel committed
551 552 553 554 555 556

        ULInformationTransfer_r8_IEs_t
        *ulInformationTransferR8;
        ulInformationTransferR8 =
        &ulInformationTransfer->criticalExtensions.choice.
        c1.choice.ulInformationTransfer_r8;
557

winckel's avatar
winckel committed
558
        if (ulInformationTransferR8->dedicatedInfoType.
559 560 561 562 563 564 565 566 567
        present ==
        ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)
          s1ap_eNB_new_data_request (mod_id, ue_index,
          ulInformationTransferR8->
          dedicatedInfoType.choice.
          dedicatedInfoNAS.buf,
          ulInformationTransferR8->
          dedicatedInfoType.choice.
          dedicatedInfoNAS.size);
winckel's avatar
winckel committed
568 569 570 571 572 573
      }
    }
  }
#endif
}

574 575 576 577 578 579 580
//------------------------------------------------------------------------------
void rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  UL_DCCH_Message_t* ul_dcch_msg
)
//------------------------------------------------------------------------------
581
{
582 583 584 585 586 587
  UECapabilityInformation_t *ueCapabilityInformation = &ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation;

  if ((ueCapabilityInformation->criticalExtensions.present == UECapabilityInformation__criticalExtensions_PR_c1)
      && (ueCapabilityInformation->criticalExtensions.choice.c1.present
          == UECapabilityInformation__criticalExtensions__c1_PR_ueCapabilityInformation_r8)
      && (ueCapabilityInformation->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.count > 0)) {
588 589
    UE_CapabilityRAT_ContainerList_t* ue_CapabilityRAT_ContainerList =
      &ueCapabilityInformation->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList;
590
    MessageDef *msg_p;
591

592
    msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CAPABILITIES_IND);
593
    S1AP_UE_CAPABILITIES_IND (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
594 595
    S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.length = ue_CapabilityRAT_ContainerList->list.array[0]->ueCapabilityRAT_Container.size;
    S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.buffer = ue_CapabilityRAT_ContainerList->list.array[0]->ueCapabilityRAT_Container.buf;
596

597
    itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
598

599
    if (ue_CapabilityRAT_ContainerList->list.count > 1) {
600 601 602
      LOG_W (RRC,"[eNB %d][UE %x] can only handle 1 UE capability RAT item for now (%d)\n",
             ctxt_pP->module_id,
             ue_context_pP->ue_context.rnti,
603 604
             ue_CapabilityRAT_ContainerList->list.count);
    }
605 606 607
  }
}

608 609 610 611 612 613 614 615
//------------------------------------------------------------------------------
void
rrc_eNB_send_S1AP_NAS_FIRST_REQ(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  RRCConnectionSetupComplete_r8_IEs_t* rrcConnectionSetupComplete
)
//------------------------------------------------------------------------------
616
{
winckel's avatar
winckel committed
617 618
#if defined(ENABLE_ITTI)
  {
619 620
    MessageDef*         message_p         = NULL;
    rrc_ue_s1ap_ids_t*  rrc_ue_s1ap_ids_p = NULL;
621
    hashtable_rc_t      h_rc;
winckel's avatar
winckel committed
622 623

    message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_FIRST_REQ);
624 625
    memset(&message_p->ittiMsg.s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));

626 627 628 629 630 631 632 633
    ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id (ctxt_pP->module_id);
    S1AP_NAS_FIRST_REQ (message_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id;

    rrc_ue_s1ap_ids_p = malloc(sizeof(*rrc_ue_s1ap_ids_p));
    rrc_ue_s1ap_ids_p->ue_initial_id  = ue_context_pP->ue_context.ue_initial_id;
    rrc_ue_s1ap_ids_p->eNB_ue_s1ap_id = UE_INITIAL_ID_INVALID;
    rrc_ue_s1ap_ids_p->ue_rnti        = ctxt_pP->rnti;

634 635 636
    h_rc = hashtable_insert(eNB_rrc_inst[ctxt_pP->module_id].initial_id2_s1ap_ids,
    		               (hash_key_t)ue_context_pP->ue_context.ue_initial_id,
    		               rrc_ue_s1ap_ids_p);
637
    if (h_rc != HASH_TABLE_OK) {
638 639
      LOG_E(S1AP, "[eNB %d] Error while hashtable_insert in initial_id2_s1ap_ids ue_initial_id %u\n",
    		  ctxt_pP->module_id, ue_context_pP->ue_context.ue_initial_id);
640
    }
winckel's avatar
winckel committed
641 642

    /* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
643
    AssertFatal(ue_context_pP->ue_context.establishment_cause < RRC_CAUSE_LAST,
644
    "Establishment cause invalid (%jd/%d) for eNB %d!",
645 646 647
    ue_context_pP->ue_context.establishment_cause, RRC_CAUSE_LAST, ctxt_pP->module_id);

    S1AP_NAS_FIRST_REQ (message_p).establishment_cause = ue_context_pP->ue_context.establishment_cause;
winckel's avatar
winckel committed
648 649

    /* Forward NAS message */S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer =
650
    rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
winckel's avatar
winckel committed
651 652 653 654 655 656
    S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size;

    /* Fill UE identities with available information */
    {
      S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask = UE_IDENTITIES_NONE;

657
      if (ue_context_pP->ue_context.Initialue_identity_s_TMSI.presence) {
winckel's avatar
winckel committed
658
        /* Fill s-TMSI */
659
        UE_S_TMSI* s_TMSI = &ue_context_pP->ue_context.Initialue_identity_s_TMSI;
winckel's avatar
winckel committed
660 661 662 663

        S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_s_tmsi;
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code = s_TMSI->mme_code;
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi = s_TMSI->m_tmsi;
664
        LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ with s_TMSI: MME code %u M-TMSI %u ue %x\n",
gauthier's avatar
gauthier committed
665 666 667 668
            ctxt_pP->module_id,
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code,
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi,
            ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
669 670 671 672 673
      }

      if (rrcConnectionSetupComplete->registeredMME != NULL) {
        /* Fill GUMMEI */
        struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
gauthier's avatar
gauthier committed
674
        int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity;
winckel's avatar
winckel committed
675 676

        S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
677

winckel's avatar
winckel committed
678 679 680 681
        if (r_mme->plmn_Identity != NULL) {
          if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
            /* Use first indicated PLMN MCC if it is defined */
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
682
            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
gauthier's avatar
gauthier committed
683 684 685
                ctxt_pP->module_id,
                S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
                ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
686
          }
687

winckel's avatar
winckel committed
688 689 690
          if (r_mme->plmn_Identity->mnc.list.count > 0) {
            /* Use first indicated PLMN MNC if it is defined */
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
691 692
            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
                  ctxt_pP->module_id,
693
                  S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
694
                  ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
695
          }
gauthier's avatar
gauthier committed
696 697 698 699 700 701 702
        } else {
          const Enb_properties_array_t   *enb_properties_p  = NULL;
          enb_properties_p = enb_config_get();

          // actually the eNB configuration contains only one PLMN (can be up to 6)
          S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc;
          S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc;
gauthier's avatar
gauthier committed
703
          S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length;
winckel's avatar
winckel committed
704
        }
705

Lionel Gauthier's avatar
Lionel Gauthier committed
706
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code     = BIT_STRING_to_uint8 (&r_mme->mmec);
winckel's avatar
winckel committed
707
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
708 709

        MSC_LOG_TX_MESSAGE(
710 711 712 713 714 715 716 717
          MSC_S1AP_ENB,
          MSC_S1AP_MME,
          (const char *)&message_p->ittiMsg.s1ap_nas_first_req,
          sizeof(s1ap_nas_first_req_t),
          MSC_AS_TIME_FMT" S1AP_NAS_FIRST_REQ eNB %u UE %x",
          MSC_AS_TIME_ARGS(ctxt_pP),
          ctxt_pP->module_id,
          ctxt_pP->rnti);
718

719 720
        LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI mme_code %u mme_group_id %u ue %x\n",
              ctxt_pP->module_id,
721 722
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code,
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id,
723
              ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
724 725
      }
    }
726
    itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, message_p);
winckel's avatar
winckel committed
727 728 729
  }
#else
  {
730 731 732
    s1ap_eNB_new_data_request (
      ctxt_pP->module_id,
      ue_context_pP,
733 734 735 736
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      buf,
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      size);
winckel's avatar
winckel committed
737 738 739 740 741
  }
#endif
}

# if defined(ENABLE_ITTI)
742 743 744 745 746 747 748 749 750
//------------------------------------------------------------------------------
int
rrc_eNB_process_S1AP_DOWNLINK_NAS(
  MessageDef* msg_p,
  const char* msg_name,
  instance_t instance,
  mui_t* rrc_eNB_mui
)
//------------------------------------------------------------------------------
751
{
752 753
  uint16_t ue_initial_id;
  uint32_t eNB_ue_s1ap_id;
winckel's avatar
winckel committed
754 755 756
  uint32_t length;
  uint8_t *buffer;

757 758
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
759 760
  ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id;
  eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
761 762 763 764 765 766
  ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
  LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d\n",
        instance,
        msg_name,
        ue_initial_id,
        eNB_ue_s1ap_id);
winckel's avatar
winckel committed
767

768
  if (ue_context_p == NULL) {
769 770

    MSC_LOG_RX_MESSAGE(
771 772 773 774 775 776 777 778
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      NULL,
      0,
      MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u eNB_ue_s1ap_id %u",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      eNB_ue_s1ap_id);
779

winckel's avatar
winckel committed
780 781 782
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

783
    LOG_W(RRC, "[eNB %d] In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
winckel's avatar
winckel committed
784

winckel's avatar
winckel committed
785
    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_NON_DELIVERY_IND);
786
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
winckel's avatar
winckel committed
787 788 789 790
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.length = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length;
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.buffer = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer;

    // TODO add failure cause when defined!
winckel's avatar
winckel committed
791

792 793

    MSC_LOG_TX_MESSAGE(
794 795 796 797 798 799 800 801
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      (const char *)NULL,
      0,
      MSC_AS_TIME_FMT" S1AP_NAS_NON_DELIVERY_IND UE initial id %u eNB_ue_s1ap_id %u (ue ctxt !found)",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      eNB_ue_s1ap_id);
802

winckel's avatar
winckel committed
803 804
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
805
  } else {
806
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
807

808
    /* Is it the first income from S1AP ? */
809 810
    if (ue_context_p->ue_context.eNB_ue_s1ap_id == 0) {
      ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
811
    }
812 813

    MSC_LOG_RX_MESSAGE(
814 815 816 817 818 819 820 821
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      (const char *)NULL,
      0,
      MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u eNB_ue_s1ap_id %u",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id);
822

823 824

    /* Create message for PDCP (DLInformationTransfer_t) */
825 826 827 828
    length = do_DLInformationTransfer (
               instance,
               &buffer,
               rrc_eNB_get_next_transaction_identifier (instance),
829 830
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
winckel's avatar
winckel committed
831

832
#ifdef RRC_MSG_PRINT
833 834
    int i=0;
    LOG_F(RRC,"[MSG] RRC DL Information Transfer\n");
835

836
    for (i = 0; i < length; i++) {
837
      LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
838
    }
839

840 841
    LOG_F(RRC,"\n");
#endif
winckel's avatar
winckel committed
842
    /* Transfer data to PDCP */
843 844 845 846 847 848 849 850
    pdcp_rrc_data_req (
      &ctxt,
      DCCH,
      *rrc_eNB_mui++,
      SDU_CONFIRM_NO,
      length,
      buffer,
      PDCP_TRANSMISSION_MODE_CONTROL);
winckel's avatar
winckel committed
851 852 853 854 855 856

    return (0);
  }
}

/*------------------------------------------------------------------------------*/
857 858
int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
859 860 861 862 863
  uint16_t                        ue_initial_id;
  uint32_t                        eNB_ue_s1ap_id;
  MessageDef                     *message_gtpv1u_p = NULL;
  gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
  gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
winckel's avatar
winckel committed
864

865 866
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
867 868
  ue_initial_id  = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id;
  eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
869 870 871
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
  LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n",
        instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs);
winckel's avatar
winckel committed
872

873
  if (ue_context_p == NULL) {
874 875
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p = NULL;
winckel's avatar
winckel committed
876

877
    LOG_W(RRC, "[eNB %d] In S1AP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
winckel's avatar
winckel committed
878

879 880
    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL);
    S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
winckel's avatar
winckel committed
881

882
    // TODO add failure cause when defined!
winckel's avatar
winckel committed
883

884 885 886
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
  } else {
winckel's avatar
winckel committed
887

888 889
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
    ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
winckel's avatar
winckel committed
890

891 892 893
    /* Save e RAB information for later */
    {
      int i;
winckel's avatar
winckel committed
894

895
      memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
896
      ue_context_p->ue_context.nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs;
897

898 899 900
      for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++) {
        ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW;
        ue_context_p->ue_context.e_rab[i].param = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i];
901

902

903 904
        create_tunnel_req.eps_bearer_id[i]       = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].e_rab_id;
        create_tunnel_req.sgw_S1u_teid[i]        = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].gtp_teid;
winckel's avatar
winckel committed
905

906
        memcpy(&create_tunnel_req.sgw_addr[i],
907 908 909
               &S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].sgw_addr,
               sizeof(transport_layer_addr_t));
      }
winckel's avatar
winckel committed
910

911 912
      create_tunnel_req.rnti       = ue_context_p->ue_context.rnti; // warning put zero above
      create_tunnel_req.num_tunnels    = i;
913

914 915 916 917 918 919 920 921
      gtpv1u_create_s1u_tunnel(
        instance,
        &create_tunnel_req,
        &create_tunnel_resp);

      rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
          &ctxt,
          &create_tunnel_resp);
922 923 924 925
    }

    /* TODO parameters yet to process ... */
    {
926
      //      S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_ambr;
927
    }
928

929 930 931 932 933 934 935 936
    rrc_eNB_process_security (
      &ctxt,
      ue_context_p,
      &S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_capabilities);
    process_eNB_security_key (
      &ctxt,
      ue_context_p,
      S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key);
937

938 939
    {
      uint8_t send_security_mode_command = TRUE;
940

941
#ifndef EXMIMO_IOT
942

943 944
      if ((ue_context_p->ue_context.ciphering_algorithm == SecurityAlgorithmConfig__cipheringAlgorithm_eea0)
          && (ue_context_p->ue_context.integrity_algorithm == INTEGRITY_ALGORITHM_NONE)) {
945 946 947
        send_security_mode_command = FALSE;
      }

948
#endif
949 950 951 952
      rrc_pdcp_config_security(
        &ctxt,
        ue_context_p,
        send_security_mode_command);
953

954
      if (send_security_mode_command) {
955

956 957 958
        rrc_eNB_generate_SecurityModeCommand (
          &ctxt,
          ue_context_p);
959 960
        send_security_mode_command = FALSE;
        // apply ciphering after RRC security command mode
961 962 963 964
        rrc_pdcp_config_security(
          &ctxt,
          ue_context_p,
          send_security_mode_command);
965
      } else {
966
        rrc_eNB_generate_UECapabilityEnquiry (&ctxt, ue_context_p);
967
      }
winckel's avatar
winckel committed
968
    }
969 970
    return (0);
  }
winckel's avatar
winckel committed
971 972
}

973
/*------------------------------------------------------------------------------*/
974 975
int rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
976
  uint32_t eNB_ue_s1ap_id;
977 978
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
979 980

  eNB_ue_s1ap_id = S1AP_UE_CTXT_MODIFICATION_REQ (msg_p).eNB_ue_s1ap_id;
981
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id);
982

983
  if (ue_context_p == NULL) {
984 985 986
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

987
    LOG_W(RRC, "[eNB %d] In S1AP_UE_CTXT_MODIFICATION_REQ: unknown UE from eNB_ue_s1ap_id (%d) for eNB %d\n", instance, eNB_ue_s1ap_id);
988 989 990 991 992 993 994 995

    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CTXT_MODIFICATION_FAIL);
    S1AP_UE_CTXT_MODIFICATION_FAIL (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;

    // TODO add failure cause when defined!

    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
996
  } else {
997

998
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
999 1000 1001
    /* TODO parameters yet to process ... */
    {
      if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_UE_AMBR) {
1002
        //        S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).ue_ambr;
1003
      }
1004 1005 1006
    }

    if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP) {
1007 1008 1009 1010
      if (rrc_eNB_process_security (
            &ctxt,
            ue_context_p,
            &S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).security_capabilities)) {
1011
        /* transmit the new security parameters to UE */
1012 1013 1014
        rrc_eNB_generate_SecurityModeCommand (
          &ctxt,
          ue_context_p);
1015 1016 1017 1018
      }
    }

    if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_SECURITY_KEY) {
1019 1020 1021 1022
      process_eNB_security_key (
        &ctxt,
        ue_context_p,
        S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).security_key);
1023 1024

      /* TODO reconfigure lower layers... */
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
    }

    /* Send the response */
    {
      MessageDef *msg_resp_p;

      msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CTXT_MODIFICATION_RESP);
      S1AP_UE_CTXT_MODIFICATION_RESP(msg_resp_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;

      itti_send_msg_to_task(TASK_S1AP, instance, msg_resp_p);
    }

    return (0);
  }
}

/*------------------------------------------------------------------------------*/
1042 1043
int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char *msg_name, instance_t instance)
{
1044
  uint32_t eNB_ue_s1ap_id;
1045
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1046 1047

  eNB_ue_s1ap_id = S1AP_UE_CONTEXT_RELEASE_REQ(msg_p).eNB_ue_s1ap_id;
1048
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id);
1049

1050
  if (ue_context_p == NULL) {
1051 1052 1053
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

Lionel Gauthier's avatar
Lionel Gauthier committed
1054
    LOG_W(RRC, "[eNB %d] In S1AP_UE_CONTEXT_RELEASE_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n",
1055 1056
          instance,
          eNB_ue_s1ap_id);
1057 1058 1059 1060 1061 1062 1063 1064

    msg_fail_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */
    S1AP_UE_CONTEXT_RELEASE_RESP(msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;

    // TODO add failure cause when defined!

    itti_send_msg_to_task(TASK_S1AP, instance, msg_fail_p);
    return (-1);
1065
  } else {
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    /* TODO release context. */

    /* Send the response */
    {
      MessageDef *msg_resp_p;

      msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_RESP);
      S1AP_UE_CONTEXT_RELEASE_RESP(msg_resp_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;

      itti_send_msg_to_task(TASK_S1AP, instance, msg_resp_p);
    }

    return (0);
  }
}

1082 1083 1084 1085 1086 1087 1088 1089
//------------------------------------------------------------------------------
void rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ (
  const module_id_t                        enb_mod_idP,
  const rrc_eNB_ue_context_t*        const ue_context_pP,
  const s1ap_Cause_t                       causeP,
  const long                               cause_valueP
)
//------------------------------------------------------------------------------
1090
{
1091
  if (ue_context_pP == NULL) {
Lionel Gauthier's avatar
Lionel Gauthier committed
1092
    LOG_W(RRC,
1093
          "[eNB] In S1AP_UE_CONTEXT_RELEASE_COMMAND: invalid  UE\n");
Lionel Gauthier's avatar
Lionel Gauthier committed
1094
  } else {
Raymond Knopp's avatar
Raymond Knopp committed
1095 1096 1097 1098 1099 1100 1101
	  MSC_LOG_TX_MESSAGE(
			  MSC_RRC_ENB,
	  		  MSC_S1AP_ENB,
	  		  NULL,0,
	  		  "0 S1AP_UE_CONTEXT_RELEASE_REQ eNB_ue_s1ap_id 0x%06"PRIX32" ",
	  		  ue_context_pP->ue_context.eNB_ue_s1ap_id);

1102 1103
    MessageDef *msg_context_release_req_p = NULL;
    msg_context_release_req_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_REQ);
1104
    S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
1105 1106
    S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause          = causeP;
    S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause_value    = cause_valueP;
1107
    itti_send_msg_to_task(TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_mod_idP), msg_context_release_req_p);
Lionel Gauthier's avatar
Lionel Gauthier committed
1108 1109 1110 1111
  }
}


1112
/*------------------------------------------------------------------------------*/
1113 1114
int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance)
{
1115
  uint32_t eNB_ue_s1ap_id;
1116
  protocol_ctxt_t              ctxt;
1117 1118
  struct rrc_eNB_ue_context_s *ue_context_p = NULL;
  struct rrc_ue_s1ap_ids_s    *rrc_ue_s1ap_ids = NULL;
1119 1120

  eNB_ue_s1ap_id = S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p).eNB_ue_s1ap_id;
1121 1122


1123
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id);
1124

1125
  if (ue_context_p == NULL) {
1126 1127 1128 1129
    /* Can not associate this message to an UE index */
    MessageDef *msg_complete_p;

    LOG_W(RRC,
1130 1131 1132
          "[eNB %d] In S1AP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from eNB_ue_s1ap_id (%d)\n",
          instance,
          eNB_ue_s1ap_id);
1133

Raymond Knopp's avatar
Raymond Knopp committed
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
    MSC_LOG_EVENT(
          MSC_RRC_ENB,
  		  "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" context not found",
  		eNB_ue_s1ap_id);

    MSC_LOG_TX_MESSAGE(
          MSC_RRC_ENB,
  		  MSC_S1AP_ENB,
  		  NULL,0,
  		  "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
  		eNB_ue_s1ap_id);

1146 1147 1148
    msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
    S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
    itti_send_msg_to_task(TASK_S1AP, instance, msg_complete_p);
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

    rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(
    		&eNB_rrc_inst[instance],
    		UE_INITIAL_ID_INVALID,
    		eNB_ue_s1ap_id);

    if (NULL != rrc_ue_s1ap_ids) {
      rrc_eNB_S1AP_remove_ue_ids(
    		  &eNB_rrc_inst[instance],
    		  rrc_ue_s1ap_ids);
    }
1160
    return (-1);
1161
  } else {
1162 1163
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
    rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context_p);
1164 1165 1166 1167 1168 1169
    /*
          LOG_W(RRC,
                  "[eNB %d] In S1AP_UE_CONTEXT_RELEASE_COMMAND: TODO call rrc_eNB_connection_release for eNB %d\n",
                  instance,
                  eNB_ue_s1ap_id);
    */
1170
    {
1171 1172 1173 1174
      int      e_rab;
      int      mod_id = 0;
      MessageDef *msg_delete_tunnels_p = NULL;

Raymond Knopp's avatar
Raymond Knopp committed
1175 1176 1177 1178 1179 1180 1181
      MSC_LOG_TX_MESSAGE(
            MSC_RRC_ENB,
            MSC_GTPU_ENB,
            NULL,0,
            "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ",
            eNB_ue_s1ap_id);

1182 1183 1184 1185 1186 1187
      msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
      memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p),
             0,
             sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));

      // do not wait response
1188
      GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
1189

1190
      for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
1191
        GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
1192
          ue_context_p->ue_context.enb_gtp_ebi[e_rab];
1193
        // erase data
1194 1195 1196
        ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
        memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
        ue_context_p->ue_context.enb_gtp_ebi[e_rab]  = 0;
1197 1198 1199
      }

      itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p);
1200

Raymond Knopp's avatar
Raymond Knopp committed
1201 1202 1203 1204 1205 1206 1207 1208

      MSC_LOG_TX_MESSAGE(
            MSC_RRC_ENB,
            MSC_S1AP_ENB,
            NULL,0,
            "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
            eNB_ue_s1ap_id);

1209 1210 1211 1212
      MessageDef *msg_complete_p = NULL;
      msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
      S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
      itti_send_msg_to_task(TASK_S1AP, instance, msg_complete_p);
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223

      rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(
      		&eNB_rrc_inst[instance],
      		UE_INITIAL_ID_INVALID,
      		eNB_ue_s1ap_id);

      if (NULL != rrc_ue_s1ap_ids) {
        rrc_eNB_S1AP_remove_ue_ids(
      		  &eNB_rrc_inst[instance],
      		  rrc_ue_s1ap_ids);
      }
1224 1225 1226 1227 1228 1229 1230
    }

    return (0);
  }
}


winckel's avatar
winckel committed
1231 1232
# endif /* defined(ENABLE_ITTI) */
#endif /* defined(ENABLE_USE_MME) */