From 6e2f63bf1fa1f225f49ae473ede18b2b69d4bde8 Mon Sep 17 00:00:00 2001 From: Xue Song Date: Wed, 25 Nov 2020 18:55:59 +0900 Subject: [PATCH] Add rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND and rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE --- openair2/COMMON/gtpv1_u_messages_def.h | 3 + openair2/COMMON/gtpv1_u_messages_types.h | 17 ++- openair2/RRC/NR/nr_rrc_defs.h | 6 + openair2/RRC/NR/nr_rrc_proto.h | 7 + openair2/RRC/NR/rrc_gNB.c | 142 +++++++++++++++++++- openair2/RRC/NR/rrc_gNB_NGAP.c | 163 +++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 7 + openair2/RRC/NR_UE/rrc_UE.c | 60 +++++---- openair3/GTPV1-U/gtpv1u_gNB.c | 81 +++++++++++ openair3/NGAP/ngap_gNB_handlers.c | 18 +-- 10 files changed, 463 insertions(+), 41 deletions(-) diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 8531ce16a0..86103dd911 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -30,4 +30,7 @@ MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_dat MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t, Gtpv1uEndMarkerReq) MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t, Gtpv1uEndMarkerInd) MESSAGE_DEF(GTPV1U_ENB_S1_REQ, MESSAGE_PRIORITY_MED, Gtpv1uS1Req, gtpv1uS1Req) + +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_req_t, NRGtpv1uDeleteTunnelReq) +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_resp_t, NRGtpv1uDeleteTunnelResp) MESSAGE_DEF(GTPV1U_GNB_NG_REQ, MESSAGE_PRIORITY_MED, Gtpv1uNGReq, gtpv1uNGReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 360d3e44d4..c581f07290 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -40,7 +40,10 @@ #define GTPV1U_ENB_END_MARKER_IND(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uEndMarkerInd #define GTPV1U_ENB_S1_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uS1Req -#define GTPV1U_GNB_NG_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uNGReq + +#define GTPV1U_GNB_DELETE_TUNNEL_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelReq +#define GTPV1U_GNB_DELETE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelResp +#define GTPV1U_GNB_NG_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uNGReq #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF @@ -194,4 +197,16 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; +typedef struct gtpv1u_gnb_delete_tunnel_req_s { + rnti_t rnti; + uint8_t num_pdusession; + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; +} gtpv1u_gnb_delete_tunnel_req_t; + +typedef struct gtpv1u_gnb_delete_tunnel_resp_s { + rnti_t rnti; + uint8_t status; ///< Status of NGU endpoint deleteion (Failed = 0xFF or Success = 0x0) + teid_t gnb_NGu_teid; ///< local NGU Tunnel Endpoint Identifier to be deleted +} gtpv1u_gnb_delete_tunnel_resp_t; + #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 8b122d4ae2..1fa7b39575 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -261,7 +261,10 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_NEW, PDU_SESSION_STATUS_DONE, PDU_SESSION_STATUS_ESTABLISHED, + PDU_SESSION_STATUS_REESTABLISHED, // after HO + PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA PDU_SESSION_STATUS_FAILED, + PDU_SESSION_STATUS_TORELEASE // to release DRB between eNB and UE } pdu_session_status_t; typedef struct pdu_session_param_s { @@ -355,6 +358,8 @@ typedef struct gNB_RRC_UE_s { //release e_rabs uint8_t nb_release_of_e_rabs; e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB]; + uint8_t nb_release_of_pdusessions; + pdusession_failed_t pdusessions_release_failed[NGAP_MAX_PDUSESSION]; // LG: For GTPV1 TUNNELS uint32_t gnb_gtp_teid[S1AP_MAX_E_RAB]; transport_layer_addr_t gnb_gtp_addrs[S1AP_MAX_E_RAB]; @@ -373,6 +378,7 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_reestablishment_timer; uint32_t ue_reestablishment_timer_thres; uint8_t e_rab_release_command_flag; + uint8_t pdu_session_release_command_flag; //------------------------------------------------------------------------------// NR_CellGroupId_t cellGroupId; struct NR_SpCellConfig *spCellConfig; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 105a33603b..2d7516dc28 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -136,3 +136,10 @@ int nr_rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP); +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 61bfa1cf8e..2921ca6fe1 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -118,6 +118,7 @@ extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * con static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn); mui_t rrc_gNB_mui = 0; +uint8_t first_rrcreconfiguration = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// @@ -545,6 +546,100 @@ rrc_gNB_generate_defaultRRCReconfiguration( // rrc_rlc_config_asn1_req } +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + int i; + uint16_t size = 0; + NR_DRB_ToReleaseList_t *DRB_Release_configList2 = NULL; + NR_DRB_Identity_t *DRB_release; + DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid]; + + if (DRB_Release_configList2) { + free(DRB_Release_configList2); + } + + DRB_Release_configList2 = CALLOC(1, sizeof(*DRB_Release_configList2)); + + for(i = 0; i < NB_RB_MAX; i++) { + if((ue_context_pP->ue_context.pdusession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_context_pP->ue_context.pdusession[i].xid == xid) { + DRB_release = CALLOC(1, sizeof(NR_DRB_Identity_t)); + *DRB_release = i+1; + ASN_SEQUENCE_ADD(&DRB_Release_configList2->list, DRB_release); + } + } + + /* If list is empty free the list and reset the address */ + if (nas_length > 0) { + memcpy(ue_context_pP->ue_context.nas_pdu.buffer, nas_buffer, nas_length); + ue_context_pP->ue_context.nas_pdu.length = nas_length; + LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length); + } else { + LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCReconfiguration(ctxt_pP, + ue_context_pP, + buffer, + xid, + NULL); + ue_context_pP->ue_context.pdu_session_release_command_flag = 1; + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, + "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + if (nas_length > 0) { + /* Free the NAS PDU buffer and invalidate it */ + free(nas_buffer); + } + + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated NR_RRCReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif +} + //----------------------------------------------------------------------------- /* * Process the RRC Reconfiguration Complete from the UE @@ -921,7 +1016,8 @@ rrc_gNB_decode_dcch( asn_dec_rval_t dec_rval; NR_UL_DCCH_Message_t *ul_dcch_msg = NULL; struct rrc_gNB_ue_context_s *ue_context_p = NULL; - // NR_RRCSetupComplete_t *rrcSetupComplete = NULL; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; int i; @@ -974,7 +1070,7 @@ rrc_gNB_decode_dcch( break; case NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete: - LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %x\n", ctxt_pP->rnti); + LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %x\n", ctxt_pP->rnti); if(!ue_context_p) { LOG_I(NR_RRC, "Processing NR_RRCReconfigurationComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); break; @@ -1007,7 +1103,39 @@ rrc_gNB_decode_dcch( ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); } - rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + if (AMF_MODE_ENABLED) { + if(ue_context_p->ue_context.pdu_session_release_command_flag == 1) { + xid = ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier; + ue_context_p->ue_context.pdu_session_release_command_flag = 0; + //gtp tunnel delete + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pdusession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = + ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid); + } else { + rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); + } + } + + if (first_rrcreconfiguration == 0){ + first_rrcreconfiguration = 1; + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + } break; @@ -1284,6 +1412,7 @@ rrc_gNB_decode_dcch( ue_context_p, ul_dcch_msg); } + sleep(1); rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; @@ -1377,6 +1506,13 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, msg_name_p, instance); break; + case NGAP_PDUSESSION_RELEASE_COMMAND: + rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, msg_name_p, instance); + break; + + case GTPV1U_GNB_DELETE_TUNNEL_RESP: + break; + /* #if defined(ENABLE_USE_MME) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 3464f9e92d..07f368887d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1228,3 +1228,166 @@ rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n"); } +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +) +//------------------------------------------------------------------------------ +{ + int pdu_sessions_released = 0; + MessageDef *msg_p; + msg_p = itti_alloc_new_message (TASK_RRC_GNB, NGAP_PDUSESSION_RELEASE_RESPONSE); + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + + for (int i = 0; i < NB_RB_MAX; i++) { + if (xid == ue_context_pP->ue_context.pdusession[i].xid) { + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusession_release[pdu_sessions_released].pdusession_id = + ue_context_pP->ue_context.pdusession[i].param.pdusession_id; + pdu_sessions_released++; + //clear + memset(&ue_context_pP->ue_context.pdusession[i], 0, sizeof(pdu_session_param_t)); + } + } + + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_released = pdu_sessions_released; + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_failed = ue_context_pP->ue_context.nb_release_of_pdusessions; + memcpy(&(NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusessions_failed[0]), &ue_context_pP->ue_context.pdusessions_release_failed[0], + sizeof(pdusession_failed_t)*ue_context_pP->ue_context.nb_release_of_pdusessions); + ue_context_pP->ue_context.setup_pdu_sessions -= pdu_sessions_released; + LOG_I(NR_RRC,"NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %d release_pdu_sessions %d setup_pdu_sessions %d \n", + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id, + pdu_sessions_released, ue_context_pP->ue_context.setup_pdu_sessions); + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + + //clear xid + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.pdusession[i].xid = -1; + } + + //clear release pdusessions + ue_context_pP->ue_context.nb_release_of_pdusessions = 0; + memset(&ue_context_pP->ue_context.pdusessions_release_failed[0], 0, sizeof(pdusession_failed_t)*NGAP_MAX_PDUSESSION); + return 0; +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +) +//------------------------------------------------------------------------------ +{ + uint32_t gNB_ue_ngap_id; + rrc_gNB_ue_context_t *ue_context_p = NULL; + protocol_ctxt_t ctxt; + pdusession_release_t pdusession_release_params[NGAP_MAX_PDUSESSION]; + uint8_t nb_pdusessions_torelease; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; + int i, pdusession; + uint8_t b_existed,is_existed; + uint8_t pdusession_release_drb; + + memcpy(&pdusession_release_params[0], &(NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).pdusession_release_params[0]), + sizeof(pdusession_release_t)*NGAP_MAX_PDUSESSION); + gNB_ue_ngap_id = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + nb_pdusessions_torelease = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).nb_pdusessions_torelease; + if (nb_pdusessions_torelease > NGAP_MAX_PDUSESSION) { + return -1; + } + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %d] Received %s: gNB_ue_ngap_id %d \n", instance, msg_name, gNB_ue_ngap_id); + + if (ue_context_p != NULL) { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id); + LOG_I(NR_RRC,"PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d release_pdusessions %d \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id, gNB_ue_ngap_id, nb_pdusessions_torelease); + + for (pdusession = 0; pdusession < nb_pdusessions_torelease; pdusession++) { + b_existed = 0; + is_existed = 0; + + for (i = pdusession-1; i >= 0; i--) { + if (pdusession_release_params[pdusession].pdusession_id == pdusession_release_params[i].pdusession_id) { + is_existed = 1; + break; + } + } + + if(is_existed == 1) { + // pdusession_id is existed + continue; + } + + for (i = 0; i < NR_NB_RB_MAX; i++) { + if (pdusession_release_params[pdusession].pdusession_id == ue_context_p->ue_context.pdusession[i].param.pdusession_id) { + b_existed = 1; + break; + } + } + + if(b_existed == 0) { + // no pdusession_id + LOG_I(NR_RRC, "no pdusession_id \n"); + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 30; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } else { + if(ue_context_p->ue_context.pdusession[i].status == PDU_SESSION_STATUS_FAILED) { + ue_context_p->ue_context.pdusession[i].xid = xid; + continue; + } else if(ue_context_p->ue_context.pdusession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { + LOG_I(NR_RRC, "RELEASE pdusession %d \n", ue_context_p->ue_context.pdusession[i].param.pdusession_id); + ue_context_p->ue_context.pdusession[i].status = PDU_SESSION_STATUS_TORELEASE; + ue_context_p->ue_context.pdusession[i].xid = xid; + pdusession_release_drb++; + } else { + // pdusession_id status NG + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 0; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } + } + } + + if(pdusession_release_drb > 0) { + //TODO RRCReconfiguration To UE + LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n"); + rrc_gNB_generate_dedicatedRRCReconfiguration_release(&ctxt, ue_context_p, xid, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.length, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.buffer); + } else { + //gtp tunnel delete + LOG_I(NR_RRC, "gtp tunnel delete \n"); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pdusession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(&ctxt, ue_context_p, xid); + LOG_I(NR_RRC, "Send PDU Session Release Response \n"); + } + } else { + LOG_E(NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d Error ue_context_p NULL \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id, NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id); + return -1; + } + + return 0; +} diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 85f4f183e6..efbcc62171 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -142,4 +142,11 @@ rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( NR_UL_DCCH_Message_t *const ul_dcch_msg ); +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 55a608e2dd..ca9ff3e091 100755 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -118,6 +118,7 @@ uint8_t do_NR_RRCReconfigurationComplete( ); mui_t nr_rrc_mui=0; +uint8_t first_rrcreconfigurationcomplete = 0; static Rrc_State_NR_t nr_rrc_get_state (module_id_t ue_mod_idP) { return NR_UE_rrc_inst[ue_mod_idP].nrRrcState; @@ -2328,36 +2329,39 @@ nr_rrc_ue_decode_dcch( nr_rrc_ue_generate_RRCReconfigurationComplete(ctxt_pP, gNB_indexP, dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier); + if (first_rrcreconfigurationcomplete == 0) { + first_rrcreconfigurationcomplete = 1; #ifdef ITTI_SIM - //wait send RRCReconfigurationComplete and InitialContextSetupResponse - sleep(1); - as_nas_info_t initialNasMsg; - memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); - generateRegistrationComplete(&initialNasMsg, NULL); - if(initialNasMsg.length > 0){ - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); - LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); - } - //wait send RegistrationComplete - usleep(100*150); - as_nas_info_t pduEstablishMsg; - memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); - generatePduSessionEstablishRequest(&pduEstablishMsg); - if(initialNasMsg.length > 0){ - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); - LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); - } + //wait send RRCReconfigurationComplete and InitialContextSetupResponse + sleep(1); + as_nas_info_t initialNasMsg; + memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); + generateRegistrationComplete(&initialNasMsg, NULL); + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); + LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); + } + //wait send RegistrationComplete + usleep(100*150); + as_nas_info_t pduEstablishMsg; + memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); + generatePduSessionEstablishRequest(&pduEstablishMsg); + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); + LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + } #endif + } } break; diff --git a/openair3/GTPV1-U/gtpv1u_gNB.c b/openair3/GTPV1-U/gtpv1u_gNB.c index 8d8a012437..d77460ba4b 100644 --- a/openair3/GTPV1-U/gtpv1u_gNB.c +++ b/openair3/GTPV1-U/gtpv1u_gNB.c @@ -551,6 +551,83 @@ gtpv1u_create_ngu_tunnel( return ret; } +//----------------------------------------------------------------------------- +int gtpv1u_delete_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_delete_tunnel_req_t *const req_pP) { + NwGtpv1uUlpApiT stack_req; + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + MessageDef *message_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + teid_t teid_gNB = 0; + int pdusession_index = 0; + message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_GNB_DELETE_TUNNEL_RESP); + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti = req_pP->rnti; + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status = 0; + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)>pv1u_ue_data_p); + + if (hash_rc == HASH_TABLE_OK) { + for (pdusession_index = 0; pdusession_index < req_pP->num_pdusession; pdusession_index++) { + teid_gNB = gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB; + LOG_D(GTPU, "Rx GTPV1U_ENB_DELETE_TUNNEL user rnti %x eNB S1U teid %u eps bearer id %u\n", + req_pP->rnti, teid_gNB, req_pP->pdusession_id[pdusession_index]); + { + memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); + stack_req.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT; + LOG_D(GTPU, "gtpv1u_delete_ngu_tunnel pdusession %u %u\n", + req_pP->pdusession_id[pdusession_index], + teid_gNB); + stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session; + rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req); + LOG_D(GTPU, ".\n"); + } + + if (rc != NW_GTPV1U_OK) { + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status |= 0xFF; + LOG_E(GTPU, "NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT failed"); + } + + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].state = BEARER_DOWN; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_upf = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].upf_ip_addr = 0; + gtpv1u_ue_data_p->num_bearers -= 1; + + if (gtpv1u_ue_data_p->num_bearers == 0) { + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti); + LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti); + } + + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->teid_mapping, teid_gNB); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , gNB NGU teid %u not found\n", req_pP->rnti, teid_gNB); + } + } + }// else silently do nothing + + LOG_D(GTPU, "Tx GTPV1U_GNB_DELETE_TUNNEL_RESP user rnti %x gNB NGU teid %u status %u\n", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).gnb_NGu_teid, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status); + MSC_LOG_TX_MESSAGE( + MSC_GTPU_GNB, + MSC_RRC_GNB, + NULL,0, + "0 GTPV1U_GNB_DELETE_TUNNEL_RESP rnti %x teid %x", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + teid_gNB); + return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p); +} + //----------------------------------------------------------------------------- static int gtpv1u_gNB_send_init_udp(const Gtpv1uNGReq *req) { // Create and alloc new message @@ -603,6 +680,10 @@ void *gtpv1u_gNB_process_itti_msg(void *notUsed) { gtpv1u_ng_req(instance, &received_message_p->ittiMsg.gtpv1uNGReq); break; + case GTPV1U_GNB_DELETE_TUNNEL_REQ: + gtpv1u_delete_ngu_tunnel(instance, &received_message_p->ittiMsg.NRGtpv1uDeleteTunnelReq); + break; + case TERMINATE_MESSAGE: { if (RC.nr_gtpv1u_data_g->ue_mapping != NULL) { hashtable_destroy (&(RC.nr_gtpv1u_data_g->ue_mapping)); diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 6051e917b4..b0c86e155e 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1754,7 +1754,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, return 0; } -// handle e-rab release command and send it to rrc_end +// 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, @@ -1772,7 +1772,7 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, 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 E-RAB release command for non existing AMF context\n", assoc_id); + NGAP_ERROR("[SCTP %d] Received pdu session release command for non existing AMF context\n", assoc_id); return -1; } @@ -1805,11 +1805,11 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, } /* 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; - } + // 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; @@ -1818,7 +1818,7 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); } - NGAP_DEBUG("[SCTP %d] Received E-RAB release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", + 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, NGAP_PDUSESSION_RELEASE_COMMAND); NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; @@ -1850,7 +1850,7 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, 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; - NGAP_DEBUG("[SCTP] Received E-RAB release command for pDUSessionID id %ld\n", item_p->pDUSessionID); + NGAP_DEBUG("[SCTP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID); } } else { return -1;