Commit 9e45f38f authored by Guido Casati's avatar Guido Casati

fix PDU Sesion Release response: add missing PDUSessionResourceReleaseResponseTransfer IE

The PDUSessionResourceReleaseResponse message was missing the mandatory
pDUSessionResourceReleaseResponseTransfer IE in each released PDU session item. This caused Open5GS to send an error indication.

Changes:
- Add encode_ngap_pdusession_release_response_transfer() function to
  properly encode the transfer structure (empty since Secondary RAT Usage
  Information is optional and not used, per 9.3.4.21)
- Always include the mandatory PDUSessionResourceReleasedListRelRes IE
- Always encode the pDUSessionResourceReleaseResponseTransfer for each
  PDU session item
- Fix Release Command handler to decode and log Cause from command transfer:
  instead of incorrectly copying command data to response: the 2 transfer
  IEs in the Command and the Response messages are different and should
  not be mixed
- Split Command/Response struct type definitions
- Add missing includes
parent ad1c92af
...@@ -348,7 +348,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu ...@@ -348,7 +348,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
if (sid < 1 || sid > 255) { if (sid < 1 || sid > 255) {
ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]); 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; msg->nb_pdusessions_torelease = nb_sessions;
...@@ -356,7 +356,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu ...@@ -356,7 +356,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
if (prnt) { if (prnt) {
prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id); 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) { 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"); prnt("\n");
} }
......
...@@ -902,12 +902,6 @@ typedef struct ngap_pdusession_modify_resp_s { ...@@ -902,12 +902,6 @@ typedef struct ngap_pdusession_modify_resp_s {
pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION];
} ngap_pdusession_modify_resp_t; } ngap_pdusession_modify_resp_t;
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_pdusession_release_command_s { typedef struct ngap_pdusession_release_command_s {
/* AMF UE id */ /* AMF UE id */
uint64_t amf_ue_ngap_id; uint64_t amf_ue_ngap_id;
...@@ -918,14 +912,19 @@ typedef struct ngap_pdusession_release_command_s { ...@@ -918,14 +912,19 @@ typedef struct ngap_pdusession_release_command_s {
/* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */
byte_array_t nas_pdu; 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; uint16_t nb_pdusessions_torelease;
uint16_t pdusession_ids[NGAP_MAX_PDU_SESSION];
/* PDUSession release command */
pdusession_release_t pdusession_release_params[NGAP_MAX_PDU_SESSION];
} ngap_pdusession_release_command_t; } 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 { typedef struct ngap_pdusession_release_resp_s {
// AMF UE NGAP ID // AMF UE NGAP ID
uint64_t amf_ue_ngap_id; uint64_t amf_ue_ngap_id;
......
...@@ -1526,9 +1526,9 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_comm ...@@ -1526,9 +1526,9 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_comm
cmd->nb_pdusessions_torelease); cmd->nb_pdusessions_torelease);
e1ap_bearer_mod_req_t req = {0}; e1ap_bearer_mod_req_t req = {0};
for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { 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) { 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; continue;
} }
if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) { if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) {
......
...@@ -1390,9 +1390,20 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin ...@@ -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++) { for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) {
NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p;
item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i];
pdusession_release_t *r = &msg->pdusession_release_params[i]; msg->pdusession_ids[i] = item_p->pDUSessionID;
r->pdusession_id = item_p->pDUSessionID;
r->data = create_byte_array(item_p->pDUSessionResourceReleaseCommandTransfer.size, item_p->pDUSessionResourceReleaseCommandTransfer.buf); /* 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); 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 ...@@ -594,6 +594,24 @@ static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusess
return out; 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) 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 ...@@ -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; ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id;
} }
/* optional */ /* PDU Session Resource Released List (mandatory) */
if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { {
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie); asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes;
ie->criticality = NGAP_Criticality_ignore; ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes;
for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { 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]; pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i];
/* PDU Session ID (mandatory) */
item->pDUSessionID = r->pdusession_id; item->pDUSessionID = r->pdusession_id;
OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)r->data.buf, r->data.len); /* PDU Session Resource Release Response Transfer (mandatory) */
NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); // 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) { if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
NGAP_ERROR("Failed to encode release response\n"); NGAP_ERROR("Failed to encode release response\n");
/* Encode procedure has failed... */ /* Encode procedure has failed... */
......
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
#include "NGAP_PDUSessionResourceSetupResponseTransfer.h" #include "NGAP_PDUSessionResourceSetupResponseTransfer.h"
#include "NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h" #include "NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h"
#include "NGAP_PDUSessionResourceToReleaseItemRelCmd.h" #include "NGAP_PDUSessionResourceToReleaseItemRelCmd.h"
#include "NGAP_PDUSessionResourceReleaseCommandTransfer.h"
#include "NGAP_PDUSessionResourceReleaseResponseTransfer.h"
#include "NGAP_PLMNSupportItem.h" #include "NGAP_PLMNSupportItem.h"
#include "NGAP_ProtocolIE-Field.h" #include "NGAP_ProtocolIE-Field.h"
#include "NGAP_QosFlowAddOrModifyResponseItem.h" #include "NGAP_QosFlowAddOrModifyResponseItem.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment