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:
Robert Schmidt
2025-12-02 13:45:17 +01:00
9 changed files with 79 additions and 72 deletions
-1
View File
@@ -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)
+24 -22
View File
@@ -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;
-4
View File
@@ -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;
+5 -32
View File
@@ -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) {