s1ap_eNB_handlers.c 75.6 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

97 98
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
99 100
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
101

102 103
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t               assoc_id,
104 105
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);
106

107 108 109 110 111
static
int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t               assoc_id,
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu);

Cedric Roux's avatar
 
Cedric Roux committed
112 113
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = {
114 115 116
  { 0, 0, 0 }, /* HandoverPreparation */
  { 0, 0, 0 }, /* HandoverResourceAllocation */
  { 0, 0, 0 }, /* HandoverNotification */
117
  { 0, s1ap_eNB_handle_s1_path_switch_request_ack, s1ap_eNB_handle_s1_path_switch_request_failure }, /* PathSwitchRequest */
118
  { 0, 0, 0 }, /* HandoverCancel */
119
  { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
120 121
  { s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */
  { s1ap_eNB_handle_e_rab_release_command, 0, 0 }, /* E_RABRelease */
122 123
  { 0, 0, 0 }, /* E_RABReleaseIndication */
  { s1ap_eNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */
124
  { s1ap_eNB_handle_paging, 0, 0 }, /* Paging */
125 126 127 128
  { s1ap_eNB_handle_nas_downlink, 0, 0 }, /* downlinkNASTransport */
  { 0, 0, 0 }, /* initialUEMessage */
  { 0, 0, 0 }, /* uplinkNASTransport */
  { 0, 0, 0 }, /* Reset */
129
  { s1ap_eNB_handle_error_indication, 0, 0 }, /* ErrorIndication */
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
  { 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 */
  { 0, 0, 0 }, /* Kill */
  { 0, 0, 0 }, /* DownlinkUEAssociatedLPPaTransport  */
  { 0, 0, 0 }, /* UplinkUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* DownlinkNonUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* UplinkNonUEAssociatedLPPaTransport */
162 163 164
  { 0, 0, 0 }, /* UERadioCapabilityMatch */
  { 0, 0, 0 }, /* PWSRestartIndication */
  { 0, s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm, 0 }, /* E_RABModificationIndication */
Cedric Roux's avatar
 
Cedric Roux committed
165
};
166
char *s1ap_direction2String(int s1ap_dir) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
167 168 169 170 171 172 173
  static char *s1ap_direction_String[] = {
    "", /* Nothing */
    "Originating message", /* originating message */
    "Successfull outcome", /* successfull outcome */
    "UnSuccessfull outcome", /* successfull outcome */
  };
  return(s1ap_direction_String[s1ap_dir]);
174
}
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
175
void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown) {
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
  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;
191
        message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_DEREGISTERED_ENB_IND);
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
        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;
209
      message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_REGISTER_ENB_CNF);
210 211
      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);
212
    }
213
  }
214 215
}

216
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
217
                            const uint8_t *const data, const uint32_t data_length) {
218 219
  S1AP_S1AP_PDU_t pdu;
  int ret;
220
  DevAssert(data != NULL);
221
  memset(&pdu, 0, sizeof(pdu));
222

223
  if (s1ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
224 225 226 227 228
    S1AP_ERROR("Failed to decode PDU\n");
    return -1;
  }

  /* Checking procedure Code and direction of message */
229
  if (pdu.choice.initiatingMessage.procedureCode >= sizeof(messages_callback) / (3 * sizeof(
230
        s1ap_message_decoded_callback))
231
      || (pdu.present > S1AP_S1AP_PDU_PR_unsuccessfulOutcome)) {
Cedric Roux's avatar
Cedric Roux committed
232
    S1AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
233 234
               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_S1AP_PDU, &pdu);
235 236 237 238 239 240
    return -1;
  }

  /* No handler present.
   * This can mean not implemented or no procedure for eNB (wrong direction).
   */
241
  if (messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
Cedric Roux's avatar
Cedric Roux committed
242
    S1AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
243
               assoc_id, pdu.choice.initiatingMessage.procedureCode,
244
               s1ap_direction2String(pdu.present - 1));
245
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_S1AP_PDU, &pdu);
246 247 248 249
    return -1;
  }

  /* Calling the right handler */
250 251 252 253
  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
254 255
}

Cedric Roux's avatar
Cedric Roux committed
256
static
257 258
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
259
                                     S1AP_S1AP_PDU_t       *pdu) {
260 261
  S1AP_S1SetupFailure_t      *container;
  S1AP_S1SetupFailureIEs_t   *ie;
262
  s1ap_eNB_mme_data_t        *mme_desc_p;
263 264
  DevAssert(pdu != NULL);
  container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure;
265

266 267 268 269 270
  /* 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);
  }
271

272 273 274 275 276
  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;
  }
277

278
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container,
279
                             S1AP_ProtocolIE_ID_id_Cause,true);
280 281 282

  if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) &&
      (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) {
283 284 285 286
    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");
  }
287

288 289 290
  mme_desc_p->state = S1AP_ENB_STATE_WAITING;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);
  return 0;
291 292 293 294 295
}

static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
296
                                      S1AP_S1AP_PDU_t       *pdu) {
297 298
  S1AP_S1SetupResponse_t    *container;
  S1AP_S1SetupResponseIEs_t *ie;
299 300
  s1ap_eNB_mme_data_t       *mme_desc_p;
  int i;
301 302
  DevAssert(pdu != NULL);
  container = &pdu->choice.successfulOutcome.value.choice.S1SetupResponse;
303 304 305 306 307 308 309 310 311 312 313 314 315 316

  /* 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;
  }

317 318
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true);
319

320 321 322
  /* 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.
   */
323 324 325
  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);
326

327 328 329
  for (i = 0; i < ie->value.choice.ServedGUMMEIs.list.count; i++) {
    S1AP_ServedGUMMEIsItem_t *gummei_item_p;
    struct served_gummei_s   *new_gummei_p;
330
    int j;
331
    gummei_item_p = ie->value.choice.ServedGUMMEIs.list.array[i];
332 333 334 335
    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);
336 337
    S1AP_DEBUG("servedPLMNs.list.count %d\n", gummei_item_p->servedPLMNs.list.count);

338
    for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) {
339
      S1AP_PLMNidentity_t *plmn_identity_p;
340
      struct plmn_identity_s *new_plmn_identity_p;
navid's avatar
navid committed
341
      plmn_identity_p = gummei_item_p->servedPLMNs.list.array[j];
342 343 344 345 346 347
      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
348

349
    for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) {
350
      S1AP_MME_Group_ID_t       *mme_group_id_p;
351
      struct served_group_id_s *new_group_id_p;
navid's avatar
navid committed
352
      mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[j];
353 354 355 356
      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
357 358
    }

359
    for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) {
360
      S1AP_MME_Code_t        *mme_code_p;
361
      struct mme_code_s *new_mme_code_p;
navid's avatar
navid committed
362
      mme_code_p = gummei_item_p->servedMMECs.list.array[j];
363 364 365 366
      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
367
    }
368 369 370 371 372

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

  /* Set the capacity of this MME */
373 374
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true);
375

376
  mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity;
377 378

  /* Optionaly set the mme name */
379 380
  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
381

382 383 384 385
  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);
386
    /* Convert the mme name to a printable string */
387
    mme_desc_p->mme_name[ie->value.choice.MMEname.size] = '\0';
388 389 390 391 392 393 394 395 396
  }

  /* 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
397 398
}

399 400

static
401 402
int s1ap_eNB_handle_error_indication(uint32_t         assoc_id,
                                     uint32_t         stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
403
                                     S1AP_S1AP_PDU_t *pdu) {
404 405
  S1AP_ErrorIndication_t    *container;
  S1AP_ErrorIndicationIEs_t *ie;
406
  s1ap_eNB_mme_data_t        *mme_desc_p;
407 408
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.ErrorIndication;
409 410 411 412 413 414 415 416 417 418 419 420

  /* 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;
  }
421 422 423 424 425

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

  /* optional */
426
  if (ie != NULL) {
427
    S1AP_WARN("Received S1 Error indication MME UE S1AP ID 0x%lx\n", ie->value.choice.MME_UE_S1AP_ID);
428
  }
429 430 431 432 433

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

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

438 439 440 441 442 443 444 445 446 447 448 449 450 451
  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");
452
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
453

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

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

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

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

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

474 475
          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");
476
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
477

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

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

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

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

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

498 499
          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");
500
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
501

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

578 579
          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");
580
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
581

582 583
          case S1AP_CauseRadioNetwork_s1_intra_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
584
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
585

586 587
          case S1AP_CauseRadioNetwork_s1_inter_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
588
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
589

590 591
          case S1AP_CauseRadioNetwork_x2_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_x2_handover_triggered\n");
592
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
593

594 595
          case S1AP_CauseRadioNetwork_redirection_towards_1xRTT:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_redirection_towards_1xRTT\n");
596
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
597

598 599
          case S1AP_CauseRadioNetwork_not_supported_QCI_value:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_not_supported_QCI_value\n");
600
            break;
601 602
          case S1AP_CauseRadioNetwork_invalid_CSG_Id:
            S1AP_WARN("Received S1 Error indication S1AP_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
603
            break;
604 605

          default:
606
            S1AP_WARN("Received S1 Error indication cause radio network 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_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");
615
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
616

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

621
          default:
622
            S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
623
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
624

625
        break;
626

627 628 629 630
      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");
631
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
632

633 634
          case S1AP_CauseNas_authentication_failure:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_authentication_failure\n");
635
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
636

637 638
          case S1AP_CauseNas_detach:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_detach\n");
639
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
640

641 642
          case S1AP_CauseNas_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_unspecified\n");
643
            break;
644 645
          case S1AP_CauseNas_csg_subscription_expiry:
            S1AP_WARN("Received S1 Error indication S1AP_CauseNas_csg_subscription_expiry\n");
646
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
647

648
          default:
649
            S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
650 651 652
        }

        break;
653

654 655 656 657
      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");
658
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
659

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

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

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

672 673
          case S1AP_CauseProtocol_semantic_error:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_semantic_error\n");
674
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
675

676 677
          case S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
678
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
679

680 681
          case S1AP_CauseProtocol_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseProtocol_unspecified\n");
682
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
683

684
          default:
685
            S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
686
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
687

688
        break;
689

690 691 692 693 694
      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
695

696 697 698
          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
699

700 701 702
          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
703

704 705 706
          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
707

708 709 710
          case S1AP_CauseMisc_unspecified:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_unspecified\n");
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
711

712 713
          case S1AP_CauseMisc_unknown_PLMN:
            S1AP_WARN("Received S1 Error indication S1AP_CauseMisc_unknown_PLMN\n");
714
            break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
715

716 717 718
          default:
            S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
        }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
719

720
        break;
721 722
    }
  }
723 724 725 726 727

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

  if (ie) {
728 729 730
    // TODO continue
  }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
731
  // TODO continue
732 733 734 735
  return 0;
}


736
static
737
int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
738
    uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
739
    S1AP_S1AP_PDU_t       *pdu) {
740 741 742 743
  int i;
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
744 745 746 747 748 749
  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
750

751 752 753 754 755
  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
756

757 758 759
  /* id-MME-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
760 761 762 763 764 765

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  } else {
    return -1;
  }
766 767 768 769 770

  /* id-eNB-UE-S1AP-ID */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);

771 772
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
frtabu's avatar
frtabu committed
773

774 775 776 777 778 779
    if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
                     enb_ue_s1ap_id)) == NULL) {
      S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
                 "existing UE context 0x%06lx\n", assoc_id,
                 enb_ue_s1ap_id);
      return -1;
780
    }
781
  } else {
782 783
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
784

785
  /* Initial context request = UE-related procedure -> stream != 0 */
786 787 788
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
789 790
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
791

792
  ue_desc_p->rx_stream = stream;
793
  ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
794
  message_p        = itti_alloc_new_message(TASK_S1AP, 0, S1AP_INITIAL_CONTEXT_SETUP_REQ);
795 796 797
  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;
798
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).mme_ue_s1ap_id = ue_desc_p->mme_ue_s1ap_id;
799 800 801
  /* id-uEaggregateMaximumBitrate */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, true);
802

803 804 805 806 807 808 809 810 811 812
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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 */
  } else {
    return -1;
  }

813 814
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true);
815

816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_e_rabs =
      ie->value.choice.E_RABToBeSetupListCtxtSUReq.list.count;

    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);
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].e_rab_id = item_p->e_RAB_ID;

      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,
               item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
        S1AP_DEBUG("Received NAS message with the E_RAB setup procedure\n");
      } 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;
      }
837

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
      /* 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;
    } /* for i... */
  } else {/* ie != NULL */
    return -1;
856
  }
857

858 859 860 861
  /* id-UESecurityCapabilities */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UESecurityCapabilities, true);

862 863 864 865 866 867 868 869 870
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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);
  } else {/* ie != NULL */
    return -1;
  }

871
  /* id-SecurityKey : Copy the security key */
872 873 874
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_SecurityKey, true);

875 876 877 878 879 880
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
           ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
  } else {/* ie != NULL */
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
881

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
  /* id-NRUESecurityCapabilities */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false);
  if (ie != NULL) {
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms =
      BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRencryptionAlgorithms);
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms =
      BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRintegrityProtectionAlgorithms);
  } else {
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0;
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0;
  }

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

897
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
898
}
899 900 901


static
902
int s1ap_eNB_handle_ue_context_release_command(uint32_t   assoc_id,
903
    uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
904
    S1AP_S1AP_PDU_t       *pdu) {
905 906 907
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
908 909 910 911 912 913
  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;
914 915 916 917 918 919

  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;
  }
920

921 922 923
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true);

924 925 926 927 928 929
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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(
930
          MSC_S1AP_ENB,
931
          MSC_S1AP_MME,
932
          NULL,0,
933 934 935 936
          "0 UEContextRelease/%s eNB_ue_s1ap_id "S1AP_UE_ID_FMT" mme_ue_s1ap_id "S1AP_UE_ID_FMT" len %u",
          s1ap_direction2String(pdu->present - 1),
          enb_ue_s1ap_id,
          mme_ue_s1ap_id);
937

938 939 940 941 942 943 944 945 946 947 948 949 950 951
        if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
                         enb_ue_s1ap_id)) == NULL) {
          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);
952
          message_p    = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND);
953 954 955 956 957 958 959 960

          if (ue_desc_p->mme_ue_s1ap_id == 0) { // case of Detach Request and switch off from RRC_IDLE mode
            ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
          }

          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;
961
        }
962

963
        break;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
964

965
      //#warning "TODO mapping mme_ue_s1ap_id  enb_ue_s1ap_id?"
966

967 968 969 970
      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 */
971

972 973 974
      case S1AP_UE_S1AP_IDs_PR_NOTHING:
      default:
        S1AP_ERROR("S1AP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements");
frtabu's avatar
frtabu committed
975 976
        return -1;
    }
977 978
  } else {
    return -1;
979
  }
980 981 982 983

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_Cause, true);
  /* TBD */
984 985
}

986
static
987 988
int s1ap_eNB_handle_e_rab_setup_request(uint32_t         assoc_id,
                                        uint32_t         stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
989
                                        S1AP_S1AP_PDU_t *pdu) {
990
  int i;
991 992 993 994 995 996 997 998 999
  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;
1000 1001 1002 1003 1004 1005 1006

  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;
  }

1007 1008 1009
  /* 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);
1010 1011 1012 1013 1014 1015

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  } else {
    return -1;
  }
1016 1017 1018 1019

  /* 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);
1020 1021 1022 1023 1024 1025

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
  } else {
    return -1;
  }
1026

1027
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1028
                   enb_ue_s1ap_id)) == NULL) {
1029
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
Cedric Roux's avatar
Cedric Roux committed
1030
               "existing UE context 0x%06lx\n", assoc_id,
1031
               enb_ue_s1ap_id);
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
    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;

1044 1045 1046
  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);
1047
  }
1048

1049
  message_p        = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_SETUP_REQ);
1050
  S1AP_E_RAB_SETUP_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
1051 1052 1053 1054
  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);
1055

1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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);
      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,
               item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
        // 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]);
      } 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");
      }
1077

1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
      /* 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;
      /* 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);
      */
      /* 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;
    } /* for i... */
frtabu's avatar
frtabu committed
1099

1100 1101 1102
    itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  } else {
    return -1;
1103 1104 1105 1106 1107
  }

  return 0;
}

1108 1109
static
int s1ap_eNB_handle_paging(uint32_t               assoc_id,
1110
                           uint32_t               stream,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1111
                           S1AP_S1AP_PDU_t       *pdu) {
1112 1113 1114
  s1ap_eNB_mme_data_t   *mme_desc_p        = NULL;
  s1ap_eNB_instance_t   *s1ap_eNB_instance = NULL;
  MessageDef            *message_p         = NULL;
1115 1116 1117 1118
  S1AP_Paging_t         *container;
  S1AP_PagingIEs_t      *ie;
  DevAssert(pdu != NULL);
  container = &pdu->choice.initiatingMessage.value.choice.Paging;
1119 1120 1121 1122 1123
  // received Paging Message from MME
  S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id);

  /* Paging procedure -> stream != 0 */
  if (stream == 0) {
1124
    LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1125
          assoc_id, stream);
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
    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
1136

1137 1138 1139 1140 1141 1142
  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;
  }

1143
  message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_PAGING_IND);
1144 1145 1146 1147
  /* 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);
1148

1149 1150 1151 1152 1153 1154 1155 1156 1157
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    S1AP_PAGING_IND(message_p).ue_index_value  = BIT_STRING_to_uint32(&ie->value.choice.UEIdentityIndexValue);
    S1AP_DEBUG("[SCTP %d] Received Paging ue_index_value (%d)\n",
               assoc_id,(uint32_t)S1AP_PAGING_IND(message_p).ue_index_value);
    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;
  } else {
    return -1;
  }
1158

1159 1160 1161
  /* 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
1162

1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    /* convert UE Paging Identity */
    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 );
1175
        S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++;
1176 1177 1178 1179 1180 1181 1182
        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);
frtabu's avatar
frtabu committed
1183
            return -1;
1184 1185 1186
          }
        } else {
          S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++;
frtabu's avatar
frtabu committed
1187
        }
1188
      } /* for i... */
1189

1190 1191 1192
      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);
frtabu's avatar
frtabu committed
1193
        return -1;
1194 1195 1196 1197
      }
    } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */
      /* invalid paging_p->uePagingID.present */
      S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present);
1198
      return -1;
1199
    }
1200
  } else { /* of ie != NULL */
1201
    return -1;
1202 1203 1204
  }

  S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256;
1205 1206 1207 1208 1209 1210 1211
  /* 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;
1212
  } else {
1213 1214 1215 1216 1217 1218 1219
    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);

1220 1221 1222 1223 1224 1225
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    /* 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;
frtabu's avatar
frtabu committed
1226
    } else {
1227 1228
      /* invalid paging_p->cnDomain */
      S1AP_ERROR("[SCTP %d] Received Paging : cnDomain(%ld) is unknown\n", assoc_id, ie->value.choice.CNDomain);
1229
      itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
1230
      return -1;
frtabu's avatar
frtabu committed
1231
    }
1232 1233
  } else {
    return -1;
1234 1235 1236 1237 1238
  }

  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;
1239 1240 1241 1242
  /* id-TAIList */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_TAIList, true);

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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]);
frtabu's avatar
frtabu committed
1258
    }
1259 1260
  } else {
    return -1;
1261 1262 1263 1264
  }

  //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,
1265 1266
             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);
1267
  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,
1268 1269 1270 1271 1272
             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]);
1273 1274
  /* send message to RRC */
  itti_send_msg_to_task(TASK_RRC_ENB, s1ap_eNB_instance->instance, message_p);
1275
  return 0;
1276 1277 1278 1279
}

static
int s1ap_eNB_handle_e_rab_modify_request(uint32_t               assoc_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1280 1281
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
  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;
1292 1293 1294 1295 1296 1297 1298

  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;
  }

1299 1300 1301
  /* 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);
1302 1303 1304 1305 1306 1307

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  } else {
    return -1;
  }
1308 1309 1310 1311

  /* 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);
1312 1313 1314 1315 1316 1317

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
  } else {
    return -1;
  }
1318 1319

  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1320
                   enb_ue_s1ap_id)) == NULL) {
1321 1322
    S1AP_ERROR("[SCTP %d] Received E-RAB modify request for non "
               "existing UE context 0x%06lx\n", assoc_id,
1323
               enb_ue_s1ap_id);
1324 1325
    return -1;
  }
1326

1327 1328 1329 1330 1331 1332 1333 1334 1335
  /* 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;

1336
  if (ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) {
1337
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
1338
              ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id);
1339
    message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFY_RESP);
1340 1341 1342 1343
    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);

frtabu's avatar
frtabu committed
1344
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
1345 1346 1347 1348 1349 1350 1351 1352
      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;
      }
frtabu's avatar
frtabu committed
1353
    } else {
1354
      return -1;
1355 1356
    }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1357
    S1AP_E_RAB_MODIFY_RESP(message_p).nb_of_e_rabs_failed = nb_of_e_rabs_failed;
1358 1359
    s1ap_eNB_e_rab_modify_resp(mme_desc_p->s1ap_eNB_instance->instance,
                               &S1AP_E_RAB_MODIFY_RESP(message_p));
1360
    itti_free(TASK_RRC_ENB,message_p);
1361 1362 1363 1364
    message_p = NULL;
    return -1;
  }

1365
  message_p        = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_MODIFY_REQ);
1366
  S1AP_E_RAB_MODIFY_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
1367 1368 1369 1370 1371
  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);
1372

1373 1374 1375
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    S1AP_E_RAB_MODIFY_REQ(message_p).nb_e_rabs_tomodify =
      ie->value.choice.E_RABToBeModifiedListBearerModReq.list.count;
1376

1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
    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);
      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;
      }
1393

1394 1395 1396 1397 1398 1399 1400 1401
      /* 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;
1402 1403
    }

1404 1405 1406
    itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
  } else { /* of if (ie != NULL)*/
    return -1;
1407 1408 1409 1410 1411 1412 1413
  }

  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
1414 1415
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1416 1417 1418 1419
  int i;
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
1420 1421 1422 1423 1424 1425
  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;
1426 1427 1428 1429 1430

  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;
  }
1431

1432

1433 1434 1435
  /* 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);
1436 1437 1438 1439 1440 1441

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
  } else {
    return -1;
  }
1442 1443 1444 1445

  /* 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);
1446 1447 1448 1449 1450 1451

  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
  } else {
    return -1;
  }
1452

1453
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1454
                   enb_ue_s1ap_id)) == NULL) {
1455
    S1AP_ERROR("[SCTP %d] Received E-RAB release command for non existing UE context 0x%06lx\n", assoc_id,
1456
               ie->value.choice.ENB_UE_S1AP_ID);
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
    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;

1469
  if (ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) {
1470
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
1471
              ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id);
1472 1473 1474
  }

  S1AP_DEBUG("[SCTP %d] Received E-RAB release command for eNB_UE_S1AP_ID %ld mme_ue_s1ap_id %ld\n",
1475
             assoc_id, enb_ue_s1ap_id, mme_ue_s1ap_id);
1476
  message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_RELEASE_COMMAND);
1477 1478 1479 1480 1481
  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
1482

1483 1484
  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;
1485
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer =
1486
      malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
1487
    memcpy(S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer,
1488 1489
           ie->value.choice.NAS_PDU.buf,
           ie->value.choice.NAS_PDU.size);
1490
  } else {
1491 1492
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0;
    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL;
1493 1494
  }

1495 1496 1497 1498
  /* id-E-RABToBeReleasedList */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                             S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true);

1499 1500 1501 1502 1503 1504 1505 1506
  if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
    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);
frtabu's avatar
frtabu committed
1507
    }
1508 1509
  } else {
    return -1;
1510 1511 1512
  }

  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
1513 1514 1515 1516 1517
  return 0;
}

static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
1518 1519
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
  S1AP_PathSwitchRequestAcknowledge_t *pathSwitchRequestAcknowledge;
  S1AP_PathSwitchRequestAcknowledgeIEs_t *ie;
  S1AP_E_RABToBeSwitchedULItemIEs_t *s1ap_E_RABToBeSwitchedULItemIEs;
  S1AP_E_RABToBeSwitchedULItem_t *s1ap_E_RABToBeSwitchedULItem;
  S1AP_E_RABItemIEs_t  *e_RABItemIEs;
  S1AP_E_RABItem_t     *e_RABItem;
  DevAssert(pdu != NULL);
  pathSwitchRequestAcknowledge = &pdu->choice.successfulOutcome.value.choice.PathSwitchRequestAcknowledge;

  /* Path Switch request == UE-related procedure -> stream !=0 */
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n",
               assoc_id, stream);
luaihui's avatar
luaihui committed
1536
    //return -1;
1537 1538 1539 1540 1541 1542 1543 1544 1545
  }

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

  // send a message to RRC
1546
  message_p        = itti_alloc_new_message(TASK_S1AP, 0, S1AP_PATH_SWITCH_REQ_ACK);
1547 1548 1549
  /* mandatory */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
1550 1551 1552 1553 1554 1555
  if (ie == NULL) {
    S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
               "ie context is NULL\n", assoc_id);
    return -1;
  }

1556 1557 1558 1559 1560 1561 1562
  S1AP_PATH_SWITCH_REQ_ACK(message_p).eNB_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;

  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
                   ie->value.choice.ENB_UE_S1AP_ID)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
               "existing UE context 0x%06lx\n", assoc_id,
               ie->value.choice.ENB_UE_S1AP_ID);
1563
    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
1564 1565 1566 1567 1568 1569 1570
    return -1;
  }

  S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
  /* mandatory */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
1571 1572 1573 1574 1575 1576 1577

  if (ie == NULL) {
    S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
               "ie context is NULL\n", assoc_id);
    return -1;
  }

1578 1579
  S1AP_PATH_SWITCH_REQ_ACK(message_p).mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;

1580
  if ( ue_desc_p->mme_ue_s1ap_id != ie->value.choice.MME_UE_S1AP_ID) {
1581 1582 1583 1584 1585 1586 1587
    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
              ue_desc_p->mme_ue_s1ap_id, ie->value.choice.MME_UE_S1AP_ID);
  }

  /* mandatory */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_SecurityContext, true);
1588 1589 1590 1591 1592 1593 1594

  if (ie == NULL) {
    S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
               "ie context is NULL\n", assoc_id);
    return -1;
  }

1595 1596 1597 1598
  S1AP_PATH_SWITCH_REQ_ACK(message_p).next_hop_chain_count =
    ie->value.choice.SecurityContext.nextHopChainingCount;
  memcpy(&S1AP_PATH_SWITCH_REQ_ACK(message_p).next_security_key,
         ie->value.choice.SecurityContext.nextHopParameter.buf,
1599
         ie->value.choice.SecurityContext.nextHopParameter.size);
1600 1601 1602 1603 1604 1605
  /* optional */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false);

  if (ie) {
    OCTET_STRING_TO_INT32 (
1606 1607 1608
      &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
      S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
    );
1609
    OCTET_STRING_TO_INT32 (
1610 1611 1612
      &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
      S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
    );
1613 1614 1615 1616 1617 1618 1619 1620
  } else {
    S1AP_WARN("UEAggregateMaximumBitrate not supported\n");
    S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
    S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 0;
  }

  /* optional */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
1621
                             S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULList, false);
1622 1623 1624 1625 1626 1627 1628 1629 1630

  if (ie) {
    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = ie->value.choice.E_RABToBeSwitchedULList.list.count;

    for (int i = 0; i < ie->value.choice.E_RABToBeSwitchedULList.list.count; i++) {
      s1ap_E_RABToBeSwitchedULItemIEs = (S1AP_E_RABToBeSwitchedULItemIEs_t *)ie->value.choice.E_RABToBeSwitchedULList.list.array[i];
      s1ap_E_RABToBeSwitchedULItem = &s1ap_E_RABToBeSwitchedULItemIEs->value.choice.E_RABToBeSwitchedULItem;
      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].e_rab_id = s1ap_E_RABToBeSwitchedULItem->e_RAB_ID;
      memcpy(S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.buffer,
1631
             s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.buf, s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size);
1632
      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.length =
1633
        s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size * 8 - s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.bits_unused;
1634
      OCTET_STRING_TO_INT32(&s1ap_E_RABToBeSwitchedULItem->gTP_TEID,
1635
                            S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].gtp_teid);
1636
    }
1637
  } else {
1638 1639 1640 1641
    S1AP_WARN("E_RABToBeSwitchedULList not supported\n");
    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = 0;
  }

1642
  /* optional */
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, false);

  if (ie) {
    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = ie->value.choice.E_RABList.list.count;

    for (int i = 0; i < ie->value.choice.E_RABList.list.count; i++) {
      e_RABItemIEs = (S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i];
      e_RABItem =  &e_RABItemIEs->value.choice.E_RABItem;
      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobereleased[i].e_rab_id = e_RABItem->e_RAB_ID;
    }
1654
  } else {
1655 1656
    S1AP_WARN("E_RABToBeReleasedList not supported\n");
    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = 0;
1657 1658
  }

1659 1660 1661
  /* optional */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
1662

1663 1664 1665 1666 1667 1668 1669
  if(!ie) {
    S1AP_WARN("Critical Diagnostic not supported\n");
  }

  /* optional */
  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID_2, false);
1670

1671 1672 1673 1674 1675
  if(!ie) {
    S1AP_WARN("MME_UE_S1AP_ID_2 flag not supported\n");
  }

  // TODO continue
1676
  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
1677 1678 1679 1680 1681
  return 0;
}

static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t               assoc_id,
1682 1683
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu) {
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  S1AP_PathSwitchRequestFailure_t    *pathSwitchRequestFailure;
  S1AP_PathSwitchRequestFailureIEs_t *ie;
  DevAssert(pdu != NULL);
  pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure;

  if (stream != 0) {
    S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
               assoc_id, stream);
    return -1;
  }
1695

1696 1697 1698 1699 1700 1701 1702 1703 1704
  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 path switch request failure for non existing "
               "MME context\n", assoc_id);
    return -1;
  }

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
                             S1AP_ProtocolIE_ID_id_Cause, true);

1705 1706 1707 1708 1709 1710
  if (ie == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 path switch request failure for non existing "
               "ie context is NULL\n", assoc_id);
    return -1;
  }

1711
  switch(ie->value.choice.Cause.present) {
1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
    case S1AP_Cause_PR_NOTHING:
      S1AP_WARN("Received S1 Error indication cause NOTHING\n");
      break;

    case S1AP_Cause_PR_radioNetwork:
      S1AP_WARN("Radio Network Layer Cause Failure\n");
      break;

    case S1AP_Cause_PR_transport:
      S1AP_WARN("Transport Layer Cause Failure\n");
      break;

    case S1AP_Cause_PR_nas:
      S1AP_WARN("NAS Cause Failure\n");
      break;

    case S1AP_Cause_PR_misc:
      S1AP_WARN("Miscelaneous Cause Failure\n");
      break;

    default:
      S1AP_WARN("Received an unknown S1 Error indication cause\n");
      break;
1735 1736 1737 1738 1739 1740 1741 1742 1743
  }

  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
                             S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);

  if(!ie) {
    S1AP_WARN("Critical Diagnostic not supported\n");
  }

1744
  // TODO continue
1745 1746
  return 0;
}
1747 1748 1749 1750 1751 1752

static
int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t               assoc_id,
    uint32_t               stream,
    S1AP_S1AP_PDU_t       *pdu){

matzakos's avatar
matzakos committed
1753
	LOG_I(S1AP, "Received S1AP E-RAB Modification confirm message \n");
1754 1755 1756
	return 0;
}