diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 8b00d529c5..54c650dd0f 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -348,7 +348,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu if (sid < 1 || sid > 255) { ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]); } - msg->pdusession_release_params[nb_sessions++].pdusession_id = sid; + msg->pdusession_ids[nb_sessions++] = sid; } msg->nb_pdusessions_torelease = nb_sessions; @@ -356,7 +356,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu if (prnt) { prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id); for (int i = 0; i < nb_sessions; ++i) { - prnt(" %d,", msg->pdusession_release_params[i].pdusession_id); + prnt(" %d,", msg->pdusession_ids[i]); } prnt("\n"); } diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 98c1f82260..26f607f884 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -64,7 +64,6 @@ MESSAGE_DEF(NGAP_UE_CAPABILITIES_IND , MESSAGE_PRIORITY_MED, ngap_ue_cap_i MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_resp_t, ngap_initial_context_setup_resp) MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_fail_t, ngap_initial_context_setup_fail) MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND , MESSAGE_PRIORITY_MED, ngap_nas_non_delivery_ind_t , ngap_nas_non_delivery_ind) -MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_RESP , MESSAGE_PRIORITY_MED, ngap_ue_release_resp_t , ngap_ue_release_resp) MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, ngap_ue_release_complete_t , ngap_ue_release_complete) MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_resp_t , ngap_ue_ctxt_modification_resp) MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_fail_t , ngap_ue_ctxt_modification_fail) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 5be5e316ef..ed93cdaadf 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -47,7 +47,6 @@ #define NGAP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_cap_info_ind #define NGAP_INITIAL_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_resp #define NGAP_INITIAL_CONTEXT_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_fail -#define NGAP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_resp #define NGAP_NAS_NON_DELIVERY_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_non_delivery_ind #define NGAP_UE_CTXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_resp #define NGAP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_fail @@ -733,12 +732,6 @@ typedef struct ngap_ue_ctxt_modification_resp_s { uint32_t gNB_ue_ngap_id; } ngap_ue_ctxt_modification_resp_t; -typedef struct ngap_ue_release_complete_s { - uint32_t gNB_ue_ngap_id; - int num_pdu_sessions; - uint32_t pdu_session_id[256]; -} ngap_ue_release_complete_t; - //-------------------------------------------------------------------------------------------// // NGAP -> RRC messages typedef struct ngap_downlink_nas_s { @@ -862,20 +855,24 @@ typedef struct ngap_ue_release_command_s { //-------------------------------------------------------------------------------------------// // NGAP <-- RRC messages -typedef struct pdusession_release_s { - /* Unique pdusession_id for the UE. */ - uint8_t pdusession_id; - byte_array_t data; -} pdusession_release_t; - typedef struct ngap_ue_release_req_s { - uint32_t gNB_ue_ngap_id; - /* Number of pdusession resource in the list */ + // RAN UE NGAP ID (mandatory) + uint32_t gNB_ue_ngap_id; + // PDU Session Resource List (optional) uint16_t nb_of_pdusessions; - /* list of pdusession resource by RRC layers */ - pdusession_release_t pdusessions[NGAP_MAX_PDU_SESSION]; + uint8_t pdusession_ids[NGAP_MAX_PDU_SESSION]; + // Cause (mandatory) ngap_cause_t cause; -} ngap_ue_release_req_t, ngap_ue_release_resp_t; +} ngap_ue_release_req_t; + +typedef struct { + // RAN UE NGAP ID (mandatory) + uint32_t gNB_ue_ngap_id; + // PDU Session Resource List (optional) + uint16_t num_pdu_sessions; + // PDU Session ID (mandatory) + uint8_t pdu_session_id[NGAP_MAX_PDU_SESSION]; +} ngap_ue_release_complete_t; typedef struct ngap_pdusession_modify_req_s { /* AMF UE id */ @@ -915,14 +912,19 @@ typedef struct ngap_pdusession_release_command_s { /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ byte_array_t nas_pdu; - /* Number of pdusession to be released in the list */ + // PDU Session Resource to Release List (mandatory) uint16_t nb_pdusessions_torelease; - - /* PDUSession release command */ - pdusession_release_t pdusession_release_params[NGAP_MAX_PDU_SESSION]; + uint16_t pdusession_ids[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_release_command_t; +typedef struct pdusession_release_s { + // PDU Session ID (mandatory) + uint8_t pdusession_id; + // PDU Session Resource Release Response Transfer (mandatory) + byte_array_t pdusession_release_response_transfer; +} pdusession_release_t; + typedef struct ngap_pdusession_release_resp_s { // AMF UE NGAP ID uint64_t amf_ue_ngap_id; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e1d2dbe841..4d28d66b69 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3182,10 +3182,6 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_dc_overall_timeout(instance, &X2AP_ENDC_DC_OVERALL_TIMEOUT(msg_p)); break; - case NGAP_UE_CONTEXT_RELEASE_REQ: - rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(msg_p, instance); - break; - case NGAP_UE_CONTEXT_RELEASE_COMMAND: rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p, instance); break; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 979fe0ac5e..5c212438e1 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1049,7 +1049,8 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE return 0; } -//------------------------------------------------------------------------------ +/** @brief Send UE Context Release Request (NG-RAN node initiated) + * Direction: NG-RAN node -> AMF (8.3.2.2 3GPP TS 38.413) */ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, const rrc_gNB_ue_context_t *const ue_context_pP, const ngap_cause_t causeP) @@ -1068,40 +1069,12 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, // PDU Session Resource List (optional) FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { DevAssert(req->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); - req->pdusessions[req->nb_of_pdusessions].pdusession_id = session->param.pdusession_id; + req->pdusession_ids[req->nb_of_pdusessions] = session->param.pdusession_id; req->nb_of_pdusessions++; } itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg); } } -/*------------------------------------------------------------------------------*/ -int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t instance) -{ - uint32_t gNB_ue_ngap_id; - gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_REQ(msg_p).gNB_ue_ngap_id; - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], gNB_ue_ngap_id); - - if (ue_context_p == NULL) { - /* Can not associate this message to an UE index, send a failure to ngAP and discard it! */ - MessageDef *msg_fail_p; - LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_REQ: unknown UE from gNB_ue_ngap_id (%u)\n", - instance, - gNB_ue_ngap_id); - msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ - NGAP_UE_CONTEXT_RELEASE_RESP(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - // TODO add failure cause when defined! - itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); - return (-1); - } else { - - /* Send the response */ - MessageDef *msg_resp_p; - msg_resp_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); - NGAP_UE_CONTEXT_RELEASE_RESP(msg_resp_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - itti_send_msg_to_task(TASK_NGAP, instance, msg_resp_p); - return (0); - } -} /** @brief Sends the NG Handover Failure from the Target NG-RAN to the AMF */ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure_t *msg) @@ -1557,9 +1530,9 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_comm cmd->nb_pdusessions_torelease); e1ap_bearer_mod_req_t req = {0}; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); + rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_ids[pdusession]); if (!pduSession) { - LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_release_params[pdusession].pdusession_id); + LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_ids[pdusession]); continue; } if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) { diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.c b/openair3/NGAP/ngap_gNB_context_management_procedures.c index 7f114d5bf6..57b7780d4f 100644 --- a/openair3/NGAP/ngap_gNB_context_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.c @@ -191,7 +191,7 @@ int ngap_ue_context_release_req(instance_t instance, for (int i = 0; i < ue_release_req_p->nb_of_pdusessions; i++) { NGAP_PDUSessionResourceItemCxtRelReq_t *item; item = (NGAP_PDUSessionResourceItemCxtRelReq_t *)calloc(1,sizeof(NGAP_PDUSessionResourceItemCxtRelReq_t)); - item->pDUSessionID = ue_release_req_p->pdusessions[i].pdusession_id; + item->pDUSessionID = ue_release_req_p->pdusession_ids[i]; asn1cSeqAdd(&ie->value.choice.PDUSessionResourceListCxtRelReq.list, item); } } diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 95c2dd45a7..a58c98508b 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1390,9 +1390,20 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) { NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; - pdusession_release_t *r = &msg->pdusession_release_params[i]; - r->pdusession_id = item_p->pDUSessionID; - r->data = create_byte_array(item_p->pDUSessionResourceReleaseCommandTransfer.size, item_p->pDUSessionResourceReleaseCommandTransfer.buf); + msg->pdusession_ids[i] = item_p->pDUSessionID; + + /* PDUSessionResourceReleaseCommandTransfer (Mandatory) */ + void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceReleaseCommandTransfer, + item_p->pDUSessionResourceReleaseCommandTransfer); + if (!decoded) { + NGAP_ERROR("Failed to decode PDUSessionResourceReleaseCommandTransfer for PDU Session %d\n", msg->pdusession_ids[i]); + return -1; + } + NGAP_PDUSessionResourceReleaseCommandTransfer_t *transfer = decoded; + ngap_cause_t cause = decode_ngap_cause(&transfer->cause); + NGAP_INFO("PDU Session %d release command: Cause type=%d value=%d\n", msg->pdusession_ids[i], cause.type, cause.value); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseCommandTransfer, transfer); + free(transfer); } itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 7dd6359b7a..2218155c61 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -594,6 +594,24 @@ static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusess return out; } +/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413) + * The transfer structure contains only an optional Secondary RAT Usage Information IE. + * Since we don't use secondary RAT (MR-DC), we encode an empty structure. */ +static byte_array_t encode_ngap_pdusession_release_response_transfer(void) +{ + NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0}; + + // Encode + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, + &pdusessionTransfer); + AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer); + byte_array_t out = {.buf = res.buffer, .len = res.result.encoded}; + return out; +} + //------------------------------------------------------------------------------ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p) //------------------------------------------------------------------------------ @@ -1200,22 +1218,28 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; } - /* optional */ - if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { + /* PDU Session Resource Released List (mandatory) */ + { asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie); ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; - + for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { - asn1cSequenceAdd(ie->value.choice.PDUSessionResourceReleasedListRelRes.list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); + NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes; + asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i]; + /* PDU Session ID (mandatory) */ item->pDUSessionID = r->pdusession_id; - OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)r->data.buf, r->data.len); - NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); + /* PDU Session Resource Release Response Transfer (mandatory) */ + // Empty transfer is valid since Secondary RAT Usage Information is optional and not used + byte_array_t transfer = encode_ngap_pdusession_release_response_transfer(); + OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len); + free_byte_array(transfer); + NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID); } } - + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode release response\n"); /* Encode procedure has failed... */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index 816cdfb979..2a861e2e32 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -58,6 +58,8 @@ #include "NGAP_PDUSessionResourceSetupResponseTransfer.h" #include "NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h" #include "NGAP_PDUSessionResourceToReleaseItemRelCmd.h" +#include "NGAP_PDUSessionResourceReleaseCommandTransfer.h" +#include "NGAP_PDUSessionResourceReleaseResponseTransfer.h" #include "NGAP_PLMNSupportItem.h" #include "NGAP_ProtocolIE-Field.h" #include "NGAP_QosFlowAddOrModifyResponseItem.h"