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

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


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

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

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

nikaeinn's avatar
nikaeinn committed
28
*******************************************************************************/
winckel's avatar
winckel committed
29
30
/*! \file rrc_eNB_S1AP.c
 * \brief rrc S1AP procedures for eNB
31
 * \author Navid Nikaein, Laurent Winckel, Sebastien ROUX, and Lionel GAUTHIER
32
 * \date 2013-2016
winckel's avatar
winckel committed
33
34
 * \version 1.0
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
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

Cedric Roux's avatar
Cedric Roux committed
63
64
#include "UERadioAccessCapabilityInformation.h"

Cedric Roux's avatar
Cedric Roux committed
65
66
67
#include "gtpv1u_eNB_task.h"
#include "RRC/LITE/rrc_eNB_GTPV1U.h"

winckel's avatar
winckel committed
68
69
70
/* Value to indicate an invalid UE initial id */
static const uint16_t UE_INITIAL_ID_INVALID = 0;

71
/* Masks for S1AP Encryption algorithms, EEA0 is always supported (not coded) */
72
73
static const uint16_t S1AP_ENCRYPTION_EEA1_MASK = 0x8000;
static const uint16_t S1AP_ENCRYPTION_EEA2_MASK = 0x4000;
74
75

/* Masks for S1AP Integrity algorithms, EIA0 is always supported (not coded) */
76
77
static const uint16_t S1AP_INTEGRITY_EIA1_MASK = 0x8000;
static const uint16_t S1AP_INTEGRITY_EIA2_MASK = 0x4000;
78
79
80
81

#ifdef Rel10
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920
#else
82
#ifdef EXMIMO_IOT
83
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia2
84
#else
85
86
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_reserved
#endif
87
#endif
88

winckel's avatar
winckel committed
89
90


91

92
# if defined(ENABLE_ITTI)
93
94
95
96
97
98
99
100
101
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
{
102
103
  rrc_ue_s1ap_ids_t *result = NULL;
  rrc_ue_s1ap_ids_t *result2 = NULL;
104
105
106
107
108
109
110
111
112
  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) {
113
	  if (eNB_ue_s1ap_id > 0) {
114
115
116
117
118
119
120
121
122
123
	    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);
124
125
            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",
126
		    		  rrc_instance_pP - eNB_rrc_inst, eNB_ue_s1ap_id);
127
            }
128
129
130
131
132
		  }
		}
	  }
	}
  }
133
  return result;
134
}
135
136
137
138
139
140
141
142
//------------------------------------------------------------------------------
void
rrc_eNB_S1AP_remove_ue_ids(
  eNB_RRC_INST*              const rrc_instance_pP,
  struct rrc_ue_s1ap_ids_s* const ue_ids_pP
)
//------------------------------------------------------------------------------
{
143
144
145
  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;
146
147
148
  if (rrc_instance_pP == NULL) {
    LOG_E(RRC, "Bad RRC instance\n");
    return;
149
150
  }

151
152
153
  if (ue_ids_pP == NULL) {
    LOG_E(RRC, "Trying to free a NULL S1AP UE IDs\n");
    return;
winckel's avatar
winckel committed
154
  }
155

156
157
158
159
  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);
160
161
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
162
163
164
165
166
167
168
	}
  }

  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);
169
170
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
171
172
	}
  }
winckel's avatar
winckel committed
173
174
}

175
176
/*! \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
177
 *\param mod_id Instance ID of eNB.
178
 *\return the UE initial ID.
winckel's avatar
winckel committed
179
 */
180
181
182
183
184
185
//------------------------------------------------------------------------------
static uint16_t
get_next_ue_initial_id(
  const module_id_t mod_id
)
//------------------------------------------------------------------------------
186
{
187
188
  static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
  ue_initial_id[mod_id]++;
winckel's avatar
winckel committed
189

190
191
192
193
  /* 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
194

195
  return ue_initial_id[mod_id];
196
}
197

198
199


winckel's avatar
winckel committed
200

winckel's avatar
winckel committed
201
/*! \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
202
203
204
205
206
207
208
 *\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.
 */
209
210
211
212
213
214
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
)
215
{
216
217
218
219
220
221
222
223
  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
224

225
226
227
    return rrc_eNB_get_ue_context(
             &eNB_rrc_inst[ENB_INSTANCE_TO_MODULE_ID(instanceP)],
             temp->ue_rnti);
winckel's avatar
winckel committed
228
229
  }

230
  return NULL;
winckel's avatar
winckel committed
231
232
}

233
234
235
236
237
/*! \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.
 */
238
239
240
static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(uint16_t algorithms)
{

241
//#warning "Forced   return SecurityAlgorithmConfig__cipheringAlgorithm_eea0, to be deleted in future"
242
  return SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
243

244
  if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) {
245
    return SecurityAlgorithmConfig__cipheringAlgorithm_eea2;
246
247
248
  }

  if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) {
249
    return SecurityAlgorithmConfig__cipheringAlgorithm_eea1;
250
251
252
253
254
255
256
257
258
259
  }

  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.
 */
260
261
262
static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
{

263
  if (algorithms & S1AP_INTEGRITY_EIA2_MASK) {
264
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
265
266
267
  }

  if (algorithms & S1AP_INTEGRITY_EIA1_MASK) {
268
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1;
269
270
271
272
273
274
275
276
277
278
279
280
  }

  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.
 */
281
282
283
284
285
286
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
)
287
{
288
  boolean_t                                         changed = FALSE;
289
290
291
292
  e_SecurityAlgorithmConfig__cipheringAlgorithm cipheringAlgorithm;
  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm;

  /* Save security parameters */
293
  ue_context_pP->ue_context.security_capabilities = *security_capabilities_pP;
294

295
296
  // translation
  LOG_D(RRC,
297
        "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %u NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n",
298
299
300
301
302
        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);
303
  /* Select relevant algorithms */
304
  cipheringAlgorithm = rrc_eNB_select_ciphering (ue_context_pP->ue_context.security_capabilities.encryption_algorithms);
305

306
307
  if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) {
    ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm;
308
    changed = TRUE;
309
310
  }

311
  integrityProtAlgorithm = rrc_eNB_select_integrity (ue_context_pP->ue_context.security_capabilities.integrity_algorithms);
312

313
314
  if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) {
    ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm;
315
    changed = TRUE;
316
317
  }

318
319
320
321
322
323
324
  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");
325
326
327
328

  return changed;
}

329
/*! \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)
330
 *\brief save security key.
331
332
333
 *\param ctxt_pP         Running context.
 *\param ue_context_pP   UE context.
 *\param security_key_pP The security key received from S1AP.
334
 */
335
336
337
338
339
340
341
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
342
{
343
344
345
346
347
#if defined(ENABLE_SECURITY)
  char ascii_buffer[65];
  uint8_t i;

  /* Saves the security key */
348
  memcpy (ue_context_pP->ue_context.kenb, security_key_pP, SECURITY_KEY_LENGTH);
349
350

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

354
355
  ascii_buffer[2 * i] = '\0';

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

360

361
362
363
364
365
366
367
368
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
369
{
370
371
372

#if defined(ENABLE_SECURITY)

373

374
  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;
375
376
377
378
  uint8_t                            *kRRCenc = NULL;
  uint8_t                            *kRRCint = NULL;
  uint8_t                            *kUPenc = NULL;
  pdcp_t                             *pdcp_p   = NULL;
379
  static int                          print_keys= 1;
380
381
  hashtable_rc_t                      h_rc;
  hash_key_t                          key;
382

383
384
  /* Derive the keys from kenb */
  if (SRB_configList != NULL) {
385
386
387
    derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
                      ue_context_pP->ue_context.kenb,
                      &kUPenc);
388
  }
389

390
391
392
393
394
395
  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);
396
397
398

#define DEBUG_SECURITY 1

399
#if defined (DEBUG_SECURITY)
Cedric Roux's avatar
Cedric Roux committed
400
#undef msg
401
#define msg printf
402

403
  if (print_keys ==1 ) {
404
405
406
407
    print_keys =0;
    int i;
    msg("\nKeNB:");

408
409
410
    for(i = 0; i < 32; i++) {
      msg("%02x", ue_context_pP->ue_context.kenb[i]);
    }
411
412
413
414
415

    msg("\n");

    msg("\nKRRCenc:");

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

    msg("\n");

    msg("\nKRRCint:");

424
    for(i = 0; i < 32; i++) {
425
      msg("%02x", kRRCint[i]);
426
    }
427
428
429
430
431

    msg("\n");

  }

432
#endif //DEBUG_SECURITY
433
434
  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);
435
436


437
  if (h_rc == HASH_TABLE_OK) {
438
    pdcp_config_set_security(
439
      ctxt_pP,
440
441
442
443
      pdcp_p,
      DCCH,
      DCCH+2,
      (send_security_mode_command == TRUE)  ?
444
445
446
      0 | (ue_context_pP->ue_context.integrity_algorithm << 4) :
      (ue_context_pP->ue_context.ciphering_algorithm )         |
      (ue_context_pP->ue_context.integrity_algorithm << 4),
447
448
449
      kRRCenc,
      kRRCint,
      kUPenc);
450
451
452
453
454
455
  } 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);
  }
456

457
#endif
458
459
}

460
461
462
463
464
465
466
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
467
{
468
  MessageDef      *msg_p         = NULL;
winckel's avatar
winckel committed
469
470
471
472
473
  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);
474
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
475

476
477
  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
478
      e_rabs_done++;
479
      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
480
      // TODO add other information from S1-U when it will be integrated
481
482
      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];
483
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr.length = 4;
484
      ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED;
485
    } else {
winckel's avatar
winckel committed
486
      e_rabs_failed++;
487
      ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED;
488
      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
489
490
491
      // TODO add cause when it will be integrated
    }
  }
gauthier's avatar
gauthier committed
492
493

  MSC_LOG_TX_MESSAGE(
494
495
496
497
498
499
500
501
502
    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);
gauthier's avatar
gauthier committed
503

504

winckel's avatar
winckel committed
505
506
507
  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;

508
  itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
509
510
511
}
# endif

512
513
514
515
516
517
518
519
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
520
{
winckel's avatar
winckel committed
521
522
523
524
525
#if defined(ENABLE_ITTI)
  {
    ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;

    if ((ulInformationTransfer->criticalExtensions.present == ULInformationTransfer__criticalExtensions_PR_c1)
526
527
528
529
    && (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
530
531
532
533
534
535
536
537
538
539
540
      /* 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);
541
      S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
winckel's avatar
winckel committed
542
543
544
      S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
      S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;

545
      itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
546
547
548
549
550
551
552
553
554
555
    }
  }
#else
  {
    ULInformationTransfer_t *ulInformationTransfer;
    ulInformationTransfer =
    &ul_dcch_msg->message.choice.c1.choice.
    ulInformationTransfer;

    if (ulInformationTransfer->criticalExtensions.present ==
556
    ULInformationTransfer__criticalExtensions_PR_c1) {
winckel's avatar
winckel committed
557
      if (ulInformationTransfer->criticalExtensions.choice.c1.present ==
558
      ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8) {
winckel's avatar
winckel committed
559
560
561
562
563
564

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

winckel's avatar
winckel committed
566
        if (ulInformationTransferR8->dedicatedInfoType.
567
568
569
570
571
572
573
574
575
        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
576
577
578
579
580
581
      }
    }
  }
#endif
}

582
583
584
585
586
587
588
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
589
{
590
  UECapabilityInformation_t *ueCapabilityInformation = &ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation;
Cedric Roux's avatar
Cedric Roux committed
591
592
593
594
595
596
597
598
599
  /* 4096 is arbitrary, should be big enough */
  unsigned char buf[4096];
  unsigned char *buf2;
  UERadioAccessCapabilityInformation_t rac;

  if (ueCapabilityInformation->criticalExtensions.present != UECapabilityInformation__criticalExtensions_PR_c1
      || ueCapabilityInformation->criticalExtensions.choice.c1.present != UECapabilityInformation__criticalExtensions__c1_PR_ueCapabilityInformation_r8) {
    LOG_E(RRC, "[eNB %d][UE %x] bad UE capabilities\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti);
    return;
600
  }
Cedric Roux's avatar
Cedric Roux committed
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

  asn_enc_rval_t ret = uper_encode_to_buffer(&asn_DEF_UECapabilityInformation, ueCapabilityInformation, buf, 4096);
  if (ret.encoded == -1) abort();

  memset(&rac, 0, sizeof(UERadioAccessCapabilityInformation_t));

  rac.criticalExtensions.present = UERadioAccessCapabilityInformation__criticalExtensions_PR_c1;
  rac.criticalExtensions.choice.c1.present = UERadioAccessCapabilityInformation__criticalExtensions__c1_PR_ueRadioAccessCapabilityInformation_r8;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.ue_RadioAccessCapabilityInfo.buf = buf;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.ue_RadioAccessCapabilityInfo.size = (ret.encoded+7)/8;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.nonCriticalExtension = NULL;

  /* 8192 is arbitrary, should be big enough */
  buf2 = malloc16(8192);
  if (buf2 == NULL) abort();
  ret = uper_encode_to_buffer(&asn_DEF_UERadioAccessCapabilityInformation, &rac, buf2, 8192);
  if (ret.encoded == -1) abort();

  MessageDef *msg_p;

  msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CAPABILITIES_IND);
  S1AP_UE_CAPABILITIES_IND (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
  S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.length = (ret.encoded+7)/8;
  S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.buffer = buf2;

  itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
627
628
}

629
630
631
632
633
634
635
636
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
637
{
winckel's avatar
winckel committed
638
639
#if defined(ENABLE_ITTI)
  {
640
641
    MessageDef*         message_p         = NULL;
    rrc_ue_s1ap_ids_t*  rrc_ue_s1ap_ids_p = NULL;
642
    hashtable_rc_t      h_rc;
winckel's avatar
winckel committed
643
644

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

647
648
649
650
651
652
653
654
    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;

655
656
657
    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);
658
    if (h_rc != HASH_TABLE_OK) {
659
660
      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);
661
    }
winckel's avatar
winckel committed
662
663

    /* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
664
    AssertFatal(ue_context_pP->ue_context.establishment_cause < RRC_CAUSE_LAST,
665
    "Establishment cause invalid (%jd/%d) for eNB %d!",
666
667
668
    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
669
670

    /* Forward NAS message */S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer =
671
    rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
winckel's avatar
winckel committed
672
673
674
675
676
677
    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;

678
      if (ue_context_pP->ue_context.Initialue_identity_s_TMSI.presence) {
winckel's avatar
winckel committed
679
        /* Fill s-TMSI */
680
        UE_S_TMSI* s_TMSI = &ue_context_pP->ue_context.Initialue_identity_s_TMSI;
winckel's avatar
winckel committed
681
682
683
684

        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;
685
        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
686
687
688
689
            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
690
691
692
693
694
      }

      if (rrcConnectionSetupComplete->registeredMME != NULL) {
        /* Fill GUMMEI */
        struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
695
        //int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity;
winckel's avatar
winckel committed
696
697

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

winckel's avatar
winckel committed
699
700
701
702
        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];
703
            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
704
705
706
                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
707
          }
708

winckel's avatar
winckel committed
709
710
711
          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];
712
713
            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
                  ctxt_pP->module_id,
714
                  S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
715
                  ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
716
          }
gauthier's avatar
gauthier committed
717
718
719
720
721
722
723
        } 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
724
          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
725
        }
726

gauthier's avatar
gauthier committed
727
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code     = BIT_STRING_to_uint8 (&r_mme->mmec);
winckel's avatar
winckel committed
728
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
gauthier's avatar
gauthier committed
729
730

        MSC_LOG_TX_MESSAGE(
731
732
733
734
735
736
737
738
          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);
gauthier's avatar
gauthier committed
739

740
741
        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,
742
743
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code,
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id,
744
              ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
745
746
      }
    }
747
    itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, message_p);
winckel's avatar
winckel committed
748
749
750
  }
#else
  {
751
752
753
    s1ap_eNB_new_data_request (
      ctxt_pP->module_id,
      ue_context_pP,
754
755
756
757
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      buf,
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      size);
winckel's avatar
winckel committed
758
759
760
761
762
  }
#endif
}

# if defined(ENABLE_ITTI)
763
764
765
766
767
768
769
770
771
//------------------------------------------------------------------------------
int
rrc_eNB_process_S1AP_DOWNLINK_NAS(
  MessageDef* msg_p,
  const char* msg_name,
  instance_t instance,
  mui_t* rrc_eNB_mui
)
//------------------------------------------------------------------------------
772
{
773
774
  uint16_t ue_initial_id;
  uint32_t eNB_ue_s1ap_id;
winckel's avatar
winckel committed
775
776
  uint32_t length;
  uint8_t *buffer;
777
778
  uint8_t srb_id; 
  
779
780
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
781
782
  ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id;
  eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
783
  ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
784
785
  srb_id = ue_context_p->ue_context.Srb2.Srb_info.Srb_id;
  
786
787
788
789
790
  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
791

792
  if (ue_context_p == NULL) {
gauthier's avatar
gauthier committed
793
794

    MSC_LOG_RX_MESSAGE(
795
796
797
798
799
800
801
802
      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);
gauthier's avatar
gauthier committed
803

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

807
    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
808

winckel's avatar
winckel committed
809
    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_NON_DELIVERY_IND);
810
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
winckel's avatar
winckel committed
811
812
813
814
    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
815

gauthier's avatar
gauthier committed
816
817

    MSC_LOG_TX_MESSAGE(
818
819
820
821
822
823
824
825
      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);
gauthier's avatar
gauthier committed
826

winckel's avatar
winckel committed
827
828
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
829
  } else {
830
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
831

832
    /* Is it the first income from S1AP ? */
833
834
    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;
835
    }
gauthier's avatar
gauthier committed
836
837

    MSC_LOG_RX_MESSAGE(
838
839
840
841
842
843
844
845
      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);
gauthier's avatar
gauthier committed
846

847
848

    /* Create message for PDCP (DLInformationTransfer_t) */
849
850
851
852
    length = do_DLInformationTransfer (
               instance,
               &buffer,
               rrc_eNB_get_next_transaction_identifier (instance),
853
854
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
winckel's avatar
winckel committed
855

856
#ifdef RRC_MSG_PRINT
857
858
    int i=0;
    LOG_F(RRC,"[MSG] RRC DL Information Transfer\n");
859

860
    for (i = 0; i < length; i++) {
861
      LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
862
    }
863

864
865
    LOG_F(RRC,"\n");
#endif
866
867
868
    /* 
     * switch UL or DL NAS message without RRC piggybacked to SRB2 if active. 
     */
winckel's avatar
winckel committed
869
    /* Transfer data to PDCP */
870
871
    rrc_data_req (
		  &ctxt,
872
		  srb_id,
873
874
875
876
877
878
		  *rrc_eNB_mui++,
		  SDU_CONFIRM_NO,
		  length,
		  buffer,
		  PDCP_TRANSMISSION_MODE_CONTROL);
    
winckel's avatar
winckel committed
879
880
881
882
883
    return (0);
  }
}

/*------------------------------------------------------------------------------*/
884
885
int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
886
887
  uint16_t                        ue_initial_id;
  uint32_t                        eNB_ue_s1ap_id;
888
  //MessageDef                     *message_gtpv1u_p = NULL;
889
890
  gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
  gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
winckel's avatar
winckel committed
891

892
893
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
894
895
  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;
896
897
898
  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
899

900
  if (ue_context_p == NULL) {
901
902
    /* 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
903

904
    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
905

906
907
    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
908

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

911
912
913
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
  } else {
winckel's avatar
winckel committed
914

915
916
    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
917

918
919
920
    /* Save e RAB information for later */
    {
      int i;
winckel's avatar
winckel committed
921

922
      memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
923
      ue_context_p->ue_context.nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs;
924
     
925
926
927
      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];
928

929

930
931
        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
932

933
        memcpy(&create_tunnel_req.sgw_addr[i],
934
935
936
               &S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].sgw_addr,
               sizeof(transport_layer_addr_t));
      }
937
    
938
939
      create_tunnel_req.rnti       = ue_context_p->ue_context.rnti; // warning put zero above
      create_tunnel_req.num_tunnels    = i;
940

941
942
943
944
945
946
947
      gtpv1u_create_s1u_tunnel(
        instance,
        &create_tunnel_req,
        &create_tunnel_resp);

      rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
          &ctxt,
948
          &create_tunnel_resp); 
949
      ue_context_p->ue_context.setup_e_rabs=ue_context_p->ue_context.nb_of_e_rabs;
950
951
952
953
    }

    /* TODO parameters yet to process ... */
    {
954
      //      S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_ambr;
955
    }
956

957
958
959
960
961
962
963
964
    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);
965

966
967
    {
      uint8_t send_security_mode_command = TRUE;
968

969
#ifndef EXMIMO_IOT
970

971
972
      if ((ue_context_p->ue_context.ciphering_algorithm == SecurityAlgorithmConfig__cipheringAlgorithm_eea0)
          && (ue_context_p->ue_context.integrity_algorithm == INTEGRITY_ALGORITHM_NONE)) {
973
974
975
        send_security_mode_command = FALSE;
      }

976
#endif
977
978
979
980
      rrc_pdcp_config_security(
        &ctxt,
        ue_context_p,
        send_security_mode_command);
981

982
      if (send_security_mode_command) {
983

984
985
986
        rrc_eNB_generate_SecurityModeCommand (
          &ctxt,
          ue_context_p);
987
988
        send_security_mode_command = FALSE;
        // apply ciphering after RRC security command mode
989
990
991
992
        rrc_pdcp_config_security(
          &ctxt,
          ue_context_p,
          send_security_mode_command);
993
      } else {
994
        rrc_eNB_generate_UECapabilityEnquiry (&ctxt, ue_context_p);
995
      }
winckel's avatar
winckel committed
996
    }
997
998
    return (0);
  }
winckel's avatar
winckel committed
999
1000
}

1001
/*------------------------------------------------------------------------------*/
1002
1003
int rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
1004
  uint32_t eNB_ue_s1ap_id;
1005
1006
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
1007
1008

  eNB_ue_s1ap_id = S1AP_UE_CTXT_MODIFICATION_REQ (msg_p).eNB_ue_s1ap_id;
1009
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id);
1010

1011
  if (ue_context_p == NULL) {
1012
1013
1014
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

1015
    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);
1016
1017
1018
1019
1020
1021
1022
1023

    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);
1024
  } else {
1025

1026
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
1027
1028
1029
    /* TODO parameters yet to process ... */
    {
      if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_UE_AMBR) {
1030
        //        S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).ue_ambr;
1031
      }
1032
1033
1034
    }

    if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP) {
1035
1036
1037
1038
      if (rrc_eNB_process_security (
            &ctxt,
            ue_context_p,
            &S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).security_capabilities)) {
1039
        /* transmit the new security parameters to UE */
1040
1041