s1ap_eNB_handlers.c 62 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
 */

Cedric Roux's avatar
 
Cedric Roux committed
22 23
/*! \file s1ap_eNB_handlers.c
 * \brief s1ap messages handlers for eNB part
24 25 26
 * \author Sebastien ROUX and Navid Nikaein
 * \email navid.nikaein@eurecom.fr
 * \date 2013 - 2015
Cedric Roux's avatar
 
Cedric Roux committed
27 28 29 30 31
 * \version 0.1
 */

#include <stdint.h>

32 33
#include "intertask_interface.h"

34 35
#include "asn1_conversions.h"

Cedric Roux's avatar
 
Cedric Roux committed
36
#include "s1ap_common.h"
37 38
// #include "s1ap_eNB.h"
#include "s1ap_eNB_defs.h"
Cedric Roux's avatar
 
Cedric Roux committed
39 40 41 42 43 44
#include "s1ap_eNB_handlers.h"
#include "s1ap_eNB_decoder.h"

#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_trace.h"
#include "s1ap_eNB_nas_procedures.h"
45
#include "s1ap_eNB_management_procedures.h"
Cedric Roux's avatar
 
Cedric Roux committed
46

47
#include "s1ap_eNB_default_values.h"
Cedric Roux's avatar
 
Cedric Roux committed
48

49
#include "assertions.h"
Cedric Roux's avatar
 
Cedric Roux committed
50
#include "conversions.h"
Raymond Knopp's avatar
Raymond Knopp committed
51
#include "msc.h"
Cedric Roux's avatar
 
Cedric Roux committed
52

53 54 55
static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
56
                                      S1AP_S1AP_PDU_t       *pdu);
Cedric Roux's avatar
Cedric Roux committed
57
static
58 59
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
60
                                     S1AP_S1AP_PDU_t       *pdu);
61

62 63
static
int s1ap_eNB_handle_error_indication(uint32_t               assoc_id,
64 65
                                     uint32_t               stream,
                                     S1AP_S1AP_PDU_t       *pdu);
66

67 68
static
int s1ap_eNB_handle_initial_context_request(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
69 70
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
Cedric Roux's avatar
 
Cedric Roux committed
71

72
static
Lionel Gauthier's avatar
 
Lionel Gauthier committed
73
int s1ap_eNB_handle_ue_context_release_command(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
74 75
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
76 77 78

static
int s1ap_eNB_handle_e_rab_setup_request(uint32_t               assoc_id,
79 80
                                        uint32_t               stream,
                                        S1AP_S1AP_PDU_t       *pdu);
81

82 83
static
int s1ap_eNB_handle_paging(uint32_t               assoc_id,
84 85
                           uint32_t               stream,
                           S1AP_S1AP_PDU_t       *pdu);
86 87 88

static
int s1ap_eNB_handle_e_rab_modify_request(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
89 90
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
91 92 93

static
int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
94 95
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
96

Cedric Roux's avatar
 
Cedric Roux committed
97 98
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = {
99 100 101 102 103
  { 0, 0, 0 }, /* HandoverPreparation */
  { 0, 0, 0 }, /* HandoverResourceAllocation */
  { 0, 0, 0 }, /* HandoverNotification */
  { 0, 0, 0 }, /* PathSwitchRequest */
  { 0, 0, 0 }, /* HandoverCancel */
104
  { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
105 106
  { s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */
  { s1ap_eNB_handle_e_rab_release_command, 0, 0 }, /* E_RABRelease */
107 108
  { 0, 0, 0 }, /* E_RABReleaseIndication */
  { s1ap_eNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */
109
  { s1ap_eNB_handle_paging, 0, 0 }, /* Paging */
110 111 112 113
  { s1ap_eNB_handle_nas_downlink, 0, 0 }, /* downlinkNASTransport */
  { 0, 0, 0 }, /* initialUEMessage */
  { 0, 0, 0 }, /* uplinkNASTransport */
  { 0, 0, 0 }, /* Reset */
114
  { s1ap_eNB_handle_error_indication, 0, 0 }, /* ErrorIndication */
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
  { 0, 0, 0 }, /* NASNonDeliveryIndication */
  { 0, s1ap_eNB_handle_s1_setup_response, s1ap_eNB_handle_s1_setup_failure }, /* S1Setup */
  { 0, 0, 0 }, /* UEContextReleaseRequest */
  { 0, 0, 0 }, /* DownlinkS1cdma2000tunneling */
  { 0, 0, 0 }, /* UplinkS1cdma2000tunneling */
  { 0, 0, 0 }, /* UEContextModification */
  { 0, 0, 0 }, /* UECapabilityInfoIndication */
  { s1ap_eNB_handle_ue_context_release_command, 0, 0 }, /* UEContextRelease */
  { 0, 0, 0 }, /* eNBStatusTransfer */
  { 0, 0, 0 }, /* MMEStatusTransfer */
  { s1ap_eNB_handle_deactivate_trace, 0, 0 }, /* DeactivateTrace */
  { s1ap_eNB_handle_trace_start, 0, 0 }, /* TraceStart */
  { 0, 0, 0 }, /* TraceFailureIndication */
  { 0, 0, 0 }, /* ENBConfigurationUpdate */
  { 0, 0, 0 }, /* MMEConfigurationUpdate */
  { 0, 0, 0 }, /* LocationReportingControl */
  { 0, 0, 0 }, /* LocationReportingFailureIndication */
  { 0, 0, 0 }, /* LocationReport */
  { 0, 0, 0 }, /* OverloadStart */
  { 0, 0, 0 }, /* OverloadStop */
  { 0, 0, 0 }, /* WriteReplaceWarning */
  { 0, 0, 0 }, /* eNBDirectInformationTransfer */
  { 0, 0, 0 }, /* MMEDirectInformationTransfer */
  { 0, 0, 0 }, /* PrivateMessage */
  { 0, 0, 0 }, /* eNBConfigurationTransfer */
  { 0, 0, 0 }, /* MMEConfigurationTransfer */
  { 0, 0, 0 }, /* CellTrafficTrace */
142
#if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0))
143 144 145 146 147
  { 0, 0, 0 }, /* Kill */
  { 0, 0, 0 }, /* DownlinkUEAssociatedLPPaTransport  */
  { 0, 0, 0 }, /* UplinkUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* DownlinkNonUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* UplinkNonUEAssociatedLPPaTransport */
148
#endif /* #if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0)) */
Cedric Roux's avatar
 
Cedric Roux committed
149
};
150
char *s1ap_direction2String(int s1ap_dir) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
151 152 153 154 155 156 157
  static char *s1ap_direction_String[] = {
    "", /* Nothing */
    "Originating message", /* originating message */
    "Successfull outcome", /* successfull outcome */
    "UnSuccessfull outcome", /* successfull outcome */
  };
  return(s1ap_direction_String[s1ap_dir]);
158
}
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
159
void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown) {
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  if (sctp_shutdown) {
    /* A previously connected MME has been shutdown */

    /* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated MME */
    if (mme_desc_p->state == S1AP_ENB_STATE_CONNECTED) {
      mme_desc_p->state = S1AP_ENB_STATE_DISCONNECTED;

      if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb > 0) {
        /* Decrease associated MME number */
        mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb --;
      }

      /* If there are no more associated MME, inform eNB app */
      if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb == 0) {
        MessageDef                 *message_p;
        message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DEREGISTERED_ENB_IND);
        S1AP_DEREGISTERED_ENB_IND(message_p).nb_mme = 0;
        itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
      }
    }
  } else {
    /* Check that at least one setup message is pending */
    DevCheck(mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0, mme_desc_p->s1ap_eNB_instance->instance,
             mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb, 0);

    if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0) {
      /* Decrease pending messages number */
      mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb --;
    }

    /* If there are no more pending messages, inform eNB app */
    if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb == 0) {
      MessageDef                 *message_p;
      message_p = itti_alloc_new_message(TASK_S1AP, S1AP_REGISTER_ENB_CNF);
      S1AP_REGISTER_ENB_CNF(message_p).nb_mme = mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb;
      itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
196
    }
197
  }
198 199
}

200
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
201
                            const uint8_t *const data, const uint32_t data_length) {
202 203
  S1AP_S1AP_PDU_t pdu;
  int ret;
204
  DevAssert(data != NULL);
205
  memset(&pdu, 0, sizeof(pdu));
206

207
  if (s1ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
208 209 210 211 212
    S1AP_ERROR("Failed to decode PDU\n");
    return -1;
  }

  /* Checking procedure Code and direction of message */
213
  if (pdu.choice.initiatingMessage.procedureCode > sizeof(messages_callback) / (3 * sizeof(
214
        s1ap_message_decoded_callback))
215
      || (pdu.present > S1AP_S1AP_PDU_PR_unsuccessfulOutcome)) {
Cedric Roux's avatar
Cedric Roux committed
216
    S1AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
217 218
               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_S1AP_PDU, &pdu);
219 220 221 222 223 224
    return -1;
  }

  /* No handler present.
   * This can mean not implemented or no procedure for eNB (wrong direction).
   */
225
  if (messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
Cedric Roux's avatar
Cedric Roux committed
226
    S1AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
227
               assoc_id, pdu.choice.initiatingMessage.procedureCode,
228
               s1ap_direction2String(pdu.present - 1));
229
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_S1AP_PDU, &pdu);
230 231 232 233
    return -1;
  }

  /* Calling the right handler */
234 235 236 237
  ret = (*messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
        (assoc_id, stream, &pdu);
  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_S1AP_PDU, &pdu);
  return ret;
Cedric Roux's avatar
 
Cedric Roux committed
238 239
}

Cedric Roux's avatar
Cedric Roux committed
240
static
241 242
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
243
                                     S1AP_S1AP_PDU_t       *pdu) {
244 245
  S1AP_S1SetupFailure_t      *container;
  S1AP_S1SetupFailureIEs_t   *ie;
246
  s1ap_eNB_mme_data_t        *mme_desc_p;
247 248
  DevAssert(pdu != NULL);
  container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure;
249

250 251 252 253 254
  /* S1 Setup Failure == Non UE-related procedure -> stream 0 */
  if (stream != 0) {
    S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
              assoc_id, stream);
  }
255

256 257 258 259 260
  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
               "MME context\n", assoc_id);
    return -1;
  }
261

262 263 264 265 266
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_Cause, true);

  if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) &&
      (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) {
267 268 269 270
    S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n");
  } else {
    S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
  }
271

272 273 274
  mme_desc_p->state = S1AP_ENB_STATE_WAITING;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);
  return 0;
275 276 277 278 279
}

static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
280
                                      S1AP_S1AP_PDU_t       *pdu) {
281 282
  S1AP_S1SetupResponse_t    *container;
  S1AP_S1SetupResponseIEs_t *ie;
283 284
  s1ap_eNB_mme_data_t       *mme_desc_p;
  int i;
285 286
  DevAssert(pdu != NULL);
  container = &pdu->choice.successfulOutcome.value.choice.S1SetupResponse;
287 288 289 290 291 292 293 294 295 296 297 298 299 300

  /* S1 Setup Response == Non UE-related procedure -> stream 0 */
  if (stream != 0) {
    S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n",
               assoc_id, stream);
    return -1;
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
               "MME context\n", assoc_id);
    return -1;
  }

301 302
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true);
303 304 305
  /* The list of served gummei can contain at most 8 elements.
   * LTE related gummei is the first element in the list, i.e with an id of 0.
   */
306 307 308
  S1AP_DEBUG("servedGUMMEIs.list.count %d\n", ie->value.choice.ServedGUMMEIs.list.count);
  DevAssert(ie->value.choice.ServedGUMMEIs.list.count > 0);
  DevAssert(ie->value.choice.ServedGUMMEIs.list.count <= S1AP_maxnoofRATs);
309

310 311 312
  for (i = 0; i < ie->value.choice.ServedGUMMEIs.list.count; i++) {
    S1AP_ServedGUMMEIsItem_t *gummei_item_p;
    struct served_gummei_s   *new_gummei_p;
313
    int j;
314
    gummei_item_p = ie->value.choice.ServedGUMMEIs.list.array[i];
315 316 317 318
    new_gummei_p = calloc(1, sizeof(struct served_gummei_s));
    STAILQ_INIT(&new_gummei_p->served_plmns);
    STAILQ_INIT(&new_gummei_p->served_group_ids);
    STAILQ_INIT(&new_gummei_p->mme_codes);
319 320
    S1AP_DEBUG("servedPLMNs.list.count %d\n", gummei_item_p->servedPLMNs.list.count);

321
    for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) {
322
      S1AP_PLMNidentity_t *plmn_identity_p;
323
      struct plmn_identity_s *new_plmn_identity_p;
navid's avatar
navid committed
324
      plmn_identity_p = gummei_item_p->servedPLMNs.list.array[j];
325 326 327 328 329 330
      new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s));
      TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc,
                      new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length);
      STAILQ_INSERT_TAIL(&new_gummei_p->served_plmns, new_plmn_identity_p, next);
      new_gummei_p->nb_served_plmns++;
    }
Cedric Roux's avatar
 
Cedric Roux committed
331

332
    for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) {
333
      S1AP_MME_Group_ID_t           *mme_group_id_p;
334
      struct served_group_id_s *new_group_id_p;
navid's avatar
navid committed
335
      mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[j];
336 337 338 339
      new_group_id_p = calloc(1, sizeof(struct served_group_id_s));
      OCTET_STRING_TO_INT16(mme_group_id_p, new_group_id_p->mme_group_id);
      STAILQ_INSERT_TAIL(&new_gummei_p->served_group_ids, new_group_id_p, next);
      new_gummei_p->nb_group_id++;
Cedric Roux's avatar
 
Cedric Roux committed
340 341
    }

342
    for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) {
343
      S1AP_MME_Code_t        *mme_code_p;
344
      struct mme_code_s *new_mme_code_p;
navid's avatar
navid committed
345
      mme_code_p = gummei_item_p->servedMMECs.list.array[j];
346 347 348 349
      new_mme_code_p = calloc(1, sizeof(struct mme_code_s));
      OCTET_STRING_TO_INT8(mme_code_p, new_mme_code_p->mme_code);
      STAILQ_INSERT_TAIL(&new_gummei_p->mme_codes, new_mme_code_p, next);
      new_gummei_p->nb_mme_code++;
Cedric Roux's avatar
 
Cedric Roux committed
350
    }
351 352 353 354 355

    STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next);
  }

  /* Set the capacity of this MME */
356 357 358
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true);
  mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity;
359
  /* Optionaly set the mme name */
360 361
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MMEname, false);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
362

363 364 365 366
  if (ie) {
    mme_desc_p->mme_name = calloc(ie->value.choice.MMEname.size + 1, sizeof(char));
    memcpy(mme_desc_p->mme_name, ie->value.choice.MMEname.buf,
           ie->value.choice.MMEname.size);
367
    /* Convert the mme name to a printable string */
368
    mme_desc_p->mme_name[ie->value.choice.MMEname.size] = '\0';
369 370 371 372 373 374 375 376 377
  }

  /* The association is now ready as eNB and MME know parameters of each other.
   * Mark the association as UP to enable UE contexts creation.
   */
  mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
  mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
378 379
}

380 381

static
382 383
int s1ap_eNB_handle_error_indication(uint32_t         assoc_id,
                                     uint32_t         stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
384
                                     S1AP_S1AP_PDU_t *pdu) {
385 386
  S1AP_ErrorIndication_t    *container;
  S1AP_ErrorIndicationIEs_t *ie;
387
  s1ap_eNB_mme_data_t        *mme_desc_p;
388 389
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.ErrorIndication;
390 391 392 393 394 395 396 397 398 399 400 401

  /* S1 Setup Failure == Non UE-related procedure -> stream 0 */
  if (stream != 0) {
    S1AP_WARN("[SCTP %d] Received s1 Error indication on stream != 0 (%d)\n",
              assoc_id, stream);
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 Error indication for non existing "
               "MME context\n", assoc_id);
    return -1;
  }
402 403 404 405 406 407 408

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_ErrorIndicationIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, false);

  /* optional */
  if (!ie) {
    S1AP_WARN("Received S1 Error indication MME UE S1AP ID 0x%lx\n", ie->value.choice.MME_UE_S1AP_ID);
409
  }
410 411 412 413 414 415 416

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_ErrorIndicationIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, false);

  /* optional */
  if (!ie) {
    S1AP_WARN("Received S1 Error indication eNB UE S1AP ID 0x%lx\n", ie->value.choice.ENB_UE_S1AP_ID);
417 418
  }

419 420 421 422 423 424 425 426 427 428 429 430 431 432
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_ErrorIndicationIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_Cause, false);

  /* optional */
  if (ie) {
    switch(ie->value.choice.Cause.present) {
      case S1AP_Cause_PR_NOTHING:
        S1AP_WARN("Received S1 Error indication cause NOTHING\n");
        break;

      case S1AP_Cause_PR_radioNetwork:
        switch (ie->value.choice.Cause.choice.radioNetwork) {
          case S1AP_CauseRadioNetwork_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unspecified\n");
433
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
434

435 436
          case S1AP_CauseRadioNetwork_tx2relocoverall_expiry:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_tx2relocoverall_expiry\n");
437
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
438

439 440
          case S1AP_CauseRadioNetwork_successful_handover:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_successful_handover\n");
441
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
442

443 444
          case S1AP_CauseRadioNetwork_release_due_to_eutran_generated_reason:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
445
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
446

447 448
          case S1AP_CauseRadioNetwork_handover_cancelled:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_handover_cancelled\n");
449
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
450

451 452
          case S1AP_CauseRadioNetwork_partial_handover:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_partial_handover\n");
453
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
454

455 456
          case S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
457
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
458

459 460
          case S1AP_CauseRadioNetwork_ho_target_not_allowed:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_ho_target_not_allowed\n");
461
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
462

463 464
          case S1AP_CauseRadioNetwork_tS1relocoverall_expiry:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_tS1relocoverall_expiry\n");
465
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
466

467 468
          case S1AP_CauseRadioNetwork_tS1relocprep_expiry:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_tS1relocprep_expiry\n");
469
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
470

471 472
          case S1AP_CauseRadioNetwork_cell_not_available:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_cell_not_available\n");
473
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
474

475 476
          case S1AP_CauseRadioNetwork_unknown_targetID:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unknown_targetID\n");
477
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
478

479 480
          case S1AP_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
481
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
482

483 484
          case S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
485
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
486

487 488
          case S1AP_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
489
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
490

491 492
          case S1AP_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
493
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
494

495 496
          case S1AP_CauseRadioNetwork_handover_desirable_for_radio_reason:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
497
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
498

499 500
          case S1AP_CauseRadioNetwork_time_critical_handover:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_time_critical_handover\n");
501
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
502

503 504
          case S1AP_CauseRadioNetwork_resource_optimisation_handover:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_resource_optimisation_handover\n");
505
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
506

507 508
          case S1AP_CauseRadioNetwork_reduce_load_in_serving_cell:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_reduce_load_in_serving_cell\n");
509
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
510

511 512
          case S1AP_CauseRadioNetwork_user_inactivity:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_user_inactivity\n");
513
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
514

515 516
          case S1AP_CauseRadioNetwork_radio_connection_with_ue_lost:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_radio_connection_with_ue_lost\n");
517
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
518

519 520
          case S1AP_CauseRadioNetwork_load_balancing_tau_required:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_load_balancing_tau_required\n");
521
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
522

523 524
          case S1AP_CauseRadioNetwork_cs_fallback_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_cs_fallback_triggered\n");
525
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
526

527 528
          case S1AP_CauseRadioNetwork_ue_not_available_for_ps_service:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_ue_not_available_for_ps_service\n");
529
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
530

531 532
          case S1AP_CauseRadioNetwork_radio_resources_not_available:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_radio_resources_not_available\n");
533
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
534

535 536
          case S1AP_CauseRadioNetwork_failure_in_radio_interface_procedure:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
537
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
538

539 540
          case S1AP_CauseRadioNetwork_invalid_qos_combination:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_invals1ap_id_qos_combination\n");
541
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
542

543 544
          case S1AP_CauseRadioNetwork_interrat_redirection:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_interrat_redirection\n");
545
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
546

547 548
          case S1AP_CauseRadioNetwork_interaction_with_other_procedure:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_interaction_with_other_procedure\n");
549
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
550

551 552
          case S1AP_CauseRadioNetwork_unknown_E_RAB_ID:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_unknown_E_RAB_ID\n");
553
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
554

555 556
          case S1AP_CauseRadioNetwork_multiple_E_RAB_ID_instances:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
557
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
558

559 560
          case S1AP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
561
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
562

563 564
          case S1AP_CauseRadioNetwork_s1_intra_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
565
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
566

567 568
          case S1AP_CauseRadioNetwork_s1_inter_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
569
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
570

571 572
          case S1AP_CauseRadioNetwork_x2_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_x2_handover_triggered\n");
573
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
574

575 576
          case S1AP_CauseRadioNetwork_redirection_towards_1xRTT:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_redirection_towards_1xRTT\n");
577
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
578

579 580
          case S1AP_CauseRadioNetwork_not_supported_QCI_value:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_not_supported_QCI_value\n");
581
            break;
582
#if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0))
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
583

584 585
          case S1AP_CauseRadioNetwork_invalid_CSG_Id:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
586
            break;
587 588 589
#endif /* #if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0)) */

          default:
590
            S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
591
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
592

593
        break;
594

595 596 597 598
      case S1AP_Cause_PR_transport:
        switch (ie->value.choice.Cause.choice.transport) {
          case S1AP_CauseTransport_transport_resource_unavailable:
            S1AP_WARN("Received S1 Error indication S1AP_CauseTransport_transport_resource_unavailable\n");
599
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
600

601 602
          case S1AP_CauseTransport_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseTransport_unspecified\n");
603
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
604

605
          default:
606
            S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
607
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
608

609
        break;
610

611 612 613 614
      case S1AP_Cause_PR_nas:
        switch (ie->value.choice.Cause.choice.nas) {
          case S1AP_CauseNas_normal_release:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_normal_release\n");
615
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
616

617 618
          case S1AP_CauseNas_authentication_failure:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_authentication_failure\n");
619
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
620

621 622
          case S1AP_CauseNas_detach:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_detach\n");
623
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
624

625 626
          case S1AP_CauseNas_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_unspecified\n");
627
            break;
628
#if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0))
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
629

630 631
          case S1AP_CauseNas_csg_subscription_expiry:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_csg_subscription_expiry\n");
632
            break;
633
#endif /* #if (S1AP_VERSION >= MAKE_VERSION(9, 0, 0)) */
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
634

635
          default:
636
            S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
637 638 639
        }

        break;
640

641 642 643 644
      case S1AP_Cause_PR_protocol:
        switch (ie->value.choice.Cause.choice.protocol) {
          case S1AP_CauseProtocol_transfer_syntax_error:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_transfer_syntax_error\n");
645
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
646

647 648
          case S1AP_CauseProtocol_abstract_syntax_error_reject:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_abstract_syntax_error_reject\n");
649
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
650

651 652
          case S1AP_CauseProtocol_abstract_syntax_error_ignore_and_notify:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
653
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
654

655 656
          case S1AP_CauseProtocol_message_not_compatible_with_receiver_state:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_message_not_compatible_with_receiver_state\n");
657
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
658

659 660
          case S1AP_CauseProtocol_semantic_error:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_semantic_error\n");
661
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
662

663 664
          case S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
665
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
666

667 668
          case S1AP_CauseProtocol_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_unspecified\n");
669
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
670

671
          default:
672
            S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
673
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
674

675
        break;
676

677 678 679 680 681
      case S1AP_Cause_PR_misc:
        switch (ie->value.choice.Cause.choice.protocol) {
          case S1AP_CauseMisc_control_processing_overload:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_control_processing_overload\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
682

683 684 685
          case S1AP_CauseMisc_not_enough_user_plane_processing_resources:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_not_enough_user_plane_processing_resources\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
686

687 688 689
          case S1AP_CauseMisc_hardware_failure:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_hardware_failure\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
690

691 692 693
          case S1AP_CauseMisc_om_intervention:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_om_intervention\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
694

695 696 697
          case S1AP_CauseMisc_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_unspecified\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
698

699 700
          case S1AP_CauseMisc_unknown_PLMN:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_unknown_PLMN\n");
701
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
702

703 704 705
          default:
            S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
706

707
        break;
708 709
    }
  }
710 711 712 713 714

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_ErrorIndicationIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);

  if (ie) {
715 716 717
    // TODO continue
  }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
718
  // TODO continue
719 720 721 722
  return 0;
}


723
static
724
int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
725
    uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
726
    S1AP_S1AP_PDU_t       *pdu) {
727 728 729 730
  int i;
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
731 732 733 734 735 736
  S1AP_InitialContextSetupRequest_t    *container;
  S1AP_InitialContextSetupRequestIEs_t *ie;
  S1AP_ENB_UE_S1AP_ID_t    enb_ue_s1ap_id;
  S1AP_MME_UE_S1AP_ID_t    mme_ue_s1ap_id;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.InitialContextSetupRequest;
Cedric Roux's avatar
 
Cedric Roux committed
737

738 739 740 741 742
  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
               "existing MME context\n", assoc_id);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
743

744 745 746 747 748 749 750 751 752
  /* id-MME-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
  mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  /* id-eNB-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
  enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;

753
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
754
                   enb_ue_s1ap_id)) == NULL) {
755
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
Cedric Roux's avatar
Cedric Roux committed
756
               "existing UE context 0x%06lx\n", assoc_id,
757
               enb_ue_s1ap_id);
758 759
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
760

761
  /* Initial context request = UE-related procedure -> stream != 0 */
762 763 764
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
765 766
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
767

768
  ue_desc_p->rx_stream = stream;
769
  ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
770 771 772 773
  message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ);
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
  ue_desc_p->ue_initial_id = 0;
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
774 775 776 777 778 779 780 781 782 783 784 785
  /* id-uEaggregateMaximumBitrate */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, true);
  asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL),
                    &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul));
  asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL),
                    &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl));
  /* id-E-RABToBeSetupListCtxtSUReq */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true);
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_e_rabs =
    ie->value.choice.E_RABToBeSetupListCtxtSUReq.list.count;
786

787 788 789
  for (i = 0; i < ie->value.choice.E_RABToBeSetupListCtxtSUReq.list.count; i++) {
    S1AP_E_RABToBeSetupItemCtxtSUReq_t *item_p;
    item_p = &(((S1AP_E_RABToBeSetupItemCtxtSUReqIEs_t *)ie->value.choice.E_RABToBeSetupListCtxtSUReq.list.array[i])->value.choice.E_RABToBeSetupItemCtxtSUReq);
790
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].e_rab_id = item_p->e_RAB_ID;
791

792 793 794 795 796 797
    if (item_p->nAS_PDU != NULL) {
      /* Only copy NAS pdu if present */
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = item_p->nAS_PDU->size;
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer =
        malloc(sizeof(uint8_t) * item_p->nAS_PDU->size);
      memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer,
798
             item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
799
      S1AP_DEBUG("Received NAS message with the E_RAB setup procedure\n");
800 801 802 803
    } else {
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = 0;
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer = NULL;
    }
804

805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
    /* Set the transport layer address */
    memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].sgw_addr.buffer,
           item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size);
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].sgw_addr.length =
      item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
    /* GTP tunnel endpoint ID */
    OCTET_STRING_TO_INT32(&item_p->gTP_TEID, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].gtp_teid);
    /* Set the QOS informations */
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI;
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.allocation_retention_priority.priority_level =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel;
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability;
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability;
  }
821

822 823 824 825 826 827 828 829 830 831 832 833
  /* id-UESecurityCapabilities */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UESecurityCapabilities, true);
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms =
    BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
    BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
  /* id-SecurityKey : Copy the security key */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_SecurityKey, true);
  memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
         ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
834 835
  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
836
}
837 838 839


static
840
int s1ap_eNB_handle_ue_context_release_command(uint32_t   assoc_id,
841
    uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
842
    S1AP_S1AP_PDU_t       *pdu) {
843 844 845
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
846 847 848 849 850 851
  S1AP_MME_UE_S1AP_ID_t  mme_ue_s1ap_id;
  S1AP_ENB_UE_S1AP_ID_t  enb_ue_s1ap_id;
  S1AP_UEContextReleaseCommand_t     *container;
  S1AP_UEContextReleaseCommand_IEs_t *ie;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.UEContextReleaseCommand;
852 853 854 855 856 857

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received UE context release command for non "
               "existing MME context\n", assoc_id);
    return -1;
  }
858

859 860 861 862 863 864 865 866 867 868 869 870
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true);

  switch (ie->value.choice.UE_S1AP_IDs.present) {
    case S1AP_UE_S1AP_IDs_PR_uE_S1AP_ID_pair:
      enb_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
      mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
      MSC_LOG_RX_MESSAGE(
        MSC_S1AP_ENB,
        MSC_S1AP_MME,
        NULL,0,
        "0 UEContextRelease/%s eNB_ue_s1ap_id "S1AP_UE_ID_FMT" mme_ue_s1ap_id "S1AP_UE_ID_FMT" len %u",
871
        s1ap_direction2String(pdu->present - 1),
872 873 874 875
        enb_ue_s1ap_id,
        mme_ue_s1ap_id);

      if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
876
                       enb_ue_s1ap_id)) == NULL) {
877 878 879 880 881 882 883 884 885 886 887 888 889
        S1AP_ERROR("[SCTP %d] Received UE context release command for non "
                   "existing UE context 0x%06lx\n",
                   assoc_id,
                   enb_ue_s1ap_id);
        return -1;
      } else {
        MSC_LOG_TX_MESSAGE(
          MSC_S1AP_ENB,
          MSC_RRC_ENB,
          NULL,0,
          "0 S1AP_UE_CONTEXT_RELEASE_COMMAND/%d eNB_ue_s1ap_id "S1AP_UE_ID_FMT" ",
          enb_ue_s1ap_id);
        message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND);
890 891

        if (ue_desc_p->mme_ue_s1ap_id == 0) { // case of Detach Request and switch off from RRC_IDLE mode
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
892
          ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
893 894
        }

895 896 897 898
        S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
        itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
        return 0;
      }
899

900
      break;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
901

902
    //#warning "TODO mapping mme_ue_s1ap_id  enb_ue_s1ap_id?"
903

904 905 906 907
    case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID:
      mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
      S1AP_ERROR("TO DO mapping mme_ue_s1ap_id  enb_ue_s1ap_id");
      (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */
908

909 910 911 912
    case S1AP_UE_S1AP_IDs_PR_NOTHING:
    default:
      S1AP_ERROR("S1AP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements");
      return -1;
913
  }
914 915 916 917

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_Cause, true);
  /* TBD */
918 919
}

920
static
921 922
int s1ap_eNB_handle_e_rab_setup_request(uint32_t         assoc_id,
                                        uint32_t         stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
923
                                        S1AP_S1AP_PDU_t *pdu) {
924
  int i;
925 926 927 928 929 930 931 932 933
  S1AP_MME_UE_S1AP_ID_t         mme_ue_s1ap_id;
  S1AP_ENB_UE_S1AP_ID_t         enb_ue_s1ap_id;
  s1ap_eNB_mme_data_t          *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t        *ue_desc_p        = NULL;
  MessageDef                   *message_p        = NULL;
  S1AP_E_RABSetupRequest_t     *container;
  S1AP_E_RABSetupRequestIEs_t  *ie;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest;
934 935 936 937 938 939 940

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
               "existing MME context\n", assoc_id);
    return -1;
  }

941 942 943 944 945 946 947 948 949
  /* id-MME-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
  mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  /* id-eNB-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
  enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;

950
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
951
                   enb_ue_s1ap_id)) == NULL) {
952
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
Cedric Roux's avatar
Cedric Roux committed
953
               "existing UE context 0x%06lx\n", assoc_id,
954
               enb_ue_s1ap_id);
955 956 957 958 959 960 961 962 963 964 965 966
    return -1;
  }

  /* Initial context request = UE-related procedure -> stream != 0 */
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
    return -1;
  }

  ue_desc_p->rx_stream = stream;

967 968 969
  if ( ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) {
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
              ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id);
970
  }
971

972 973
  message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_SETUP_REQ);
  S1AP_E_RAB_SETUP_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
974 975 976 977 978 979 980 981 982 983
  S1AP_E_RAB_SETUP_REQ(message_p).mme_ue_s1ap_id  = mme_ue_s1ap_id;
  S1AP_E_RAB_SETUP_REQ(message_p).eNB_ue_s1ap_id  = enb_ue_s1ap_id;
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeSetupListBearerSUReq, true);
  S1AP_E_RAB_SETUP_REQ(message_p).nb_e_rabs_tosetup =
    ie->value.choice.E_RABToBeSetupListBearerSUReq.list.count;

  for (i = 0; i < ie->value.choice.E_RABToBeSetupListBearerSUReq.list.count; i++) {
    S1AP_E_RABToBeSetupItemBearerSUReq_t *item_p;
    item_p = &(((S1AP_E_RABToBeSetupItemBearerSUReqIEs_t *)ie->value.choice.E_RABToBeSetupListBearerSUReq.list.array[i])->value.choice.E_RABToBeSetupItemBearerSUReq);
984 985 986 987 988 989 990
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].e_rab_id = item_p->e_RAB_ID;

    // check for the NAS PDU
    if (item_p->nAS_PDU.size > 0 ) {
      S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = item_p->nAS_PDU.size;
      S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size);
      memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer,
991
             item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
992
      // S1AP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]);
993 994 995 996
    } else {
      S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0;
      S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL;
      S1AP_WARN("NAS PDU is not provided, generate a E_RAB_SETUP Failure (TBD) back to MME \n");
997
      // return -1;
998 999 1000 1001 1002 1003 1004
    }

    /* Set the transport layer address */
    memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer,
           item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size);
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.length =
      item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
1005 1006 1007 1008
    /* S1AP_INFO("sgw addr %s  len: %d (size %d, index %d)\n",
                 S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer,
                 S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.length,
                 item_p->transportLayerAddress.size, i);
1009
    */
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
    /* GTP tunnel endpoint ID */
    OCTET_STRING_TO_INT32(&item_p->gTP_TEID, S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].gtp_teid);
    /* Set the QOS informations */
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI;
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.allocation_retention_priority.priority_level =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel;
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.allocation_retention_priority.pre_emp_capability =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability;
    S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.allocation_retention_priority.pre_emp_vulnerability =
      item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability;
  }

  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  return 0;
}

1026 1027
static
int s1ap_eNB_handle_paging(uint32_t               assoc_id,
1028
                           uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1029
                           S1AP_S1AP_PDU_t       *pdu) {
1030 1031 1032
  s1ap_eNB_mme_data_t   *mme_desc_p        = NULL;
  s1ap_eNB_instance_t   *s1ap_eNB_instance = NULL;
  MessageDef            *message_p         = NULL;
1033 1034 1035 1036
  S1AP_Paging_t         *container;
  S1AP_PagingIEs_t      *ie;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.Paging;
1037 1038 1039 1040 1041
  // received Paging Message from MME
  S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id);

  /* Paging procedure -> stream != 0 */
  if (stream == 0) {
1042
    LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1043
          assoc_id, stream);
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
    return -1;
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received Paging for non "
               "existing MME context\n", assoc_id);
    return -1;
  }

  s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1054

1055 1056 1057 1058 1059 1060 1061
  if (s1ap_eNB_instance == NULL) {
    S1AP_ERROR("[SCTP %d] Received Paging for non existing MME context : s1ap_eNB_instance is NULL\n",
               assoc_id);
    return -1;
  }

  message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PAGING_IND);
1062 1063 1064 1065 1066
  /* convert S1AP_PagingIEs_t to s1ap_paging_ind_t */
  /* id-UEIdentityIndexValue : convert UE Identity Index value */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UEIdentityIndexValue, true);
  S1AP_PAGING_IND(message_p).ue_index_value  = BIT_STRING_to_uint32(&ie->value.choice.UEIdentityIndexValue);
1067
  S1AP_DEBUG("[SCTP %d] Received Paging ue_index_value (%d)\n",
1068
             assoc_id,(uint32_t)S1AP_PAGING_IND(message_p).ue_index_value);
1069 1070
  S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0;
  S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0;
1071 1072 1073
  /* id-UEPagingID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UEPagingID, true);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1074

1075
  /* convert UE Paging Identity */
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
  if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_s_TMSI) {
    S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask = UE_PAGING_IDENTITY_s_tmsi;
    OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingID.choice.s_TMSI.mMEC, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code);
    OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingID.choice.s_TMSI.m_TMSI, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi);
  } else if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) {
    S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask = UE_PAGING_IDENTITY_imsi;
    S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length = 0;

    for (int i = 0; i < ie->value.choice.UEPagingID.choice.iMSI.size; i++) {
      S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i] = (uint8_t)(ie->value.choice.UEPagingID.choice.iMSI.buf[i] & 0x0F );
      S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++;
      S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1] = (uint8_t)((ie->value.choice.UEPagingID.choice.iMSI.buf[i]>>4) & 0x0F);
      LOG_D(S1AP,"paging : i %d %d imsi %d %d \n",2*i,2*i+1,S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1]);

      if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1] == 0x0F) {
        if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) {
          /* invalid paging_p->uePagingID.choise.iMSI.buffer */
          S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i);
1094
          return -1;
1095 1096 1097 1098 1099 1100 1101 1102 1103
        }
      } else {
        S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++;
      }
    }

    if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) {
      /* invalid paging_p->uePagingID.choise.iMSI.size */
      S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH);
1104
      return -1;
1105 1106 1107 1108 1109
    }
  } else {
    /* invalid paging_p->uePagingID.present */
    S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present);
    return -1;
1110 1111 1112
  }

  S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256;
1113 1114 1115 1116 1117 1118 1119
  /* id-pagingDRX */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_pagingDRX, false);

  /* optional */
  if (ie) {
    S1AP_PAGING_IND(message_p).paging_drx = ie->value.choice.PagingDRX;
1120
  } else {
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
    S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256;
  }

  /* */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_CNDomain, true);

  /* id-CNDomain : convert cnDomain */
  if (ie->value.choice.CNDomain == S1AP_CNDomain_ps) {
    S1AP_PAGING_IND(message_p).cn_domain = CN_DOMAIN_PS;
  } else if (ie->value.choice.CNDomain == S1AP_CNDomain_cs) {
    S1AP_PAGING_IND(message_p).cn_domain = CN_DOMAIN_CS;
  } else {
    /* invalid paging_p->cnDomain */
    S1AP_ERROR("[SCTP %d] Received Paging : cnDomain(%ld) is unknown\n", assoc_id, ie->value.choice.CNDomain);
    return -1;
1137 1138 1139 1140 1141
  }

  memset (&S1AP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256);
  memset (&S1AP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256);
  S1AP_PAGING_IND(message_p).tai_size = 0;
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
  /* id-TAIList */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_TAIList, true);
  S1AP_INFO("[SCTP %d] Received Paging taiList: count %d\n", assoc_id, ie->value.choice.TAIList.list.count);

  for (int i = 0; i < ie->value.choice.TAIList.list.count; i++) {
    S1AP_TAIItem_t *item_p;
    item_p = &(((S1AP_TAIItemIEs_t *)ie->value.choice.TAIList.list.array[i])->value.choice.TAIItem);
    TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNidentity), S1AP_PAGING_IND(message_p).plmn_identity[i].mcc,
                    S1AP_PAGING_IND(message_p).plmn_identity[i].mnc,
                    S1AP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length);
    OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), S1AP_PAGING_IND(message_p).tac[i]);
    S1AP_PAGING_IND(message_p).tai_size++;
    S1AP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id,
               S1AP_PAGING_IND(message_p).plmn_identity[i].mcc,
               S1AP_PAGING_IND(message_p).plmn_identity[i].mnc,
               S1AP_PAGING_IND(message_p).tac[i]);
1159 1160 1161 1162
  }

  //paging parameter values
  S1AP_DEBUG("[SCTP %d] Received Paging parameters: ue_index_value %d  cn_domain %d paging_drx %d paging_priority %d\n",assoc_id,
1163 1164
             S1AP_PAGING_IND(message_p).ue_index_value, S1AP_PAGING_IND(message_p).cn_domain,
             S1AP_PAGING_IND(message_p).paging_drx, S1AP_PAGING_IND(message_p).paging_priority);
1165
  S1AP_DEBUG("[SCTP %d] Received Paging parameters(ue): presenceMask %d  s_tmsi.m_tmsi %d s_tmsi.mme_code %d IMSI length %d (0-5) %d%d%d%d%d%d\n",assoc_id,
1166 1167 1168 1169 1170
             S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi,
             S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length,
             S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[0], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[1],
             S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[3],
             S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[4], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[5]);
1171 1172
  /* send message to RRC */
  itti_send_msg_to_task(TASK_RRC_ENB, s1ap_eNB_instance->instance, message_p);
1173
  return 0;
1174 1175 1176 1177
}

static
int s1ap_eNB_handle_e_rab_modify_request(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1178 1179
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
  int i, nb_of_e_rabs_failed;
  s1ap_eNB_mme_data_t           *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t         *ue_desc_p        = NULL;
  MessageDef                    *message_p        = NULL;
  S1AP_E_RABModifyRequest_t     *container;
  S1AP_E_RABModifyRequestIEs_t  *ie;
  S1AP_ENB_UE_S1AP_ID_t         enb_ue_s1ap_id;
  S1AP_MME_UE_S1AP_ID_t         mme_ue_s1ap_id;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.E_RABModifyRequest;
1190 1191 1192 1193 1194 1195 1196

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received E-RAB modify request for non "
               "existing MME context\n", assoc_id);
    return -1;
  }

1197 1198 1199 1200 1201 1202 1203 1204
  /* id-MME-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABModifyRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
  mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  /* id-eNB-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABModifyRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
  enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
1205 1206

  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1207
                   enb_ue_s1ap_id)) == NULL) {
1208 1209
    S1AP_ERROR("[SCTP %d] Received E-RAB modify request for non "
               "existing UE context 0x%06lx\n", assoc_id,
1210
               enb_ue_s1ap_id);
1211 1212
    return -1;
  }
1213

1214 1215 1216 1217 1218 1219 1220 1221 1222
  /* E-RAB modify request = UE-related procedure -> stream != 0 */
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
    return -1;
  }

  ue_desc_p->rx_stream = stream;

1223
  if (ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) {
1224
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
1225
              ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id);
1226
    message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP);
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
    S1AP_E_RAB_MODIFY_RESP (message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
    S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABModifyRequestIEs_t, ie, container,
                               S1AP_ProtocolIE_ID_id_E_RABToBeModifiedListBearerModReq, true);

    for(nb_of_e_rabs_failed = 0; nb_of_e_rabs_failed < ie->value.choice.E_RABToBeModifiedListBearerModReq.list.count; nb_of_e_rabs_failed++) {
      S1AP_E_RABToBeModifiedItemBearerModReq_t *item_p;
      item_p = &(((S1AP_E_RABToBeModifiedItemBearerModReqIEs_t *)
                  ie->value.choice.E_RABToBeModifiedListBearerModReq.list.array[nb_of_e_rabs_failed])->value.choice.E_RABToBeModifiedItemBearerModReq);
      S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].e_rab_id = item_p->e_RAB_ID;
      S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause = S1AP_Cause_PR_radioNetwork;
      S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id;
1238 1239
    }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1240
    S1AP_E_RAB_MODIFY_RESP(message_p).nb_of_e_rabs_failed = nb_of_e_rabs_failed;
1241 1242 1243 1244 1245 1246 1247 1248
    s1ap_eNB_e_rab_modify_resp(mme_desc_p->s1ap_eNB_instance->instance,
                               &S1AP_E_RAB_MODIFY_RESP(message_p));
    message_p = NULL;
    return -1;
  }

  message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_MODIFY_REQ);
  S1AP_E_RAB_MODIFY_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
1249 1250 1251 1252 1253
  S1AP_E_RAB_MODIFY_REQ(message_p).mme_ue_s1ap_id  = mme_ue_s1ap_id;
  S1AP_E_RAB_MODIFY_REQ(message_p).eNB_ue_s1ap_id  = enb_ue_s1ap_id;
  /* id-E-RABToBeModifiedListBearerModReq */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABModifyRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeModifiedListBearerModReq, true);
1254
  S1AP_E_RAB_MODIFY_REQ(message_p).nb_e_rabs_tomodify =
1255
    ie->value.choice.E_RABToBeModifiedListBearerModReq.list.count;
1256

1257 1258 1259
  for (i = 0; i < ie->value.choice.E_RABToBeModifiedListBearerModReq.list.count; i++) {
    S1AP_E_RABToBeModifiedItemBearerModReq_t *item_p;
    item_p = &(((S1AP_E_RABToBeModifiedItemBearerModReqIEs_t *)ie->value.choice.E_RABToBeModifiedListBearerModReq.list.array[i])->value.choice.E_RABToBeModifiedItemBearerModReq);
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
    S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].e_rab_id = item_p->e_RAB_ID;

    // check for the NAS PDU
    if (item_p->nAS_PDU.size > 0 ) {
      S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.length = item_p->nAS_PDU.size;
      S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size);
      memcpy(S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer,
             item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
    } else {
      S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.length = 0;
      S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer = NULL;
      continue;
    }

    /* Set the QOS informations */
    S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.qci = item_p->e_RABLevelQoSParameters.qCI;
    S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.priority_level =
      item_p->e_RABLevelQoSParameters.allocationRetentionPriority.priorityLevel;
    S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.pre_emp_capability =
      item_p->e_RABLevelQoSParameters.allocationRetentionPriority.pre_emptionCapability;
    S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.pre_emp_vulnerability =
      item_p->e_RABLevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability;
  }

  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  return 0;
}
// handle e-rab release command and send it to rrc_end
static
int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1290 1291
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1292 1293 1294 1295
  int i;
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
1296 1297 1298 1299 1300 1301
  S1AP_E_RABReleaseCommand_t     *container;
  S1AP_E_RABReleaseCommandIEs_t  *ie;
  S1AP_ENB_UE_S1AP_ID_t           enb_ue_s1ap_id;
  S1AP_MME_UE_S1AP_ID_t           mme_ue_s1ap_id;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.E_RABReleaseCommand;
1302 1303 1304 1305 1306

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received E-RAB release command for non existing MME context\n", assoc_id);
    return -1;
  }
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316

  /* id-MME-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
  mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  /* id-eNB-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
  enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;

1317
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1318
                   enb_ue_s1ap_id)) == NULL) {
1319
    S1AP_ERROR("[SCTP %d] Received E-RAB release command for non existing UE context 0x%06lx\n", assoc_id,
1320
               ie->value.choice.ENB_UE_S1AP_ID);
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
    return -1;
  }

  /* Initial context request = UE-related procedure -> stream != 0 */
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
    return -1;
  }

  ue_desc_p->rx_stream = stream;

1333
  if (ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) {
1334
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
1335
              ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id);
1336 1337 1338
  }

  S1AP_DEBUG("[SCTP %d] Received E-RAB release command for eNB_UE_S1AP_ID %ld mme_ue_s1ap_id %ld\n",
1339 1340 1341 1342 1343 1344 1345
             assoc_id, enb_ue_s1ap_id, mme_ue_s1ap_id);
  message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_RELEASE_COMMAND);
  S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
  S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id;
  /* id-NAS-PDU */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_NAS_PDU, false);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1346

1347 1348
  if(ie && ie->value.choice.NAS_PDU.size > 0) {
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size;
1349
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer =
1350
      malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
1351
    memcpy(S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer,
1352 1353
           ie->value.choice.NAS_PDU.buf,
           ie->value.choice.NAS_PDU.size);
1354
  } else {
1355 1356
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0;
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL;
1357 1358
  }

1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
  /* id-E-RABToBeReleasedList */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true);
  S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count;

  for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) {
    S1AP_E_RABItem_t *item_p;
    item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem);
    S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID;
    S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID);
1369 1370 1371 1372 1373
  }

  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  return 0;
}