s1ap_eNB_handlers.c 37.4 KB
Newer Older
Cedric Roux's avatar
 
Cedric Roux committed
1
/*******************************************************************************
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
Cedric Roux's avatar
 
Cedric Roux committed
4

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


Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
Cedric Roux's avatar
 
Cedric Roux committed
15

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

  Contact Information
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
22 23 24 25 26
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
Cedric Roux's avatar
 
Cedric Roux committed
27

Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
28
 *******************************************************************************/
Cedric Roux's avatar
 
Cedric Roux committed
29 30 31 32 33 34 35 36 37 38

/*! \file s1ap_eNB_handlers.c
 * \brief s1ap messages handlers for eNB part
 * \author Sebastien ROUX <sebastien.roux@eurecom.fr>
 * \date 2013
 * \version 0.1
 */

#include <stdint.h>

39 40
#include "intertask_interface.h"

41 42
#include "asn1_conversions.h"

Cedric Roux's avatar
 
Cedric Roux committed
43 44
#include "s1ap_common.h"
#include "s1ap_ies_defs.h"
45 46
// #include "s1ap_eNB.h"
#include "s1ap_eNB_defs.h"
Cedric Roux's avatar
 
Cedric Roux committed
47 48 49 50 51 52
#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"
53
#include "s1ap_eNB_management_procedures.h"
Cedric Roux's avatar
 
Cedric Roux committed
54

55
#include "s1ap_eNB_default_values.h"
Cedric Roux's avatar
 
Cedric Roux committed
56

57
#include "assertions.h"
Cedric Roux's avatar
 
Cedric Roux committed
58
#include "conversions.h"
Raymond Knopp's avatar
Raymond Knopp committed
59
#include "msc.h"
Cedric Roux's avatar
 
Cedric Roux committed
60

61 62 63 64
static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
                                      struct s1ap_message_s *message_p);
Cedric Roux's avatar
Cedric Roux committed
65
static
66 67 68 69
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
                                     struct s1ap_message_s *message_p);

70 71 72 73 74
static
int s1ap_eNB_handle_error_indication(uint32_t               assoc_id,
    uint32_t               stream,
    struct s1ap_message_s *message_p);

75 76
static
int s1ap_eNB_handle_initial_context_request(uint32_t               assoc_id,
77 78
    uint32_t               stream,
    struct s1ap_message_s *message_p);
Cedric Roux's avatar
 
Cedric Roux committed
79

80
static
Lionel Gauthier's avatar
 
Lionel Gauthier committed
81
int s1ap_eNB_handle_ue_context_release_command(uint32_t               assoc_id,
82 83
    uint32_t               stream,
    struct s1ap_message_s *s1ap_message_p);
84

Cedric Roux's avatar
 
Cedric Roux committed
85 86
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = {
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  { 0, 0, 0 }, /* HandoverPreparation */
  { 0, 0, 0 }, /* HandoverResourceAllocation */
  { 0, 0, 0 }, /* HandoverNotification */
  { 0, 0, 0 }, /* PathSwitchRequest */
  { 0, 0, 0 }, /* HandoverCancel */
  { 0, 0, 0 }, /* E_RABSetup */
  { 0, 0, 0 }, /* E_RABModify */
  { 0, 0, 0 }, /* E_RABRelease */
  { 0, 0, 0 }, /* E_RABReleaseIndication */
  { s1ap_eNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */
  { 0, 0, 0 }, /* Paging */
  { s1ap_eNB_handle_nas_downlink, 0, 0 }, /* downlinkNASTransport */
  { 0, 0, 0 }, /* initialUEMessage */
  { 0, 0, 0 }, /* uplinkNASTransport */
  { 0, 0, 0 }, /* Reset */
102
  { s1ap_eNB_handle_error_indication, 0, 0 }, /* ErrorIndication */
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  { 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 */
Cedric Roux's avatar
 
Cedric Roux committed
130
#if defined(UPDATE_RELEASE_9)
131 132 133 134 135
  { 0, 0, 0 }, /* Kill */
  { 0, 0, 0 }, /* DownlinkUEAssociatedLPPaTransport  */
  { 0, 0, 0 }, /* UplinkUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* DownlinkNonUEAssociatedLPPaTransport */
  { 0, 0, 0 }, /* UplinkNonUEAssociatedLPPaTransport */
Cedric Roux's avatar
 
Cedric Roux committed
136 137 138
#endif
};

Raymond Knopp's avatar
Raymond Knopp committed
139
static const char *s1ap_direction2String[] = {
140 141 142 143
  "", /* Nothing */
  "Originating message", /* originating message */
  "Successfull outcome", /* successfull outcome */
  "UnSuccessfull outcome", /* successfull outcome */
Cedric Roux's avatar
 
Cedric Roux committed
144 145
};

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown)
{
  if (sctp_shutdown) {
    /* A previously connected MME has been shutdown */

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

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

      /* If there are no more associated MME, inform eNB app */
      if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb == 0) {
        MessageDef                 *message_p;

        message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DEREGISTERED_ENB_IND);
        S1AP_DEREGISTERED_ENB_IND(message_p).nb_mme = 0;
        itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
      }
    }
  } else {
    /* Check that at least one setup message is pending */
    DevCheck(mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0, mme_desc_p->s1ap_eNB_instance->instance,
             mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb, 0);

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

    /* If there are no more pending messages, inform eNB app */
    if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb == 0) {
      MessageDef                 *message_p;

      message_p = itti_alloc_new_message(TASK_S1AP, S1AP_REGISTER_ENB_CNF);
      S1AP_REGISTER_ENB_CNF(message_p).nb_mme = mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb;
      itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
186
    }
187
  }
188 189
}

190 191
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
                            const uint8_t * const data, const uint32_t data_length)
Cedric Roux's avatar
 
Cedric Roux committed
192
{
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
  struct s1ap_message_s message;

  DevAssert(data != NULL);

  memset(&message, 0, sizeof(struct s1ap_message_s));

  if (s1ap_eNB_decode_pdu(&message, data, data_length) < 0) {
    S1AP_ERROR("Failed to decode PDU\n");
    return -1;
  }

  /* Checking procedure Code and direction of message */
  if (message.procedureCode > sizeof(messages_callback) / (3 * sizeof(
        s1ap_message_decoded_callback))
      || (message.direction > S1AP_PDU_PR_unsuccessfulOutcome)) {
    S1AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n",
               assoc_id, message.procedureCode, message.direction);
    return -1;
  }

  /* No handler present.
   * This can mean not implemented or no procedure for eNB (wrong direction).
   */
  if (messages_callback[message.procedureCode][message.direction-1] == NULL) {
    S1AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n",
               assoc_id, message.procedureCode,
Raymond Knopp's avatar
Raymond Knopp committed
219
               s1ap_direction2String[message.direction]);
220 221 222 223 224 225
    return -1;
  }

  /* Calling the right handler */
  return (*messages_callback[message.procedureCode][message.direction-1])
         (assoc_id, stream, &message);
Cedric Roux's avatar
 
Cedric Roux committed
226 227
}

Cedric Roux's avatar
Cedric Roux committed
228
static
229 230 231 232
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
                                     struct s1ap_message_s *message_p)
{
233 234
  S1ap_S1SetupFailureIEs_t   *s1_setup_failure_p;
  s1ap_eNB_mme_data_t        *mme_desc_p;
235

236
  DevAssert(message_p != NULL);
237

238
  s1_setup_failure_p = &message_p->msg.s1ap_S1SetupFailureIEs;
239

240 241 242 243 244
  /* 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);
  }
245

246 247 248 249 250
  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;
  }
251

252 253 254 255 256 257
  if ((s1_setup_failure_p->cause.present == S1ap_Cause_PR_misc) &&
      (s1_setup_failure_p->cause.choice.misc == S1ap_CauseMisc_unspecified)) {
    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");
  }
258

259 260
  mme_desc_p->state = S1AP_ENB_STATE_WAITING;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);
261

262
  return 0;
263 264 265 266 267
}

static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
Cedric Roux's avatar
 
Cedric Roux committed
268 269
                                      struct s1ap_message_s *message_p)
{
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  S1ap_S1SetupResponseIEs_t *s1SetupResponse_p;
  s1ap_eNB_mme_data_t       *mme_desc_p;
  int i;

  DevAssert(message_p != NULL);

  s1SetupResponse_p = &message_p->msg.s1ap_S1SetupResponseIEs;

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

  /* 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.
   */
navid's avatar
navid committed
294 295 296 297
  S1AP_DEBUG("servedGUMMEIs.list.count %d\n",s1SetupResponse_p->servedGUMMEIs.list.count); 
  DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count > 0);
  DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count <= 8);

298 299 300 301 302 303 304 305 306 307 308 309 310

  for (i = 0; i < s1SetupResponse_p->servedGUMMEIs.list.count; i++) {
    struct S1ap_ServedGUMMEIsItem *gummei_item_p;
    struct served_gummei_s        *new_gummei_p;
    int j;

    gummei_item_p = (struct S1ap_ServedGUMMEIsItem *)
                    s1SetupResponse_p->servedGUMMEIs.list.array[i];
    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);
navid's avatar
navid committed
311 312
    
    S1AP_DEBUG("servedPLMNs.list.count %d\n",gummei_item_p->servedPLMNs.list.count);
313 314 315
    for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) {
      S1ap_PLMNidentity_t *plmn_identity_p;
      struct plmn_identity_s *new_plmn_identity_p;
navid's avatar
navid committed
316 317
      
      plmn_identity_p = gummei_item_p->servedPLMNs.list.array[j];
318 319 320 321 322 323
      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
324

325 326 327
    for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) {
      S1ap_MME_Group_ID_t           *mme_group_id_p;
      struct served_group_id_s *new_group_id_p;
Cedric Roux's avatar
 
Cedric Roux committed
328

navid's avatar
navid committed
329
      mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[j];
330 331 332 333
      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
334 335
    }

336 337 338
    for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) {
      S1ap_MME_Code_t        *mme_code_p;
      struct mme_code_s *new_mme_code_p;
Cedric Roux's avatar
 
Cedric Roux committed
339

navid's avatar
navid committed
340
      mme_code_p = gummei_item_p->servedMMECs.list.array[j];
341 342 343 344 345
      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
346
    }
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

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

  /* Free contents of the list */
  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1ap_ServedGUMMEIs,
                                (void *)&s1SetupResponse_p->servedGUMMEIs);
  /* Set the capacity of this MME */
  mme_desc_p->relative_mme_capacity = s1SetupResponse_p->relativeMMECapacity;

  /* Optionaly set the mme name */
  if (s1SetupResponse_p->presenceMask & S1AP_S1SETUPRESPONSEIES_MMENAME_PRESENT) {
    mme_desc_p->mme_name = calloc(s1SetupResponse_p->mmEname.size + 1, sizeof(char));
    memcpy(mme_desc_p->mme_name, s1SetupResponse_p->mmEname.buf,
           s1SetupResponse_p->mmEname.size);
    /* Convert the mme name to a printable string */
    mme_desc_p->mme_name[s1SetupResponse_p->mmEname.size] = '\0';
  }

  /* 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);
Cedric Roux's avatar
 
Cedric Roux committed
372

373
#if 0
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
  /* We call back our self
   * -> generate a dummy initial UE message
   */
  {
    s1ap_nas_first_req_t s1ap_nas_first_req;

    memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));

    s1ap_nas_first_req.rnti = 0xC03A;
    s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA;
    s1ap_nas_first_req.ue_identity.presenceMask = UE_IDENTITIES_gummei;

    s1ap_nas_first_req.ue_identity.gummei.mcc = 208;
    s1ap_nas_first_req.ue_identity.gummei.mnc = 34;
    s1ap_nas_first_req.ue_identity.gummei.mme_code = 0;
    s1ap_nas_first_req.ue_identity.gummei.mme_group_id = 0;

    /* NAS Attach request with IMSI */
    static uint8_t nas_attach_req_imsi[] = {
      0x07, 0x41,
      /* EPS Mobile identity = IMSI */
      0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
      0xF9,
      /* End of EPS Mobile Identity */
      0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
      0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
      0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
      0x01, 0x27, 0x11,
    };

    /* NAS Attach request with GUTI */
    static uint8_t nas_attach_req_guti[] = {
      0x07, 0x41,
      /* EPS Mobile identity = IMSI */
      0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
      0xDA, 0x1F,
      /* End of EPS Mobile Identity */
      0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
      0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
      0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
      0x01, 0x27, 0x11,
    };

    s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti;
    s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti);

    s1ap_eNB_handle_nas_first_req(mme_desc_p->s1ap_eNB_instance->instance,
                                  &s1ap_nas_first_req);
  }
425
#endif
Cedric Roux's avatar
 
Cedric Roux committed
426

427
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
428 429
}

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687

static
int s1ap_eNB_handle_error_indication(uint32_t               assoc_id,
                                     uint32_t               stream,
                                     struct s1ap_message_s *message_p)
{
  S1ap_ErrorIndicationIEs_t   *s1_error_indication_p;
  s1ap_eNB_mme_data_t        *mme_desc_p;

  DevAssert(message_p != NULL);

  s1_error_indication_p = &message_p->msg.s1ap_ErrorIndicationIEs;

  /* 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;
  }
  if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_MME_UE_S1AP_ID_PRESENT) {
	  	S1AP_WARN("Received S1 Error indication MME UE S1AP ID 0x%x\n", s1_error_indication_p->mme_ue_s1ap_id);
  }
  if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_ENB_UE_S1AP_ID_PRESENT) {
  	S1AP_WARN("Received S1 Error indication eNB UE S1AP ID 0x%x\n", s1_error_indication_p->eNB_UE_S1AP_ID);
  }

  if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) {
    switch(s1_error_indication_p->cause.present) {
      case S1ap_Cause_PR_NOTHING:
    	S1AP_WARN("Received S1 Error indication cause NOTHING\n");
      break;
      case S1ap_Cause_PR_radioNetwork:
      	switch (s1_error_indication_p->cause.choice.radioNetwork) {
	      case S1ap_CauseRadioNetwork_unspecified:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
            break;
  	      case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
            break;
  	      case S1ap_CauseRadioNetwork_successful_handover:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
            break;
  	      case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
            break;
  	      case S1ap_CauseRadioNetwork_handover_cancelled:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
            break;
  	      case S1ap_CauseRadioNetwork_partial_handover:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
            break;
  	      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");
            break;
  	      case S1ap_CauseRadioNetwork_ho_target_not_allowed:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
            break;
  	      case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
            break;
  	      case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
            break;
  	      case S1ap_CauseRadioNetwork_cell_not_available:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
            break;
  	      case S1ap_CauseRadioNetwork_unknown_targetID:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
            break;
  	      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");
            break;
  	      case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
            break;
  	      case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
            break;
  	      case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
            break;
  	      case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
            break;
  	      case S1ap_CauseRadioNetwork_time_critical_handover:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
            break;
  	      case S1ap_CauseRadioNetwork_resource_optimisation_handover:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
            break;
  	      case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
            break;
  	      case S1ap_CauseRadioNetwork_user_inactivity:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
            break;
  	      case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
            break;
  	      case S1ap_CauseRadioNetwork_load_balancing_tau_required:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
            break;
  	      case S1ap_CauseRadioNetwork_cs_fallback_triggered:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
            break;
  	      case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
            break;
  	      case S1ap_CauseRadioNetwork_radio_resources_not_available:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
            break;
  	      case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
            break;
  	      case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
            break;
  	      case S1ap_CauseRadioNetwork_interrat_redirection:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
            break;
  	      case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
            break;
  	      case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
            break;
  	      case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
            break;
  	      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");
            break;
  	      case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
            break;
  	      case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
            break;
  	      case S1ap_CauseRadioNetwork_x2_handover_triggered:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
            break;
  	      case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
            break;
  	      case S1ap_CauseRadioNetwork_not_supported_QCI_value:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
            break;
  	      case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
            S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
            break;
      	  default:
            S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
      	}
      break;

      case S1ap_Cause_PR_transport:
      	switch (s1_error_indication_p->cause.choice.transport) {
    	  case S1ap_CauseTransport_transport_resource_unavailable:
            S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
            break;
    	  case S1ap_CauseTransport_unspecified:
            S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
            break;
      	  default:
            S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
      	}
      break;

      case S1ap_Cause_PR_nas:
      	switch (s1_error_indication_p->cause.choice.nas) {
    	  case S1ap_CauseNas_normal_release:
            S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
            break;
      	  case S1ap_CauseNas_authentication_failure:
            S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
            break;
      	  case S1ap_CauseNas_detach:
            S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
            break;
      	  case S1ap_CauseNas_unspecified:
            S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
            break;
      	  case S1ap_CauseNas_csg_subscription_expiry:
            S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
            break;
      	  default:
            S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
      	}
      break;

      case S1ap_Cause_PR_protocol:
      	switch (s1_error_indication_p->cause.choice.protocol) {
      	  case S1ap_CauseProtocol_transfer_syntax_error:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
            break;
      	  case S1ap_CauseProtocol_abstract_syntax_error_reject:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
            break;
      	  case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
            break;
      	  case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
            break;
      	  case S1ap_CauseProtocol_semantic_error:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
            break;
      	  case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
            break;
      	  case S1ap_CauseProtocol_unspecified:
            S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
            break;
      	  default:
            S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
      	}
      break;

      case S1ap_Cause_PR_misc:
        switch (s1_error_indication_p->cause.choice.protocol) {
          case S1ap_CauseMisc_control_processing_overload:
            S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
            break;
          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;
          case S1ap_CauseMisc_hardware_failure:
        	S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
        	break;
          case S1ap_CauseMisc_om_intervention:
        	S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
        	break;
          case S1ap_CauseMisc_unspecified:
        	S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
        	break;
          case S1ap_CauseMisc_unknown_PLMN:
        	S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
        	break;
          default:
            S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
        }
      break;
    }
  }
  if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) {
    // TODO continue
  }
  // TODO continue

  return 0;
}


688 689
static
int s1ap_eNB_handle_initial_context_request(uint32_t               assoc_id,
690 691
    uint32_t               stream,
    struct s1ap_message_s *s1ap_message_p)
Cedric Roux's avatar
 
Cedric Roux committed
692
{
693
  int i;
694

695 696 697
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;
Cedric Roux's avatar
 
Cedric Roux committed
698

699 700
  S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
  DevAssert(s1ap_message_p != NULL);
Cedric Roux's avatar
 
Cedric Roux committed
701

702
  initialContextSetupRequest_p = &s1ap_message_p->msg.s1ap_InitialContextSetupRequestIEs;
Cedric Roux's avatar
 
Cedric Roux committed
703

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

710 711 712 713 714 715 716
  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
                   initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
               "existing UE context 0x%06x\n", assoc_id,
               initialContextSetupRequest_p->eNB_UE_S1AP_ID);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
717

718
  /* Initial context request = UE-related procedure -> stream != 0 */
719 720 721
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
               assoc_id, stream);
722 723
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
724

725 726
  ue_desc_p->rx_stream = stream;

727
  ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id;
728

729
  message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ);
730

731 732 733 734 735
  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;
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_e_rabs =
736 737
    initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.count;

738 739
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul = 64;// TO DO(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL);
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl = 1024;//(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL);
740

741
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms =
742
    BIT_STRING_to_uint16(&initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms);
743
  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
744 745
    BIT_STRING_to_uint16(&initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms);

746 747 748
  /* Copy the security key */
  memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
         initialContextSetupRequest_p->securityKey.buf, initialContextSetupRequest_p->securityKey.size);
749

750 751
  for (i = 0; i < initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.count; i++) {
    S1ap_E_RABToBeSetupItemCtxtSUReq_t *item_p;
752

753
    item_p = (S1ap_E_RABToBeSetupItemCtxtSUReq_t *)initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.array[i];
754

755
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].e_rab_id = item_p->e_RAB_ID;
756

757 758 759
    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;
760

761 762
      S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer =
        malloc(sizeof(uint8_t) * item_p->nAS_PDU->size);
763

764 765 766 767 768 769
      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);
    } 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;
    }
770

771 772 773 774 775
    /* 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;
776

777 778
    /* 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);
779

780 781
    /* Set the QOS informations */
    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI;
782

783 784 785 786 787 788 789
    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;
  }
790

791
  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
792

793
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
794
}
795 796 797


static
Lionel Gauthier's avatar
 
Lionel Gauthier committed
798
int s1ap_eNB_handle_ue_context_release_command(uint32_t               assoc_id,
799 800
    uint32_t               stream,
    struct s1ap_message_s *s1ap_message_p)
801
{
802 803 804 805 806 807 808 809 810 811 812 813 814 815
  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
  MessageDef            *message_p        = NULL;

  S1ap_UEContextReleaseCommandIEs_t *ueContextReleaseCommand_p;
  DevAssert(s1ap_message_p != NULL);

  ueContextReleaseCommand_p = &s1ap_message_p->msg.s1ap_UEContextReleaseCommandIEs;

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

817 818
  S1ap_MME_UE_S1AP_ID_t    mme_ue_s1ap_id;
  S1ap_ENB_UE_S1AP_ID_t    enb_ue_s1ap_id;
819

820 821 822 823
  switch (ueContextReleaseCommand_p->uE_S1AP_IDs.present) {
  case S1ap_UE_S1AP_IDs_PR_uE_S1AP_ID_pair:
    enb_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
    mme_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
824

Raymond Knopp's avatar
Raymond Knopp committed
825 826 827 828 829 830 831 832 833
    MSC_LOG_RX_MESSAGE(
    		MSC_S1AP_ENB,
    		MSC_S1AP_MME,
    		NULL,0,
    		"0 UEContextRelease/%s eNB_ue_s1ap_id "S1AP_UE_ID_FMT" mme_ue_s1ap_id "S1AP_UE_ID_FMT" len %u",
  		s1ap_direction2String[s1ap_message_p->direction],
  		enb_ue_s1ap_id,
  		mme_ue_s1ap_id);

834 835 836 837 838 839 840 841 842 843 844 845 846
    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%06x\n",
                 assoc_id,
                 enb_ue_s1ap_id);
      /*MessageDef *msg_complete_p;
      msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
      S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
      itti_send_msg_to_task(TASK_S1AP, ue_desc_p->eNB_instance->instance <=> 0, msg_complete_p);
      */
      return -1;
    } else {
Raymond Knopp's avatar
Raymond Knopp committed
847 848 849 850
      MSC_LOG_TX_MESSAGE(
    		  MSC_S1AP_ENB,
    		  MSC_RRC_ENB,
    		  NULL,0,
Cedric Roux's avatar
Cedric Roux committed
851
    		  "0 S1AP_UE_CONTEXT_RELEASE_COMMAND/%d eNB_ue_s1ap_id "S1AP_UE_ID_FMT" ",
Raymond Knopp's avatar
Raymond Knopp committed
852 853
    		  enb_ue_s1ap_id);

854 855 856 857
      message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND);
      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;
858 859
    }

860
    break;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
861 862

#warning "TODO mapping mme_ue_s1ap_id  enb_ue_s1ap_id?"
863 864 865 866 867 868 869 870 871 872

  case S1ap_UE_S1AP_IDs_PR_mME_UE_S1AP_ID:
    mme_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.mME_UE_S1AP_ID;
    S1AP_ERROR("TO DO mapping mme_ue_s1ap_id  enb_ue_s1ap_id");

  case S1ap_UE_S1AP_IDs_PR_NOTHING:
  default:
    S1AP_ERROR("S1AP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements");
    return -1;
  }
873 874
}