rrc_eNB_S1AP.c 53.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

winckel's avatar
winckel committed
22
23
/*! \file rrc_eNB_S1AP.c
 * \brief rrc S1AP procedures for eNB
24
 * \author Navid Nikaein, Laurent Winckel, Sebastien ROUX, and Lionel GAUTHIER
25
 * \date 2013-2016
winckel's avatar
winckel committed
26
27
 * \version 1.0
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
28
 * \email: navid.nikaein@eurecom.fr
winckel's avatar
winckel committed
29
30
31
32
33
34
35
 */

#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"
36
37
# include "RRC/LITE/defs.h"
# include "rrc_eNB_UE_context.h"
winckel's avatar
winckel committed
38
# include "rrc_eNB_S1AP.h"
gauthier's avatar
gauthier committed
39
# include "enb_config.h"
winckel's avatar
winckel committed
40
41
42
43
44

# if defined(ENABLE_ITTI)
#   include "asn1_conversions.h"
#   include "intertask_interface.h"
#   include "pdcp.h"
45
#   include "pdcp_primitives.h"
winckel's avatar
winckel committed
46
47
48
49
50
#   include "s1ap_eNB.h"
# else
#   include "../../S1AP/s1ap_eNB.h"
# endif

51
52
53
#if defined(ENABLE_SECURITY)
#   include "UTIL/OSA/osa_defs.h"
#endif
54
#include "msc.h"
55

Cedric Roux's avatar
Cedric Roux committed
56
57
#include "UERadioAccessCapabilityInformation.h"

Cedric Roux's avatar
Cedric Roux committed
58
59
60
#include "gtpv1u_eNB_task.h"
#include "RRC/LITE/rrc_eNB_GTPV1U.h"

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

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

/* Masks for S1AP Integrity algorithms, EIA0 is always supported (not coded) */
69
70
static const uint16_t S1AP_INTEGRITY_EIA1_MASK = 0x8000;
static const uint16_t S1AP_INTEGRITY_EIA2_MASK = 0x4000;
71

Cedric Roux's avatar
Cedric Roux committed
72
#if defined(Rel10) || defined(Rel14)
73
74
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920
#else
75
#ifdef EXMIMO_IOT
76
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia2
77
#else
78
79
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_reserved
#endif
80
#endif
81

winckel's avatar
winckel committed
82
83


84

85
# if defined(ENABLE_ITTI)
86
87
88
89
90
91
92
93
94
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
{
95
96
  rrc_ue_s1ap_ids_t *result = NULL;
  rrc_ue_s1ap_ids_t *result2 = NULL;
97
98
99
100
101
102
103
104
105
  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) {
106
	  if (eNB_ue_s1ap_id > 0) {
107
108
109
110
111
112
113
114
115
116
	    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);
117
            if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
118
              LOG_E(S1AP, "[eNB %ld] Error while hashtable_insert in s1ap_id2_s1ap_ids eNB_ue_s1ap_id %"PRIu32"\n",
119
		    		  rrc_instance_pP - eNB_rrc_inst, eNB_ue_s1ap_id);
120
            }
121
122
123
124
125
		  }
		}
	  }
	}
  }
126
  return result;
127
}
128
129
130
131
132
133
134
135
//------------------------------------------------------------------------------
void
rrc_eNB_S1AP_remove_ue_ids(
  eNB_RRC_INST*              const rrc_instance_pP,
  struct rrc_ue_s1ap_ids_s* const ue_ids_pP
)
//------------------------------------------------------------------------------
{
136
137
138
  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;
139
140
141
  if (rrc_instance_pP == NULL) {
    LOG_E(RRC, "Bad RRC instance\n");
    return;
142
143
  }

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

149
150
151
152
  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);
153
154
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
155
156
157
158
159
160
161
	}
  }

  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);
162
163
	} else {
	  LOG_W(RRC, "S1AP removed entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
164
165
	}
  }
winckel's avatar
winckel committed
166
167
}

168
169
/*! \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
170
 *\param mod_id Instance ID of eNB.
171
 *\return the UE initial ID.
winckel's avatar
winckel committed
172
 */
173
174
175
176
177
178
//------------------------------------------------------------------------------
static uint16_t
get_next_ue_initial_id(
  const module_id_t mod_id
)
//------------------------------------------------------------------------------
179
{
180
181
  static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
  ue_initial_id[mod_id]++;
winckel's avatar
winckel committed
182

183
184
185
186
  /* 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
187

188
  return ue_initial_id[mod_id];
189
}
190

191
192


winckel's avatar
winckel committed
193

winckel's avatar
winckel committed
194
/*! \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
195
196
197
198
199
200
201
 *\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.
 */
202
203
204
205
206
207
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
)
208
{
209
210
211
212
213
214
215
216
  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
217

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

223
  return NULL;
winckel's avatar
winckel committed
224
225
}

226
227
228
229
230
/*! \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.
 */
Cedric Roux's avatar
Cedric Roux committed
231
static CipheringAlgorithm_r12_t rrc_eNB_select_ciphering(uint16_t algorithms)
232
233
{

234
//#warning "Forced   return SecurityAlgorithmConfig__cipheringAlgorithm_eea0, to be deleted in future"
Cedric Roux's avatar
Cedric Roux committed
235
  return CipheringAlgorithm_r12_eea0;
236

237
  if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) {
Cedric Roux's avatar
Cedric Roux committed
238
    return CipheringAlgorithm_r12_eea2;
239
240
241
  }

  if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) {
Cedric Roux's avatar
Cedric Roux committed
242
    return CipheringAlgorithm_r12_eea1;
243
244
  }

Cedric Roux's avatar
Cedric Roux committed
245
  return CipheringAlgorithm_r12_eea0;
246
247
248
249
250
251
252
}

/*! \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.
 */
253
254
255
static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
{

256
  if (algorithms & S1AP_INTEGRITY_EIA2_MASK) {
257
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
258
259
260
  }

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

  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.
 */
274
275
276
277
278
279
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
)
280
{
281
  boolean_t                                         changed = FALSE;
Cedric Roux's avatar
Cedric Roux committed
282
  CipheringAlgorithm_r12_t                          cipheringAlgorithm;
283
284
285
  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm;

  /* Save security parameters */
286
  ue_context_pP->ue_context.security_capabilities = *security_capabilities_pP;
287

288
289
  // translation
  LOG_D(RRC,
Cedric Roux's avatar
Cedric Roux committed
290
        "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %lu NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n",
291
292
293
294
295
        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);
296
  /* Select relevant algorithms */
297
  cipheringAlgorithm = rrc_eNB_select_ciphering (ue_context_pP->ue_context.security_capabilities.encryption_algorithms);
298

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

304
  integrityProtAlgorithm = rrc_eNB_select_integrity (ue_context_pP->ue_context.security_capabilities.integrity_algorithms);
305

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

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

  return changed;
}

322
/*! \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)
323
 *\brief save security key.
324
325
326
 *\param ctxt_pP         Running context.
 *\param ue_context_pP   UE context.
 *\param security_key_pP The security key received from S1AP.
327
 */
328
329
330
331
332
333
334
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
335
{
336
337
338
339
340
#if defined(ENABLE_SECURITY)
  char ascii_buffer[65];
  uint8_t i;

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

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

347
348
  ascii_buffer[2 * i] = '\0';

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

353

354
355
356
357
358
359
360
361
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
362
{
363
364
365

#if defined(ENABLE_SECURITY)

366

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

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

383
384
385
386
387
388
  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);
389
390
391

#define DEBUG_SECURITY 1

392
#if defined (DEBUG_SECURITY)
Cedric Roux's avatar
Cedric Roux committed
393
#undef msg
394
#define msg printf
395

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

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

    msg("\n");

    msg("\nKRRCenc:");

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

    msg("\n");

    msg("\nKRRCint:");

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

    msg("\n");

  }

425
#endif //DEBUG_SECURITY
426
427
  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);
428
429


430
  if (h_rc == HASH_TABLE_OK) {
431
    pdcp_config_set_security(
432
      ctxt_pP,
433
434
435
436
      pdcp_p,
      DCCH,
      DCCH+2,
      (send_security_mode_command == TRUE)  ?
437
438
439
      0 | (ue_context_pP->ue_context.integrity_algorithm << 4) :
      (ue_context_pP->ue_context.ciphering_algorithm )         |
      (ue_context_pP->ue_context.integrity_algorithm << 4),
440
441
442
      kRRCenc,
      kRRCint,
      kUPenc);
443
444
445
446
447
448
  } 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);
  }
449

450
#endif
451
452
}

453
454
455
456
457
458
459
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
460
{
461
  MessageDef      *msg_p         = NULL;
winckel's avatar
winckel committed
462
463
464
465
466
  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);
467
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
468

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

  MSC_LOG_TX_MESSAGE(
487
488
489
490
491
492
493
494
495
    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
496

497

winckel's avatar
winckel committed
498
499
500
  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;

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

505
506
507
508
509
510
511
512
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
513
{
winckel's avatar
winckel committed
514
515
516
517
518
#if defined(ENABLE_ITTI)
  {
    ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;

    if ((ulInformationTransfer->criticalExtensions.present == ULInformationTransfer__criticalExtensions_PR_c1)
519
520
521
522
    && (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
523
524
525
526
527
528
529
530
531
532
533
      /* 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);
534
      S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
winckel's avatar
winckel committed
535
536
537
      S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
      S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;

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

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

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

winckel's avatar
winckel committed
559
        if (ulInformationTransferR8->dedicatedInfoType.
560
561
562
563
564
565
566
567
568
        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
569
570
571
572
573
574
      }
    }
  }
#endif
}

575
576
577
578
579
580
581
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
582
{
583
  UECapabilityInformation_t *ueCapabilityInformation = &ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation;
Cedric Roux's avatar
Cedric Roux committed
584
585
586
587
588
589
590
591
592
  /* 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;
593
  }
Cedric Roux's avatar
Cedric Roux committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

  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);
620
621
}

622
623
624
625
626
627
628
629
//------------------------------------------------------------------------------
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
)
//------------------------------------------------------------------------------
630
{
winckel's avatar
winckel committed
631
632
#if defined(ENABLE_ITTI)
  {
633
634
    MessageDef*         message_p         = NULL;
    rrc_ue_s1ap_ids_t*  rrc_ue_s1ap_ids_p = NULL;
635
    hashtable_rc_t      h_rc;
winckel's avatar
winckel committed
636
637

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

640
641
642
643
644
645
646
647
    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;

648
649
650
    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);
651
    if (h_rc != HASH_TABLE_OK) {
652
653
      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);
654
    }
winckel's avatar
winckel committed
655
656

    /* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
657
    AssertFatal(ue_context_pP->ue_context.establishment_cause < RRC_CAUSE_LAST,
658
    "Establishment cause invalid (%jd/%d) for eNB %d!",
659
660
661
    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
662
663

    /* Forward NAS message */S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer =
664
    rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
winckel's avatar
winckel committed
665
666
667
668
669
670
    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;

671
      if (ue_context_pP->ue_context.Initialue_identity_s_TMSI.presence) {
winckel's avatar
winckel committed
672
        /* Fill s-TMSI */
673
        UE_S_TMSI* s_TMSI = &ue_context_pP->ue_context.Initialue_identity_s_TMSI;
winckel's avatar
winckel committed
674
675
676
677

        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;
678
        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
679
680
681
682
            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
683
684
685
686
687
      }

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

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

winckel's avatar
winckel committed
692
693
694
695
        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];
696
            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
697
698
699
                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
700
          }
701

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

gauthier's avatar
gauthier committed
720
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code     = BIT_STRING_to_uint8 (&r_mme->mmec);
winckel's avatar
winckel committed
721
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
gauthier's avatar
gauthier committed
722
723

        MSC_LOG_TX_MESSAGE(
724
725
726
727
728
729
730
731
          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
732

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

# if defined(ENABLE_ITTI)
756
757
758
759
760
761
762
763
764
//------------------------------------------------------------------------------
int
rrc_eNB_process_S1AP_DOWNLINK_NAS(
  MessageDef* msg_p,
  const char* msg_name,
  instance_t instance,
  mui_t* rrc_eNB_mui
)
//------------------------------------------------------------------------------
765
{
766
767
  uint16_t ue_initial_id;
  uint32_t eNB_ue_s1ap_id;
winckel's avatar
winckel committed
768
769
  uint32_t length;
  uint8_t *buffer;
770
771
  uint8_t srb_id; 
  
772
773
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
774
775
  ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id;
  eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
776
  ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
knopp's avatar
knopp committed
777
778


779
780
781
782
783
  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
784

785
  if (ue_context_p == NULL) {
gauthier's avatar
gauthier committed
786
787

    MSC_LOG_RX_MESSAGE(
788
789
790
791
792
793
794
795
      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
796

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

800
    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
801

winckel's avatar
winckel committed
802
    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_NON_DELIVERY_IND);
803
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
winckel's avatar
winckel committed
804
805
806
807
    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
808

gauthier's avatar
gauthier committed
809
810

    MSC_LOG_TX_MESSAGE(
811
812
813
814
815
816
817
818
      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
819

winckel's avatar
winckel committed
820
821
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
822
  } else {
823
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
824

knopp's avatar
knopp committed
825
826
827
    srb_id = ue_context_p->ue_context.Srb2.Srb_info.Srb_id;
  

828
    /* Is it the first income from S1AP ? */
829
830
    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;
831
    }
gauthier's avatar
gauthier committed
832
833

    MSC_LOG_RX_MESSAGE(
834
835
836
837
838
839
840
841
      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
842

843
844

    /* Create message for PDCP (DLInformationTransfer_t) */
845
846
847
848
    length = do_DLInformationTransfer (
               instance,
               &buffer,
               rrc_eNB_get_next_transaction_identifier (instance),
849
850
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
winckel's avatar
winckel committed
851

852
#ifdef RRC_MSG_PRINT
853
854
    int i=0;
    LOG_F(RRC,"[MSG] RRC DL Information Transfer\n");
855

856
    for (i = 0; i < length; i++) {
857
      LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
858
    }
859

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

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

888
889
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
890
891
  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;
892
893
894
  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
895

896
  if (ue_context_p == NULL) {
897
898
    /* 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
899

900
    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
901

902
903
    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
904

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

907
908
909
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
  } else {
winckel's avatar
winckel committed
910

911
912
    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
913

914
915
916
    /* Save e RAB information for later */
    {
      int i;
winckel's avatar
winckel committed
917

918
      memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
919
      ue_context_p->ue_context.nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs;
920
     
921
922
923
      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];
924

925

926
927
        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
928

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

937
938
939
940
941
942
943
      gtpv1u_create_s1u_tunnel(
        instance,
        &create_tunnel_req,
        &create_tunnel_resp);

      rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
          &ctxt,
944
          &create_tunnel_resp); 
945
      ue_context_p->ue_context.setup_e_rabs=ue_context_p->ue_context.nb_of_e_rabs;
946
947
948
949
    }

    /* TODO parameters yet to process ... */
    {
950
      //      S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_ambr;
951
    }
952

953
954
955
956
957
958
959
960
    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);
961

962
963
    {
      uint8_t send_security_mode_command = TRUE;
964

965
#ifndef EXMIMO_IOT
966

967
968
      if ((ue_context_p->ue_context.ciphering_algorithm == SecurityAlgorithmConfig__cipheringAlgorithm_eea0)
          && (ue_context_p->ue_context.integrity_algorithm == INTEGRITY_ALGORITHM_NONE)) {
969
970
971
        send_security_mode_command = FALSE;
      }

972
#endif
973
974
975
976
      rrc_pdcp_config_security(
        &ctxt,
        ue_context_p,
        send_security_mode_command);
977

978
      if (send_security_mode_command) {
979

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

997
/*------------------------------------------------------------------------------*/
998
999
int rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
1000
  uint32_t eNB_ue_s1ap_id;
1001
1002
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
1003
1004

  eNB_ue_s1ap_id = S1AP_UE_CTXT_MODIFICATION_REQ (msg_p).eNB_ue_s1ap_id;
1005
  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id);
1006

1007
  if (ue_context_p == NULL) {
1008
1009
1010
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

Cedric Roux's avatar
Cedric Roux committed
1011
    LOG_W(RRC, "[eNB %d] In S1AP_UE_CTXT_MODIFICATION_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n", instance, eNB_ue_s1ap_id);
1012
1013
1014
1015
1016
1017
1018
1019

    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);
1020
  } else {
1021

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

    if (S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).present & S1AP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP) {
1031
1032
1033
1034
      if (rrc_eNB_process_security (
            &ctxt,
            ue_context_p,
            &S1AP_UE_CTXT_MODIFICATION_REQ(msg_p).security_capabilities)) {