Merge remote-tracking branch 'origin/fix-pdu-session-release-transfer' into integration_2025_w49 (!3780)
NGAP: fix PDU Session Release Response
1. Refactor NG UE Context Release Request
- Removed incorrect UE Context Release Response code (not in 3GPP TS
38.413)
- Fixed UE Context Release Request to use correct PDU Session Resource
List structure
- Removed incorrect use of pdusession_release_t type
2. Fix PDU Session Release Response
- Added missing mandatory PDUSessionResourceReleaseResponseTransfer IE
- Implemented encode_ngap_pdusession_release_response_transfer()
function
- Fixed Release Command handler to correctly decode Cause from command
transfer
- Split Command/Response struct type definitions to prevent mixing
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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... */
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user