text: /*
   * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The OpenAirInterface Software Alliance licenses this file to You under
   * the OAI Public License, Version 1.1  (the "License"); you may not use this file
   * except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.openairinterface.org/?page_id=698
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *-------------------------------------------------------------------------------
   * For more information about the OpenAirInterface (OAI) Software Alliance:
   *      contact@openairinterface.org
   */
  
  /*! \file ngap_gNB_handlers.c
   * \brief ngap messages handlers for gNB part
   * \author Yoshio INOUE, Masayuki HARADA
   * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
   * \date 2020
   * \version 0.1
   */
   
  #include <stdint.h>
  
  #include "intertask_interface.h"
  
  #include "asn1_conversions.h"
  
  #include "ngap_common.h"
  // #include "ngap_gNB.h"
  #include "ngap_gNB_defs.h"
  #include "ngap_gNB_handlers.h"
  #include "ngap_gNB_decoder.h"
  
  #include "ngap_gNB_ue_context.h"
  #include "ngap_gNB_trace.h"
  #include "ngap_gNB_nas_procedures.h"
  #include "ngap_gNB_management_procedures.h"
  
  #include "ngap_gNB_default_values.h"
  
  #include "assertions.h"
  #include "conversions.h"
  #include "NGAP_NonDynamic5QIDescriptor.h"
  
  static
  int ngap_gNB_handle_ng_setup_response(uint32_t               assoc_id,
                                        uint32_t               stream,
                                        NGAP_NGAP_PDU_t       *pdu);
  static
  int ngap_gNB_handle_ng_setup_failure(uint32_t               assoc_id,
                                       uint32_t               stream,
                                       NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_error_indication(uint32_t               assoc_id,
                                       uint32_t               stream,
                                       NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_initial_context_request(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_ue_context_release_command(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_pdusession_setup_request(uint32_t               assoc_id,
                                          uint32_t               stream,
                                          NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_paging(uint32_t               assoc_id,
                             uint32_t               stream,
                             NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_pdusession_modify_request(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_pdusession_release_command(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_ng_path_switch_request_ack(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_ng_path_switch_request_failure(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  static
  int ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu);
  
  /* Handlers matrix. Only gNB related procedure present here */
  ngap_message_decoded_callback ngap_messages_callback[][3] = {
    { 0, 0, 0 }, /* AMFConfigurationUpdate */
    { 0, 0, 0 }, /* AMFStatusIndication */
    { 0, 0, 0 }, /* CellTrafficTrace */
    { ngap_gNB_handle_deactivate_trace, 0, 0 }, /* DeactivateTrace */
    { ngap_gNB_handle_nas_downlink, 0, 0 }, /* DownlinkNASTransport */
    { 0, 0, 0 }, /* DownlinkNonUEAssociatedNRPPaTransport */
    { 0, 0, 0 }, /* DownlinkRANConfigurationTransfer */
    { 0, 0, 0 }, /* DownlinkRANStatusTransfer */
    { 0, 0, 0 }, /* DownlinkUEAssociatedNRPPaTransport */
    { ngap_gNB_handle_error_indication, 0, 0 }, /* ErrorIndication */
    { 0, 0, 0 }, /* HandoverCancel */
    { 0, 0, 0 }, /* HandoverNotification */
    { 0, 0, 0 }, /* HandoverPreparation */
    { 0, 0, 0 }, /* HandoverResourceAllocation */
    { ngap_gNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */
    { 0, 0, 0 }, /* InitialUEMessage */
    { 0, 0, 0 }, /* LocationReportingControl */
    { 0, 0, 0 }, /* LocationReportingFailureIndication */
    { 0, 0, 0 }, /* LocationReport */
    { 0, 0, 0 }, /* NASNonDeliveryIndication */
    { 0, 0, 0 }, /* NGReset */
    { 0, ngap_gNB_handle_ng_setup_response, ngap_gNB_handle_ng_setup_failure }, /* NGSetup */
    { 0, 0, 0 }, /* OverloadStart */
    { 0, 0, 0 }, /* OverloadStop */
    { ngap_gNB_handle_paging, 0, 0 }, /* Paging */
    { 0, ngap_gNB_handle_ng_path_switch_request_ack, ngap_gNB_handle_ng_path_switch_request_failure }, /* PathSwitchRequest */
    { ngap_gNB_handle_pdusession_modify_request, 0, 0 }, /* PDUSessionResourceModify */
    { 0, ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm, 0 }, /* PDUSessionResourceModifyIndication */
    { ngap_gNB_handle_pdusession_release_command, 0, 0 }, /* PDUSessionResourceRelease */
    { ngap_gNB_handle_pdusession_setup_request, 0, 0 }, /* PDUSessionResourceSetup */
    { 0, 0, 0 }, /* PDUSessionResourceNotify */
    { 0, 0, 0 }, /* PrivateMessage */
    { 0, 0, 0 }, /* PWSCancel */
    { 0, 0, 0 }, /* PWSFailureIndication */
    { 0, 0, 0 }, /* PWSRestartIndication */
    { 0, 0, 0 }, /* RANConfigurationUpdate */
    { 0, 0, 0 }, /* RerouteNASRequest */
    { 0, 0, 0 }, /* RRCInactiveTransitionReport */
    { 0, 0, 0 }, /* TraceFailureIndication */
    { ngap_gNB_handle_trace_start, 0, 0 }, /* TraceStart */
    { 0, 0, 0 }, /* UEContextModification */
    { ngap_gNB_handle_ue_context_release_command, 0, 0 }, /* UEContextRelease */
    { 0, 0, 0 }, /* UEContextReleaseRequest */
    { 0, 0, 0 }, /* UERadioCapabilityCheck */
    { 0, 0, 0 }, /* UERadioCapabilityInfoIndication */
    { 0, 0, 0 }, /* UETNLABindingRelease */
    { 0, 0, 0 }, /* UplinkNASTransport */
    { 0, 0, 0 }, /* UplinkNonUEAssociatedNRPPaTransport */
    { 0, 0, 0 }, /* UplinkRANConfigurationTransfer */
    { 0, 0, 0 }, /* UplinkRANStatusTransfer */
    { 0, 0, 0 }, /* UplinkUEAssociatedNRPPaTransport */
    { 0, 0, 0 }, /* WriteReplaceWarning */
    { 0, 0, 0 }, /* SecondaryRATDataUsageReport */
  
  };
  char *ngap_direction2String(int ngap_dir) {
    static char *ngap_direction_String[] = {
      "", /* Nothing */
      "Originating message", /* originating message */
      "Successfull outcome", /* successfull outcome */
      "UnSuccessfull outcome", /* successfull outcome */
    };
    return(ngap_direction_String[ngap_dir]);
  }
  void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shutdown) {
    if (sctp_shutdown) {
      /* A previously connected AMF has been shutdown */
  
      /* TODO check if it was used by some gNB and send a message to inform these gNB if there is no more associated AMF */
      if (amf_desc_p->state == NGAP_GNB_STATE_CONNECTED) {
        amf_desc_p->state = NGAP_GNB_STATE_DISCONNECTED;
  
        if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb > 0) {
          /* Decrease associated AMF number */
          amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb --;
        }
  
        /* If there are no more associated AMF, inform gNB app */
        if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb == 0) {
          MessageDef                 *message_p;
          message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND);
          NGAP_DEREGISTERED_GNB_IND(message_p).nb_amf = 0;
          itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p);
        }
      }
    } else {
      /* Check that at least one setup message is pending */
      DevCheck(amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0, amf_desc_p->ngap_gNB_instance->instance,
               amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb, 0);
  
      if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0) {
        /* Decrease pending messages number */
        amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb --;
      }
  
      /* If there are no more pending messages, inform gNB app */
      if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb == 0) {
        MessageDef                 *message_p;
        message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF);
        NGAP_REGISTER_GNB_CNF(message_p).nb_amf = amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb;
        itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p);
      }
    }
  }
  
  int ngap_gNB_handle_message(uint32_t assoc_id, int32_t stream,
                              const uint8_t *const data, const uint32_t data_length) {
    NGAP_NGAP_PDU_t pdu;
    int ret;
    DevAssert(data != NULL);
    memset(&pdu, 0, sizeof(pdu));
  
    if (ngap_gNB_decode_pdu(&pdu, data, data_length) < 0) {
      NGAP_ERROR("Failed to decode PDU\n");
      return -1;
    }
  
    /* Checking procedure Code and direction of message */
    if (pdu.choice.initiatingMessage->procedureCode >= sizeof(ngap_messages_callback) / (3 * sizeof(
          ngap_message_decoded_callback))
        || (pdu.present > NGAP_NGAP_PDU_PR_unsuccessfulOutcome)) {
      NGAP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
                 assoc_id, pdu.choice.initiatingMessage->procedureCode, pdu.present);
      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
      return -1;
    }
  
    /* No handler present.
     * This can mean not implemented or no procedure for gNB (wrong direction).
     */
    if (ngap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1] == NULL) {
      NGAP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
                 assoc_id, pdu.choice.initiatingMessage->procedureCode,
                 ngap_direction2String(pdu.present - 1));
      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
      return -1;
    }
  
    /* Calling the right handler */
    ret = (*ngap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])
          (assoc_id, stream, &pdu);
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
    return ret;
  }
  
  static
  int ngap_gNB_handle_ng_setup_failure(uint32_t               assoc_id,
                                       uint32_t               stream,
                                       NGAP_NGAP_PDU_t       *pdu) {
    NGAP_NGSetupFailure_t      *container;
    NGAP_NGSetupFailureIEs_t   *ie;
    ngap_gNB_amf_data_t        *amf_desc_p;
    DevAssert(pdu != NULL);
    container = &pdu->choice.unsuccessfulOutcome->value.choice.NGSetupFailure;
  
    /* S1 Setup Failure == Non UE-related procedure -> stream 0 */
    if (stream != 0) {
      NGAP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
                assoc_id, stream);
    }
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received S1 setup response for non existing "
                 "AMF context\n", assoc_id);
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupFailureIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_Cause,true);
  
    if ((ie->value.choice.Cause.present == NGAP_Cause_PR_misc) &&
        (ie->value.choice.Cause.choice.misc == NGAP_CauseMisc_unspecified)) {
      NGAP_WARN("Received NG setup failure for AMF... AMF is not ready\n");
    } else {
      NGAP_ERROR("Received NG setup failure for AMF... please check your parameters\n");
    }
  
    amf_desc_p->state = NGAP_GNB_STATE_WAITING;
    ngap_handle_ng_setup_message(amf_desc_p, 0);
    return 0;
  }
  
  static
  int ngap_gNB_handle_ng_setup_response(uint32_t               assoc_id,
                                        uint32_t               stream,
                                        NGAP_NGAP_PDU_t       *pdu) {
    NGAP_NGSetupResponse_t    *container;
    NGAP_NGSetupResponseIEs_t *ie;
    ngap_gNB_amf_data_t       *amf_desc_p;
    int i;
    DevAssert(pdu != NULL);
    container = &pdu->choice.successfulOutcome->value.choice.NGSetupResponse;
  
    /* NG Setup Response == Non UE-related procedure -> stream 0 */
    if (stream != 0) {
      NGAP_ERROR("[SCTP %d] Received ng setup response on stream != 0 (%d)\n",
                 assoc_id, stream);
      return -1;
    }
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received NG setup response for non existing "
                 "AMF context\n", assoc_id);
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_ServedGUAMIList, true);
  
    /* The list of served guami can contain at most 256 elements.
     * NR related guami is the first element in the list, i.e with an id of 0.
     */
    NGAP_DEBUG("servedGUAMIs.list.count %d\n", ie->value.choice.ServedGUAMIList.list.count);
    DevAssert(ie->value.choice.ServedGUAMIList.list.count > 0);
    DevAssert(ie->value.choice.ServedGUAMIList.list.count <= NGAP_maxnoofServedGUAMIs);
  
    for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) {
      NGAP_ServedGUAMIItem_t  *guami_item_p;
      struct served_guami_s   *new_guami_p;
  
      guami_item_p = ie->value.choice.ServedGUAMIList.list.array[i];
      new_guami_p = calloc(1, sizeof(struct served_guami_s));
      STAILQ_INIT(&new_guami_p->served_plmns);
      STAILQ_INIT(&new_guami_p->served_region_ids);
      STAILQ_INIT(&new_guami_p->amf_set_ids);
      STAILQ_INIT(&new_guami_p->amf_pointers);
      
      NGAP_PLMNIdentity_t *plmn_identity_p;
      struct plmn_identity_s *new_plmn_identity_p;
      plmn_identity_p = &guami_item_p->gUAMI.pLMNIdentity;
      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_guami_p->served_plmns, new_plmn_identity_p, next);
      new_guami_p->nb_served_plmns++;
      
      NGAP_AMFRegionID_t        *amf_region_id_p;
      struct served_region_id_s *new_region_id_p;
      amf_region_id_p = &guami_item_p->gUAMI.aMFRegionID;
      new_region_id_p = calloc(1, sizeof(struct served_region_id_s));
      OCTET_STRING_TO_INT8(amf_region_id_p, new_region_id_p->amf_region_id);
      STAILQ_INSERT_TAIL(&new_guami_p->served_region_ids, new_region_id_p, next);
      new_guami_p->nb_region_id++;
  
      NGAP_AMFSetID_t        *amf_set_id_p;
      struct amf_set_id_s    *new_amf_set_id_p;
      amf_set_id_p = &guami_item_p->gUAMI.aMFSetID;
      new_amf_set_id_p = calloc(1, sizeof(struct amf_set_id_s));
      OCTET_STRING_TO_INT16(amf_set_id_p, new_amf_set_id_p->amf_set_id);
      STAILQ_INSERT_TAIL(&new_guami_p->amf_set_ids, new_amf_set_id_p, next);
      new_guami_p->nb_amf_set_id++;
  
      NGAP_AMFPointer_t        *amf_pointer_p;
      struct amf_pointer_s     *new_amf_pointer_p;
      amf_pointer_p = &guami_item_p->gUAMI.aMFPointer;
      new_amf_pointer_p = calloc(1, sizeof(struct amf_pointer_s));
      OCTET_STRING_TO_INT8(amf_pointer_p, new_amf_pointer_p->amf_pointer);
      STAILQ_INSERT_TAIL(&new_guami_p->amf_pointers, new_amf_pointer_p, next);
      new_guami_p->nb_amf_pointer++;
  
      STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, new_guami_p, next);
    }
  
    /* Set the capacity of this AMF */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_RelativeAMFCapacity, true);
  
    amf_desc_p->relative_amf_capacity = ie->value.choice.RelativeAMFCapacity;
  
    /* mandatory set the amf name */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMFName, true);
  
    if (ie) {
      amf_desc_p->amf_name = calloc(ie->value.choice.AMFName.size + 1, sizeof(char));
      memcpy(amf_desc_p->amf_name, ie->value.choice.AMFName.buf,
             ie->value.choice.AMFName.size);
      /* Convert the amf name to a printable string */
      amf_desc_p->amf_name[ie->value.choice.AMFName.size] = '\0';
    }
  
    
    /* mandatory set the plmn supports */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
                                 NGAP_ProtocolIE_ID_id_PLMNSupportList, true);
  
    NGAP_DEBUG("PLMNSupportList.list.count %d\n", ie->value.choice.PLMNSupportList.list.count);
    DevAssert(ie->value.choice.PLMNSupportList.list.count > 0);
    DevAssert(ie->value.choice.PLMNSupportList.list.count <= NGAP_maxnoofPLMNs);
  
    STAILQ_INIT(&amf_desc_p->plmn_supports);
  
    for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) {
      NGAP_PLMNSupportItem_t *plmn_support_item_p;
      struct plmn_support_s  *new_plmn_support_p;
      NGAP_SliceSupportItem_t  *slice_support_item_p;
      struct slice_support_s *new_slice_support_p;
  
      plmn_support_item_p = ie->value.choice.PLMNSupportList.list.array[i];
  
      new_plmn_support_p = calloc(1, sizeof(struct plmn_support_s));
      
      TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, new_plmn_support_p->plmn_identity.mcc,
                      new_plmn_support_p->plmn_identity.mnc, new_plmn_support_p->plmn_identity.mnc_digit_length);
  
      NGAP_DEBUG("PLMNSupportList.list.count %d\n", plmn_support_item_p->sliceSupportList.list.count);
      DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0);
      DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems);
  
      STAILQ_INIT(&new_plmn_support_p->slice_supports);
      for(int j=0; j<plmn_support_item_p->sliceSupportList.list.count; j++) {
        slice_support_item_p = plmn_support_item_p->sliceSupportList.list.array[j];
        
        new_slice_support_p = calloc(1, sizeof(struct slice_support_s));
  
        OCTET_STRING_TO_INT8(&slice_support_item_p->s_NSSAI.sST, new_slice_support_p->sST);
  
        if(slice_support_item_p->s_NSSAI.sD != NULL) {
          new_slice_support_p->sD_flag = 1;
          new_slice_support_p->sD[0] = slice_support_item_p->s_NSSAI.sD->buf[0];
          new_slice_support_p->sD[1] = slice_support_item_p->s_NSSAI.sD->buf[1];
          new_slice_support_p->sD[2] = slice_support_item_p->s_NSSAI.sD->buf[2];
        }
        STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next);
      }
  
      STAILQ_INSERT_TAIL(&amf_desc_p->plmn_supports, new_plmn_support_p, next);
    }
  
    /* The association is now ready as gNB and AMF know parameters of each other.
     * Mark the association as UP to enable UE contexts creation.
     */
    amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
    amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb ++;
    ngap_handle_ng_setup_message(amf_desc_p, 0);
  
    return 0;
  }
  
  
  static
  int ngap_gNB_handle_error_indication(uint32_t         assoc_id,
                                       uint32_t         stream,
                                       NGAP_NGAP_PDU_t *pdu) {
  
    NGAP_ErrorIndication_t    *container;
    NGAP_ErrorIndicationIEs_t *ie;
    ngap_gNB_amf_data_t        *amf_desc_p;
    uint64_t                 amf_ue_ngap_id;
      
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.ErrorIndication;
  
    /* NG Setup Failure == Non UE-related procedure -> stream 0 */
    if (stream != 0) {
      NGAP_WARN("[SCTP %d] Received ng Error indication on stream != 0 (%d)\n",
                assoc_id, stream);
    }
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received ng Error indication for non existing "
                 "AMF context\n", assoc_id);
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, false);
  
    /* optional */
    if (ie != NULL) {
      asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
      NGAP_WARN("Received NG Error indication AMF UE NGAP ID 0x%lx\n", amf_ue_ngap_id);
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, false);
  
    /* optional */
    if (ie != NULL) {
      NGAP_WARN("Received NG Error indication gNB UE NGAP ID 0x%lx\n", ie->value.choice.RAN_UE_NGAP_ID);
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_Cause, false);
  
    /* optional */
    if (ie) {
      switch(ie->value.choice.Cause.present) {
        case NGAP_Cause_PR_NOTHING:
          NGAP_WARN("Received NG Error indication cause NOTHING\n");
          break;
  
        case NGAP_Cause_PR_radioNetwork:
          switch (ie->value.choice.Cause.choice.radioNetwork) {
            case NGAP_CauseRadioNetwork_unspecified:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unspecified\n");
              break;
  
            case NGAP_CauseRadioNetwork_txnrelocoverall_expiry:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_txnrelocoverall_expiry\n");
              break;
  
            case NGAP_CauseRadioNetwork_successful_handover:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_successful_handover\n");
              break;
  
            case NGAP_CauseRadioNetwork_release_due_to_ngran_generated_reason:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_ngran_generated_reason\n");
              break;
            
            case NGAP_CauseRadioNetwork_release_due_to_5gc_generated_reason:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_5gc_generated_reason\n");
              break;
  
            case NGAP_CauseRadioNetwork_handover_cancelled:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_handover_cancelled\n");
              break;
  
            case NGAP_CauseRadioNetwork_partial_handover:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_partial_handover\n");
              break;
  
            case NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system\n");
              break;
  
            case NGAP_CauseRadioNetwork_ho_target_not_allowed:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ho_target_not_allowed\n");
              break;
  
            case NGAP_CauseRadioNetwork_tngrelocoverall_expiry:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_tngrelocoverall_expiry\n");
              break;
  
            case NGAP_CauseRadioNetwork_tngrelocprep_expiry:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_tngrelocprep_expiry\n");
              break;
  
            case NGAP_CauseRadioNetwork_cell_not_available:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_cell_not_available\n");
              break;
  
            case NGAP_CauseRadioNetwork_unknown_targetID:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_targetID\n");
              break;
  
            case NGAP_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
              break;
  
            case NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID\n");
              break;
  
            case NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID\n");
              break;
  
            case NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
              break;
  
            case NGAP_CauseRadioNetwork_time_critical_handover:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_time_critical_handover\n");
              break;
  
            case NGAP_CauseRadioNetwork_resource_optimisation_handover:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_resource_optimisation_handover\n");
              break;
  
            case NGAP_CauseRadioNetwork_reduce_load_in_serving_cell:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_reduce_load_in_serving_cell\n");
              break;
  
            case NGAP_CauseRadioNetwork_user_inactivity:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_user_inactivity\n");
              break;
  
            case NGAP_CauseRadioNetwork_radio_connection_with_ue_lost:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_radio_connection_with_ue_lost\n");
              break;
  
            case NGAP_CauseRadioNetwork_radio_resources_not_available:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_radio_resources_not_available\n");
              break;
  
            case NGAP_CauseRadioNetwork_invalid_qos_combination:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_invalid_qos_combination\n");
              break;
  
            case NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
              break;
  
            case NGAP_CauseRadioNetwork_interaction_with_other_procedure:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_interaction_with_other_procedure\n");
              break;
  
            case NGAP_CauseRadioNetwork_unknown_PDU_session_ID:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_PDU_session_ID\n");
              break;
  
            case NGAP_CauseRadioNetwork_unkown_qos_flow_ID:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unkown_qos_flow_ID\n");
              break;
  
            case NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances\n");
              break;
  
            case NGAP_CauseRadioNetwork_multiple_qos_flow_ID_instances:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_qos_flow_ID_instances\n");
              break;
  
            case NGAP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
              break;
  
            case NGAP_CauseRadioNetwork_ng_intra_system_handover_triggered:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ng_intra_system_handover_triggered\n");
              break;
  
            case NGAP_CauseRadioNetwork_ng_inter_system_handover_triggered:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ng_inter_system_handover_triggered\n");
              break;
  
            case NGAP_CauseRadioNetwork_xn_handover_triggered:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_xn_handover_triggered\n");
              break;
  
            case NGAP_CauseRadioNetwork_not_supported_5QI_value:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_not_supported_5QI_value\n");
              break;
  
            case NGAP_CauseRadioNetwork_ue_context_transfer:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_context_transfer\n");
              break;
  
            case NGAP_CauseRadioNetwork_ims_voice_eps_fallback_or_rat_fallback_triggered:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ims_voice_eps_fallback_or_rat_fallback_triggered\n");
              break;
  
            case NGAP_CauseRadioNetwork_up_integrity_protection_not_possible:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_up_integrity_protection_not_possible\n");
              break;
  
            case NGAP_CauseRadioNetwork_up_confidentiality_protection_not_possible:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_up_confidentiality_protection_not_possible\n");
              break;
  
            case NGAP_CauseRadioNetwork_slice_not_supported:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_slice_not_supported\n");
              break;
  
            case NGAP_CauseRadioNetwork_ue_in_rrc_inactive_state_not_reachable:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_in_rrc_inactive_state_not_reachable\n");
              break;
  
            case NGAP_CauseRadioNetwork_redirection:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_redirection\n");
              break;
  
            case NGAP_CauseRadioNetwork_resources_not_available_for_the_slice:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_resources_not_available_for_the_slice\n");
              break;
  
            case NGAP_CauseRadioNetwork_ue_max_integrity_protected_data_rate_reason:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_max_integrity_protected_data_rate_reason\n");
              break;
  
            case NGAP_CauseRadioNetwork_release_due_to_cn_detected_mobility:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_cn_detected_mobility\n");
              break;
  
            case NGAP_CauseRadioNetwork_n26_interface_not_available:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_n26_interface_not_available\n");
              break;
  
            case NGAP_CauseRadioNetwork_release_due_to_pre_emption:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_pre_emption\n");
              break;
  
            case NGAP_CauseRadioNetwork_multiple_location_reporting_reference_ID_instances:
              NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_location_reporting_reference_ID_instances\n");
              break;
  
            default:
              NGAP_WARN("Received NG Error indication cause radio network case not handled\n");
          }
  
          break;
  
        case NGAP_Cause_PR_transport:
          switch (ie->value.choice.Cause.choice.transport) {
            case NGAP_CauseTransport_transport_resource_unavailable:
              NGAP_WARN("Received NG Error indication NGAP_CauseTransport_transport_resource_unavailable\n");
              break;
  
            case NGAP_CauseTransport_unspecified:
              NGAP_WARN("Received NG Error indication NGAP_CauseTransport_unspecified\n");
              break;
  
            default:
              NGAP_WARN("Received NG Error indication cause transport case not handled\n");
          }
  
          break;
  
        case NGAP_Cause_PR_nas:
          switch (ie->value.choice.Cause.choice.nas) {
            case NGAP_CauseNas_normal_release:
              NGAP_WARN("Received NG Error indication NGAP_CauseNas_normal_release\n");
              break;
  
            case NGAP_CauseNas_authentication_failure:
              NGAP_WARN("Received NG Error indication NGAP_CauseNas_authentication_failure\n");
              break;
  
            case NGAP_CauseNas_deregister:
              NGAP_WARN("Received NG Error indication NGAP_CauseNas_deregister\n");
              break;
  
            case NGAP_CauseNas_unspecified:
              NGAP_WARN("Received NG Error indication NGAP_CauseNas_unspecified\n");
              break;
  
            default:
              NGAP_WARN("Received NG Error indication cause nas case not handled\n");
          }
  
          break;
  
        case NGAP_Cause_PR_protocol:
          switch (ie->value.choice.Cause.choice.protocol) {
            case NGAP_CauseProtocol_transfer_syntax_error:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_transfer_syntax_error\n");
              break;
  
            case NGAP_CauseProtocol_abstract_syntax_error_reject:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_reject\n");
              break;
  
            case NGAP_CauseProtocol_abstract_syntax_error_ignore_and_notify:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
              break;
  
            case NGAP_CauseProtocol_message_not_compatible_with_receiver_state:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_message_not_compatible_with_receiver_state\n");
              break;
  
            case NGAP_CauseProtocol_semantic_error:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_semantic_error\n");
              break;
  
            case NGAP_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
              break;
  
            case NGAP_CauseProtocol_unspecified:
              NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_unspecified\n");
              break;
  
            default:
              NGAP_WARN("Received NG Error indication cause protocol case not handled\n");
          }
  
          break;
  
        case NGAP_Cause_PR_misc:
          switch (ie->value.choice.Cause.choice.protocol) {
            case NGAP_CauseMisc_control_processing_overload:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_control_processing_overload\n");
              break;
  
            case NGAP_CauseMisc_not_enough_user_plane_processing_resources:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_not_enough_user_plane_processing_resources\n");
              break;
  
            case NGAP_CauseMisc_hardware_failure:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_hardware_failure\n");
              break;
  
            case NGAP_CauseMisc_om_intervention:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_om_intervention\n");
              break;
  
            case NGAP_CauseMisc_unspecified:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_unspecified\n");
              break;
  
            case NGAP_CauseMisc_unknown_PLMN:
              NGAP_WARN("Received NG Error indication NGAP_CauseMisc_unknown_PLMN\n");
              break;
  
            default:
              NGAP_WARN("Received NG Error indication cause misc case not handled\n");
          }
  
          break;
          
        default:
         NGAP_WARN("Received NG Error indication cause NGAP_Cause_PR_choice_Extensions\n");
         break;
        
      }
    }
  
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
  
    if (ie) {
      // TODO continue
    }
  
  
    // TODO continue
    return 0;
  }
  
  
  static
  int ngap_gNB_handle_initial_context_request(uint32_t   assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
  
    int i;
    ngap_gNB_amf_data_t   *amf_desc_p       = NULL;
    ngap_gNB_ue_context_t *ue_desc_p        = NULL;
    MessageDef            *message_p        = NULL;
    NGAP_InitialContextSetupRequest_t    *container;
    NGAP_InitialContextSetupRequestIEs_t *ie;
    NGAP_RAN_UE_NGAP_ID_t    ran_ue_ngap_id;
    uint64_t                 amf_ue_ngap_id;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.InitialContextSetupRequest;
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received initial context setup request for non "
                 "existing AMF context\n", assoc_id);
      return -1;
    }
  
    /* id-AMF-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
    } else {
      return -1;
    }
  
    /* id-RAN-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      ran_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
  
      if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance,
                       ran_ue_ngap_id)) == NULL) {
        NGAP_ERROR("[SCTP %d] Received initial context setup request for non "
                   "existing UE context 0x%06lx\n", assoc_id,
                   ran_ue_ngap_id);
        return -1;
      }
    } else {
      return -1;
    }
  
    /* Initial context request = UE-related procedure -> stream != 0 */
    //if (stream == 0) {
    //  NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
    //             assoc_id, stream);
    //  return -1;
    //}
  
    ue_desc_p->rx_stream = stream;
    ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id;
    
    message_p        = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ);
    NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
    ue_desc_p->ue_initial_id = 0;
    NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id;
    NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id;
    /* id-UEAggregateMaximumBitRate */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL),
                        &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul));
      asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL),
                        &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl));
    } else {
      NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n");
    }
  
  
    /* id-GUAMI */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_GUAMI, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mcc,
                      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc_len);
      
      OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_region_id);
      OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_set_id);
      OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_pointer);
    } else {/* ie != NULL */
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_pdusessions =
        ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count;
  
      for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) {
        NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p;
        asn_dec_rval_t                           dec_rval;
        NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer_p = NULL;
        NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL;
          
        item_p = (NGAP_PDUSessionResourceSetupItemCxtReq_t *)ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
        NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].pdusession_id = item_p->pDUSessionID;
  
        if (item_p->nAS_PDU != NULL) {
          /* Only copy NAS pdu if present */
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size;
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer =
            malloc(sizeof(uint8_t) * item_p->nAS_PDU->size);
          memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer,
                 item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
          NGAP_DEBUG("Received NAS message with the PDUSESSION setup procedure\n");
        } else {
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = 0;
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = NULL;
        }
  
  
        dec_rval = aper_decode(NULL,
                                 &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
                                 (void **)&pdusessionTransfer_p,
                                 item_p->pDUSessionResourceSetupRequestTransfer.buf,
                                 item_p->pDUSessionResourceSetupRequestTransfer.size, 0, 0);
  
        if(dec_rval.code != RC_OK) {
          NGAP_ERROR("could not decode PDUSessionResourceSetupRequestTransfer\n");
          return -1;
        }
  
        for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) {
          pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j];
          switch(pdusessionTransfer_ies->id) {
            /* optional PDUSessionAggregateMaximumBitRate */
            case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
              break;
          
            /* mandatory UL-NGU-UP-TNLInformation */
            case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation:
              {
                NGAP_GTPTunnel_t  *gTPTunnel_p;
                gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel;
                
                /* Set the transport layer address */
                memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.buffer,
                       gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
                
                NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.length =
                  gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused;
                
                /* GTP tunnel endpoint ID */
                OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].gtp_teid);
              }
              
              break;
              
            /* optional AdditionalUL-NGU-UP-TNLInformation */
            case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
              break;
  
            /* optional DataForwardingNotPossible */
            case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible:
              break;
  
            /* mandatory PDUSessionType */
            case NGAP_ProtocolIE_ID_id_PDUSessionType:
              NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
              break;
  
            /* optional SecurityIndication */
            case NGAP_ProtocolIE_ID_id_SecurityIndication:
              break;
  
            /* optional NetworkInstance */
            case NGAP_ProtocolIE_ID_id_NetworkInstance:
              break;
  
            /* mandatory QosFlowSetupRequestList */
            case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
              {
                NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p;
                
                NGAP_DEBUG("QosFlowSetupRequestList.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count);
                DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0);
                DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows);
  
                NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count;
                  
                for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++) {
                  qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
                  
                  /* Set the QOS informations */
                  NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
                  if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){
                    if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){
                      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].fiveQI =
                          (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI;
                    }
                  }
                
                  NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level =
                    qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
                  NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability =
                    qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability;
                  NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability =
                    qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability;
                }
              }
            
              break;
              
            /* optional CommonNetworkInstance */
            case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
              break;
              
            default:
              NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
              return -1;
          }
        }
  
      } /* for i... */
    } else {/* ie != NULL */
      NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n");
    }
    
    /* id-AllowedNSSAI */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                                 NGAP_ProtocolIE_ID_id_AllowedNSSAI, true);
    
    //if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_AllowedNSSAI_Item_t *allow_nssai_item_p = NULL;
  
      //NGAP_DEBUG("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
      //DevAssert(ie->value.choice.AllowedNSSAI.list.count > 0);
      //DevAssert(ie->value.choice.AllowedNSSAI.list.count <= NGAP_maxnoofAllowedS_NSSAIs);
  
      if (ie == NULL) {
          NGAP_WARN("AllowedNSSAI not present, forging 2 NSSAI\n");
  
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = 2;
  
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sST = 01;
  
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD_flag = 1;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[0] = 01;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[1] = 02;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[2] = 03;
  
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sST = 01;
   
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD_flag = 1;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[0] = 00;//11;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[1] = 00;//22;
      	NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[2] = 01;//33;
      } else {
      NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count;
      
      for(i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) {
        allow_nssai_item_p = ie->value.choice.AllowedNSSAI.list.array[i];
        
        OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sST);
  
        if(allow_nssai_item_p->s_NSSAI.sD != NULL) {
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD_flag = 1;
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0];
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1];
          NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2];
        }
      }
     }
    //} else {/* ie != NULL */
    //  return -1;
    //}
  
    /* id-UESecurityCapabilities */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRencryption_algorithms =
        BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRencryptionAlgorithms);
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRintegrity_algorithms =
        BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRintegrityProtectionAlgorithms);
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAencryption_algorithms =
        BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAencryptionAlgorithms);
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAintegrity_algorithms =
        BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAintegrityProtectionAlgorithms);
    } else {/* ie != NULL */
      return -1;
    }
  
    /* id-SecurityKey : Copy the security key */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_SecurityKey, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      memcpy(&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
             ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
      
    } else {/* ie != NULL */
      return -1;
    }
  
    /* id-MobilityRestrictionList */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                                 NGAP_ProtocolIE_ID_id_MobilityRestrictionList, false);
    
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_MobilityRestrictionList_t *mobility_rest_list_p = NULL;
      mobility_rest_list_p = &ie->value.choice.MobilityRestrictionList;
  
      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction_flag   = 1;
      TBCD_TO_MCC_MNC(&mobility_rest_list_p->servingPLMN, 
                      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mcc,
                      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc, 
                      NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc_digit_length);
    } 
  
  
    /* id-NAS-PDU */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                                   NGAP_ProtocolIE_ID_id_NAS_PDU, false);
      
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      if(ie->value.choice.NAS_PDU.size > 0) {
        NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu_flag   = 1;
        NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size;
        NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
        memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer,
               ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size);
      }
    } 
  
    itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
  
    return 0;
  }
  
  
  static
  int ngap_gNB_handle_ue_context_release_command(uint32_t   assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
  
    ngap_gNB_amf_data_t   *amf_desc_p       = NULL;
    ngap_gNB_ue_context_t *ue_desc_p        = NULL;
    MessageDef            *message_p        = NULL;
    uint64_t                            amf_ue_ngap_id;
    NGAP_RAN_UE_NGAP_ID_t               gnb_ue_ngap_id;
    NGAP_UEContextReleaseCommand_t     *container;
    NGAP_UEContextReleaseCommand_IEs_t *ie;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand;
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received UE context release command for non "
                 "existing AMF context\n", assoc_id);
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_UEContextReleaseCommand_IEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_UE_NGAP_IDs, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      switch (ie->value.choice.UE_NGAP_IDs.present) {
        case NGAP_UE_NGAP_IDs_PR_uE_NGAP_ID_pair:
          gnb_ue_ngap_id = ie->value.choice.UE_NGAP_IDs.choice.uE_NGAP_ID_pair->rAN_UE_NGAP_ID;
          asn_INTEGER2ulong(&(ie->value.choice.UE_NGAP_IDs.choice.uE_NGAP_ID_pair->aMF_UE_NGAP_ID), &amf_ue_ngap_id);
  
          if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance,
                           gnb_ue_ngap_id)) == NULL) {
            NGAP_ERROR("[SCTP %d] Received UE context release command for non "
                       "existing UE context 0x%06lx\n",
                       assoc_id,
                       gnb_ue_ngap_id);
            return -1;
          } else {
            message_p    = itti_alloc_new_message(TASK_NGAP, 0, NGAP_UE_CONTEXT_RELEASE_COMMAND);
  
            if (ue_desc_p->amf_ue_ngap_id == 0) { // case of Detach Request and switch off from RRC_IDLE mode
              ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id;
            }
  
            NGAP_UE_CONTEXT_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id;
            itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
            return 0;
          }
  
          break;
  
        //#warning "TODO mapping amf_ue_ngap_id  gnb_ue_ngap_id?"
  
        case NGAP_UE_NGAP_IDs_PR_aMF_UE_NGAP_ID:
          asn_INTEGER2ulong(&(ie->value.choice.UE_NGAP_IDs.choice.aMF_UE_NGAP_ID), &amf_ue_ngap_id);
          NGAP_ERROR("TO DO mapping amf_ue_ngap_id  gnb_ue_ngap_id");
          (void)amf_ue_ngap_id; /* TODO: remove - it's to remove gcc warning about unused var */
  
        case NGAP_UE_NGAP_IDs_PR_NOTHING:
        default:
          NGAP_ERROR("NGAP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements");
          return -1;
      }
    } else {
      return -1;
    }
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_UEContextReleaseCommand_IEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_Cause, true);
    /* TBD */
  
    return 0;
  }
  
  static
  int ngap_gNB_handle_pdusession_setup_request(uint32_t         assoc_id,
                                          uint32_t         stream,
                                          NGAP_NGAP_PDU_t *pdu) {
  //  NGAP_AMF_UE_NGAP_ID_t       amf_ue_ngap_id;
    uint64_t                      amf_ue_ngap_id;
    NGAP_RAN_UE_NGAP_ID_t         ran_ue_ngap_id;
    ngap_gNB_amf_data_t          *amf_desc_p       = NULL;
    ngap_gNB_ue_context_t        *ue_desc_p        = NULL;
    MessageDef                   *message_p        = NULL;
    NGAP_PDUSessionResourceSetupRequest_t     *container;
    NGAP_PDUSessionResourceSetupRequestIEs_t  *ie;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceSetupRequest;
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received pdu session resource setup request for non "
                 "existing AMF context\n", assoc_id);
      return -1;
    }
  
    /* id-AMF-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
       asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
    } else {
      return -1;
    }
  
    /* id-gNB-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container,
                           NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      ran_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
    } else {
      return -1;
    }
  
    if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance,
                     ran_ue_ngap_id)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received pdu session resource setup request for non "
                 "existing UE context 0x%06lx\n", assoc_id,
                 ran_ue_ngap_id);
      return -1;
    }
  
    /* Initial context request = UE-related procedure -> stream != 0 */
    // if (stream == 0) {
    //   NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
    //              assoc_id, stream);
    //   return -1;
    // }
  
    ue_desc_p->rx_stream = stream;
  
    if ( ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) {
      NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%lu != %lu)",
                (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id);
    }
  
    message_p        = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ);
    NGAP_PDUSESSION_SETUP_REQ(message_p).ue_initial_id   = ue_desc_p->ue_initial_id;
    ue_desc_p->ue_initial_id = 0;
    NGAP_PDUSESSION_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id;
    NGAP_PDUSESSION_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id;
  
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container,
                           NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_PDUSESSION_SETUP_REQ(message_p).nb_pdusessions_tosetup =
        ie->value.choice.PDUSessionResourceSetupListSUReq.list.count;
  
      for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) {
        NGAP_PDUSessionResourceSetupItemSUReq_t          *item_p;
        asn_dec_rval_t                                   dec_rval;
        NGAP_PDUSessionResourceSetupRequestTransfer_t    *pdusessionTransfer_p   = NULL;
        NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL;
  
        item_p = (NGAP_PDUSessionResourceSetupItemSUReq_t *)ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i];
        NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID;
  
  
        // check for the NAS PDU
        if (item_p->pDUSessionNAS_PDU->size > 0 ) {
          NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size;
          NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size);
          memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer,
                 item_p->pDUSessionNAS_PDU->buf, item_p->pDUSessionNAS_PDU->size);
          // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]);
        } else {
          NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = 0;
          NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = NULL;
          NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n");
        }
  
        dec_rval = aper_decode(NULL,
                                 &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
                                 (void **)&pdusessionTransfer_p,
                                 item_p->pDUSessionResourceSetupRequestTransfer.buf,
                                 item_p->pDUSessionResourceSetupRequestTransfer.size, 0, 0);
  
        if(dec_rval.code != RC_OK) {
          NGAP_ERROR("could not decode PDUSessionResourceSetupRequestTransfer\n");
          return -1;
        }
  
        for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) {
          pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j];
  
          switch(pdusessionTransfer_ies->id) {
            /* optional PDUSessionAggregateMaximumBitRate */
            case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
              break;
  
            /* mandatory UL-NGU-UP-TNLInformation */
            case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation:
            {
            	NGAP_GTPTunnel_t  *gTPTunnel_p;
                gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel;
                /* The transport layer address for the IP packets */
                OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].gtp_teid);
                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.length =
                		gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused;
                memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.buffer ,
                		gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
            }
              break;
  
            /* optional AdditionalUL-NGU-UP-TNLInformation */
            case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
              break;
  
            /* optional DataForwardingNotPossible */
            case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible:
              break;
  
            /* mandatory PDUSessionType */
            case NGAP_ProtocolIE_ID_id_PDUSessionType:
              NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
              break;
  
            /* optional SecurityIndication */
            case NGAP_ProtocolIE_ID_id_SecurityIndication:
              break;
  
            /* optional NetworkInstance */
            case NGAP_ProtocolIE_ID_id_NetworkInstance:
              break;
  
            /* mandatory QosFlowSetupRequestList */
            case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
            {
              NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p;
  
              NGAP_DEBUG("servedGUAMIs.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count);
              DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0);
              DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows);
  
              NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count;
  
              for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++){
                qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
  
                /* Set the QOS informations */
                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
                if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){
                  if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){
                    NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI = 
                      (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI;
                  }
                }
                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
                  qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability =
                  qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability;
                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability =
                  qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability;
              }
            }
            break;
  
            /* optional CommonNetworkInstance */
            case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
              break;
  
            default:
              NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
              return -1;
          }
        }/* for j... */
      } /* for i... */
      itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
    }else {/* ie == NULL */
      NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq\n");
      return -1;
    }
    return 0;
  }
  
  
  static
  int ngap_gNB_handle_paging(uint32_t               assoc_id,
                             uint32_t               stream,
                             NGAP_NGAP_PDU_t       *pdu) {
  
    ngap_gNB_amf_data_t   *amf_desc_p        = NULL;
    ngap_gNB_instance_t   *ngap_gNB_instance = NULL;
    MessageDef            *message_p         = NULL;
    NGAP_Paging_t         *container;
    NGAP_PagingIEs_t      *ie;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.Paging;
    // received Paging Message from AMF
    NGAP_DEBUG("[SCTP %d] Received Paging Message From AMF\n",assoc_id);
  
    /* Paging procedure -> stream != 0 */
    if (stream == 0) {
      LOG_W(NGAP,"[SCTP %d] Received Paging procedure on stream (%d)\n",
            assoc_id, stream);
      return -1;
    }
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received Paging for non "
                 "existing AMF context\n", assoc_id);
      return -1;
    }
  
    ngap_gNB_instance = amf_desc_p->ngap_gNB_instance;
  
    if (ngap_gNB_instance == NULL) {
      NGAP_ERROR("[SCTP %d] Received Paging for non existing AMF context : ngap_gNB_instance is NULL\n",
                 assoc_id);
      return -1;
    }
  
    message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND);
    /* convert NGAP_PagingIEs_t to ngap_paging_ind_t */
    /* id-UEIdentityIndexValue : convert UE Identity Index value */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_UEPagingIdentity, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id);
      OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer);
      OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi);
  
      NGAP_DEBUG("[SCTP %d] Received Paging Identity amf_set_id %d, amf_pointer %d, m_tmsi %d\n",
                 assoc_id,
                 NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id,
                 NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer,
                 NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi);
    } else {
      return -1;
    }
  
  
    NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256;
    /* id-pagingDRX */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_PagingDRX, false);
  
    /* optional */
    if (ie) {
      NGAP_PAGING_IND(message_p).paging_drx = ie->value.choice.PagingDRX;
    } else {
      NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256;
    }
  
    memset (&NGAP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256);
    memset (&NGAP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256);
    NGAP_PAGING_IND(message_p).tai_size = 0;
    /* id-TAIList */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_TAIListForPaging, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_INFO("[SCTP %d] Received Paging taiList For Paging: count %d\n", assoc_id, ie->value.choice.TAIListForPaging.list.count);
  
      for (int i = 0; i < ie->value.choice.TAIListForPaging.list.count; i++) {
        NGAP_TAIListForPagingItem_t *item_p;
        item_p = (NGAP_TAIListForPagingItem_t *)ie->value.choice.TAIListForPaging.list.array[i];
        TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), NGAP_PAGING_IND(message_p).plmn_identity[i].mcc,
                        NGAP_PAGING_IND(message_p).plmn_identity[i].mnc,
                        NGAP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length);
        OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), NGAP_PAGING_IND(message_p).tac[i]);
        NGAP_PAGING_IND(message_p).tai_size++;
        NGAP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id,
                   NGAP_PAGING_IND(message_p).plmn_identity[i].mcc,
                   NGAP_PAGING_IND(message_p).plmn_identity[i].mnc,
                   NGAP_PAGING_IND(message_p).tac[i]);
      }
    } else {
      return -1;
    }
  
    //paging parameter values
    NGAP_DEBUG("[SCTP %d] Received Paging parameters: Paging Identity amf_set_id %d amf_pointer %d m_tmsi %d paging_drx %d paging_priority %d\n",assoc_id,
               NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id,
               NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer,
               NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi,
               NGAP_PAGING_IND(message_p).paging_drx, NGAP_PAGING_IND(message_p).paging_priority);
    /* send message to RRC */
    itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p);
  
    return 0;
  }
  
  static
  int ngap_gNB_handle_pdusession_modify_request(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
  
    int i, nb_of_pdusessions_failed;
    ngap_gNB_amf_data_t           *amf_desc_p       = NULL;
    ngap_gNB_ue_context_t         *ue_desc_p        = NULL;
    MessageDef                    *message_p        = NULL;
    NGAP_PDUSessionResourceModifyRequest_t     *container;
    NGAP_PDUSessionResourceModifyRequestIEs_t  *ie;
    NGAP_RAN_UE_NGAP_ID_t         gnb_ue_ngap_id;
    uint64_t                      amf_ue_ngap_id;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceModifyRequest;
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received PDUSession Resource modify request for non "
                 "existing AMF context\n", assoc_id);
      return -1;
    }
  
    /* id-AMF-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
    } else {
      return -1;
    }
  
    /* id-RAN-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
    } else {
      return -1;
    }
  
    if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance,
                     gnb_ue_ngap_id)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received PDUSession Resource modify request for non "
                 "existing UE context 0x%08lx\n", assoc_id,
                 gnb_ue_ngap_id);
      return -1;
    }
  
    ue_desc_p->rx_stream = stream;
  
    if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) {
      NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%ld != %ld)",
                (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id);
      message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP);
      NGAP_PDUSESSION_MODIFY_RESP (message_p).gNB_ue_ngap_id = gnb_ue_ngap_id;
      NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container,
                                 NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true);
  
      if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
        for(nb_of_pdusessions_failed = 0; nb_of_pdusessions_failed < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; nb_of_pdusessions_failed++) {
          NGAP_PDUSessionResourceModifyItemModReq_t *item_p;
          item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[nb_of_pdusessions_failed];
          
          NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID;
          NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork;
          NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID;
        }
      } else {
        return -1;
      }
  
      NGAP_PDUSESSION_MODIFY_RESP(message_p).nb_of_pdusessions_failed = nb_of_pdusessions_failed;
      ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance,
                                 &NGAP_PDUSESSION_MODIFY_RESP(message_p));
      itti_free(TASK_RRC_GNB,message_p);
      message_p = NULL;
      return -1;
    }
  
    message_p        = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ);
    NGAP_PDUSESSION_MODIFY_REQ(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
    NGAP_PDUSESSION_MODIFY_REQ(message_p).amf_ue_ngap_id  = amf_ue_ngap_id;
    NGAP_PDUSESSION_MODIFY_REQ(message_p).gNB_ue_ngap_id  = gnb_ue_ngap_id;
    /* id-PDUSessionResourceModifyListModReq */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_PDUSESSION_MODIFY_REQ(message_p).nb_pdusessions_tomodify =
        ie->value.choice.PDUSessionResourceModifyListModReq.list.count;
  
      for (i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) {
        NGAP_PDUSessionResourceModifyItemModReq_t         *item_p;
        asn_dec_rval_t                                    dec_rval;
        NGAP_PDUSessionResourceModifyRequestTransfer_t    *pdusessionTransfer_p = NULL;
        NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = NULL;
          
        item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i];
      
        NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID;
  
        // check for the NAS PDU
        if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0 ) {
          NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size;
          NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size);
          memcpy(NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer,
                 item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
        } else {
          NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = 0;
          NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = NULL;
          continue;
        }
  
        dec_rval = aper_decode(NULL,
                               &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
                               (void **)&pdusessionTransfer_p,
                               item_p->pDUSessionResourceModifyRequestTransfer.buf,
                               item_p->pDUSessionResourceModifyRequestTransfer.size, 0, 0);
  
        if(dec_rval.code != RC_OK) {
          NGAP_ERROR("could not decode PDUSessionResourceModifyRequestTransfer\n");
          return -1;
        }
  
        for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) {
          pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j];
          switch(pdusessionTransfer_ies->id) {
            /* optional PDUSessionAggregateMaximumBitRate */
            case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate\n");
              break;
          
            /* optional UL-NGU-UP-TNLModifyList */
            case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList\n");
              break;
              
            /* optional NetworkInstance */
            case NGAP_ProtocolIE_ID_id_NetworkInstance:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_NetworkInstance\n");
              break;
  
            /* optional QosFlowAddOrModifyRequestList */
            case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList:
              {
                NGAP_QosFlowAddOrModifyRequestItem_t *qosFlowItem_p;
                
                NGAP_DEBUG("QosFlowAddOrModifyRequestList.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count);
                DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count > 0);
                DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count <= NGAP_maxnoofQosFlows);
  
                NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count;
                  
                for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; qosIdx++) {
                  qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx];
                  
                  /* Set the QOS informations */
                  NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
                  if(qosFlowItem_p->qosFlowLevelQosParameters) {
                    if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
                      NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].fiveQI =
                        qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.choice.nonDynamic5QI->fiveQI;
                    } else if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI) {
                      // TODO
                    }
                    NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
                      qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP;
                    NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability =
                      qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability;
                    NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability =
                      qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability;
                  }
                }
              }
              break;
  
            /* optional QosFlowToReleaseList */
            case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_QosFlowToReleaseList\n");
              break;
  
            /* optional AdditionalUL-NGU-UP-TNLInformation */
            case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation\n");
              break;
  
            /* optional CommonNetworkInstance */
            case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
              // TODO
              NGAP_ERROR("Cant' handle NGAP_ProtocolIE_ID_id_CommonNetworkInstance\n");
              break;
              
            default:
              NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
              return -1;
          }
        }
      }
  
      itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
    } else { /* of if (ie != NULL)*/
      return -1;
    }
  
    return 0;
  }
  // handle pdu session release command and send it to rrc_end
  static
  int ngap_gNB_handle_pdusession_release_command(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
  
    int i;
    ngap_gNB_amf_data_t   *amf_desc_p       = NULL;
    ngap_gNB_ue_context_t *ue_desc_p        = NULL;
    MessageDef            *message_p        = NULL;
    NGAP_PDUSessionResourceReleaseCommand_t     *container;
    NGAP_PDUSessionResourceReleaseCommandIEs_t  *ie;
    NGAP_RAN_UE_NGAP_ID_t           gnb_ue_ngap_id;
    uint64_t                        amf_ue_ngap_id;
    DevAssert(pdu != NULL);
    container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceReleaseCommand;
  
    if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received pdu session release command for non existing AMF context\n", assoc_id);
      return -1;
    }
  
  
    /* id-AMF-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
    } else {
      return -1;
    }
  
    /* id-RAN-UE-NGAP-ID */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
    } else {
      return -1;
    }
  
    if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance,
                     gnb_ue_ngap_id)) == NULL) {
      NGAP_ERROR("[SCTP %d] Received PDUSession Resource release command for non existing UE context 0x%08lx\n", assoc_id,
                 ie->value.choice.RAN_UE_NGAP_ID);
      return -1;
    }
  
    /* Initial context request = UE-related procedure -> stream != 0 */
    // if (stream == 0) {
    //   NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
    //              assoc_id, stream);
    //   return -1;
    // }
  
    ue_desc_p->rx_stream = stream;
  
    if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) {
      NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%lu != %lu)",
                (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id);
    }
  
    NGAP_DEBUG("[SCTP %d] Received pdu session release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n",
               assoc_id, gnb_ue_ngap_id, amf_ue_ngap_id);
    message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND);
    NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id;
    NGAP_PDUSESSION_RELEASE_COMMAND(message_p).amf_ue_ngap_id = amf_ue_ngap_id;
    /* id-NAS-PDU */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_NAS_PDU, false);
  
    if(ie && ie->value.choice.NAS_PDU.size > 0) {
      NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size;
      NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
      memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer,
             ie->value.choice.NAS_PDU.buf,
             ie->value.choice.NAS_PDU.size);
    } else {
      NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = 0;
      NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL;
    }
  
    /* id-PDUSessionResourceToReleaseListRelCmd */
    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
                               NGAP_ProtocolIE_ID_id_PDUSessionResourceToReleaseListRelCmd, true);
  
    if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
      NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count;
  
      for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) {
        NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p;
        item_p = (NGAP_PDUSessionResourceToReleaseItemRelCmd_t *)ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i];
      
        NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].pdusession_id = item_p->pDUSessionID;
        if(item_p->pDUSessionResourceReleaseCommandTransfer.size > 0) {
          NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size;
          NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size);
          memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer,
                 item_p->pDUSessionResourceReleaseCommandTransfer.buf,
                 item_p->pDUSessionResourceReleaseCommandTransfer.size);
        }else {
          NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = 0;
          NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = NULL;
          NGAP_ERROR("[NGAP] Received pdu session release command for pDUSessionResourceReleaseCommandTransfer is NULL!\n");
        }
        NGAP_DEBUG("[NGAP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID);
      }
    } else {
      return -1;
    }
  
    itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
  
    return 0;
  }
  
  static
  int ngap_gNB_handle_ng_path_switch_request_ack(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
    // TODO
    return 0;
  }
  
  static
  int ngap_gNB_handle_ng_path_switch_request_failure(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu) {
  
    // TODO
    return 0;
  }
  
  static
  int ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm(uint32_t               assoc_id,
      uint32_t               stream,
      NGAP_NGAP_PDU_t       *pdu){
  
  	LOG_W(NGAP, "Implementation of NGAP Pdusession Modification confirm handler is pending...\n");
  	return 0;
  }
  
  