mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
PDU Session Modify: extend PDU Session Modify Transfer (NGAP/RRC) with QoS add/modify/release
This commit extends the PDU Session Resource Modify Request handling (within
PDU Session Modify) to fully support QoS Flow add/modify and release operations
(3GPP TS 38.413 section 9.3.4.3) via the Transfer IE. This is propagated to
RRC which performs PDU Session update, which occurs upon PDU Session Modify.
Refactoring was necessary since type `pdusession_transfer_t` and
`pdusession_resource_item_t` both for setup, were inaccurately used for the modify procedure.
The implementation adds proper type definitions, decoding logic,
and error handling for QoS flow management during PDU session modification transfer,
namely:
- Adds QoS add/modify and release lists to the NGAP Modify Request Transfer type
- Introduces QoS Flow With Cause IE
- Decode new IEs and propagate QoS changes to RRC session state
NGAP PDU Session Modify Request Transfer:
- Add qos_flow_to_release_t structure to represent QoS Flow to Release Items IE
with QFI and release cause (per 3GPP TS 38.413 section 9.3.1.13)
- Introduce pdusession_mod_req_transfer_t structure to properly represent
PDU Session Resource Modify Request Transfer IEs:
* QoS Flow Add or Modify Request List (mandatory)
* QoS Flow to Release List (optional)
- Add pdusession_resource_mod_item_t structure for PDU Session Resource
Modify Request Items, replacing pdusession_resource_item_t, which is for setup
- Update ngap_pdusession_modify_req_t to use the new type-specific structure
- Refactor decodePDUSessionResourceModify() to return
pdusession_mod_req_transfer_t instead of pdusession_transfer_t
- Implement proper decoding of QosFlowAddOrModifyRequestList IE
- Add decoding support for QosFlowToReleaseList (QosFlowListWithCause) IE:
* Extract QFI and cause for each QoS flow to be released
- Improve error handling throughout
ngap_msg_includes.h:
- Add includes for NGAP_QosFlowListWithCause.h and
NGAP_QosFlowWithCauseItem.h to support QoS flow release decoding
NGAP/RRC:
- Update nr_rrc_update_pdusession() function signature to accept
pdusession_resource_mod_item_t instead of pdusession_resource_item_t
- Remove references to unnecessary pdu_session_type and n3_incoming
fields that are not part of the Modify Request Transfer structure
- Update QoS flow update logic to use nb_qos_to_add_modify and
qos_to_add_modify fields from the new transfer structure
This implementation aligns NGAP with 3GPP TS 38.413 specifications
and provides a foundation for handling QoS flow modifications and releases
during PDU session resource modification procedures.
Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
@@ -845,18 +845,42 @@ typedef struct {
|
||||
uint8_t pdu_session_id[NR_MAX_NB_PDU_SESSIONS];
|
||||
} ngap_ue_release_complete_t;
|
||||
|
||||
/* QoS Flow to Release Item (9.3.1.13 3GPP TS 38.413) */
|
||||
typedef struct qos_flow_to_release_s {
|
||||
uint8_t qfi;
|
||||
ngap_cause_t cause;
|
||||
} qos_flow_to_release_t;
|
||||
|
||||
/* PDU Session Resource Modify Request Transfer (9.3.4.3 3GPP TS 38.413) */
|
||||
typedef struct {
|
||||
// QoS Flow Add or Modify Request List (Mandatory)
|
||||
uint8_t nb_qos_to_add_modify;
|
||||
pdusession_level_qos_parameter_t qos_to_add_modify[MAX_QOS_FLOWS];
|
||||
// QoS Flow to Release List (Optional)
|
||||
uint8_t nb_qos_to_release;
|
||||
qos_flow_to_release_t qos_to_release[MAX_QOS_FLOWS];
|
||||
} pdusession_mod_req_transfer_t;
|
||||
|
||||
/* PDU Session Resource Setup/Modify Request Item */
|
||||
typedef struct {
|
||||
// PDU Session ID (Mandatory)
|
||||
int pdusession_id;
|
||||
// NAS PDU (Optional)
|
||||
byte_array_t nas_pdu;
|
||||
// S-NSSAI (Optional)
|
||||
nssai_t nssai;
|
||||
// PDU Session Resource Modify Request Transfer (Mandatory)
|
||||
pdusession_mod_req_transfer_t pdusessionTransfer;
|
||||
} pdusession_resource_mod_item_t;
|
||||
|
||||
typedef struct ngap_pdusession_modify_req_s {
|
||||
/* AMF UE id */
|
||||
/* AMF UE NGAP ID (Mandatory) */
|
||||
uint64_t amf_ue_ngap_id;
|
||||
|
||||
/* gNB ue ngap id as initialized by NGAP layer */
|
||||
/* RAN UE NGAP ID (Mandatory) */
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
|
||||
/* Number of pdusession to be modify in the list */
|
||||
/* PDU Session Resource Modify Request List (Mandatory) */
|
||||
uint16_t nb_pdusessions_tomodify;
|
||||
|
||||
// PDU Session Resource Modify Request List
|
||||
pdusession_resource_item_t pdusession[NR_MAX_NB_PDU_SESSIONS];
|
||||
pdusession_resource_mod_item_t pdusession[NR_MAX_NB_PDU_SESSIONS];
|
||||
} ngap_pdusession_modify_req_t;
|
||||
|
||||
/* 9.2.1.6 of 3GPP TS 38.413 */
|
||||
|
||||
@@ -1005,16 +1005,15 @@ static void nr_rrc_update_qos(seq_arr_t *list, const int nb_qos, const pdusessio
|
||||
}
|
||||
|
||||
/** @brief Update stored pdusession_t in list from NGAP PDU Session Resource item */
|
||||
static void nr_rrc_update_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src)
|
||||
static void nr_rrc_update_pdusession(pdusession_t *dst, const pdusession_resource_mod_item_t *src)
|
||||
{
|
||||
dst->pdusession_id = src->pdusession_id;
|
||||
dst->nas_pdu = src->nas_pdu;
|
||||
dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type;
|
||||
dst->n3_incoming = src->pdusessionTransfer.n3_incoming;
|
||||
dst->nssai = src->nssai;
|
||||
DevAssert(dst->qos.data); // QoS list has to be initialized at this stage
|
||||
// Update QoS flow
|
||||
nr_rrc_update_qos(&dst->qos, src->pdusessionTransfer.nb_qos, src->pdusessionTransfer.qos);
|
||||
const pdusession_mod_req_transfer_t *transfer = &src->pdusessionTransfer;
|
||||
nr_rrc_update_qos(&dst->qos, transfer->nb_qos_to_add_modify, transfer->qos_to_add_modify);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1065,7 +1064,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(const ngap_pdusession_modify_req_
|
||||
bool all_failed = true;
|
||||
DevAssert(req->nb_pdusessions_tomodify <= NR_MAX_NB_PDU_SESSIONS);
|
||||
for (int i = 0; i < req->nb_pdusessions_tomodify; i++) {
|
||||
const pdusession_resource_item_t *sessMod = &req->pdusession[i];
|
||||
const pdusession_resource_mod_item_t *sessMod = &req->pdusession[i];
|
||||
rrc_pdu_session_param_t *session = find_pduSession(&UE->pduSessions, sessMod->pdusession_id);
|
||||
if (!session) {
|
||||
/* 8.2.3.4 3GPP TS 38.413: If the NG-RAN node receives unrecognized PDU Session ID IEs,
|
||||
|
||||
@@ -1148,7 +1148,7 @@ static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_N
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool decodePDUSessionResourceModify(pdusession_transfer_t *out, const OCTET_STRING_t in)
|
||||
static bool decodePDUSessionResourceModify(pdusession_mod_req_transfer_t *out, const OCTET_STRING_t in)
|
||||
{
|
||||
void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, in);
|
||||
if (!decoded) {
|
||||
@@ -1156,23 +1156,69 @@ static bool decodePDUSessionResourceModify(pdusession_transfer_t *out, const OCT
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset counters
|
||||
out->nb_qos_to_add_modify = 0;
|
||||
out->nb_qos_to_release = 0;
|
||||
|
||||
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceModifyRequestTransfer_t *)decoded;
|
||||
for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) {
|
||||
NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j];
|
||||
if (!pdusessionTransfer_ies) {
|
||||
LOG_E(NGAP, "NULL protocol IE at index %d in PDUSessionResourceModifyRequestTransfer\n", j);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
switch (pdusessionTransfer_ies->id) {
|
||||
/* optional QosFlowAddOrModifyRequestList */
|
||||
case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList:
|
||||
out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count;
|
||||
for (int i = 0; i < out->nb_qos; i++) {
|
||||
NGAP_QosFlowAddOrModifyRequestItem_t *item =
|
||||
pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[i];
|
||||
out->qos[i] = fill_qos(item->qosFlowIdentifier, item->qosFlowLevelQosParameters);
|
||||
case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList: {
|
||||
NGAP_QosFlowAddOrModifyRequestList_t *addmod = &pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList;
|
||||
out->nb_qos_to_add_modify = addmod->list.count;
|
||||
if (out->nb_qos_to_add_modify > MAX_QOS_FLOWS) {
|
||||
LOG_E(NGAP, "QosFlowAddOrModifyRequestList count %d exceeds MAX_QOS_FLOWS %d\n",
|
||||
out->nb_qos_to_add_modify, MAX_QOS_FLOWS);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < out->nb_qos_to_add_modify; i++) {
|
||||
NGAP_QosFlowAddOrModifyRequestItem_t *item = addmod->list.array[i];
|
||||
if (!item) {
|
||||
LOG_E(NGAP, "NULL QosFlowAddOrModifyRequestItem at index %d\n", i);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
if (!item->qosFlowLevelQosParameters) {
|
||||
LOG_E(NGAP, "NULL qosFlowLevelQosParameters for QFI %ld\n", item->qosFlowIdentifier);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
out->qos_to_add_modify[i] = fill_qos(item->qosFlowIdentifier, item->qosFlowLevelQosParameters);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList: {
|
||||
NGAP_QosFlowListWithCause_t *list = &pdusessionTransfer_ies->value.choice.QosFlowListWithCause;
|
||||
out->nb_qos_to_release = list->list.count;
|
||||
if (out->nb_qos_to_release > MAX_QOS_FLOWS) {
|
||||
LOG_E(NGAP, "QosFlowToReleaseList count %d exceeds MAX_QOS_FLOWS %d\n",
|
||||
out->nb_qos_to_release, MAX_QOS_FLOWS);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < out->nb_qos_to_release; i++) {
|
||||
NGAP_QosFlowWithCauseItem_t *item = list->list.array[i];
|
||||
if (!item) {
|
||||
LOG_E(NGAP, "NULL QosFlowWithCauseItem at index %d\n", i);
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
return false;
|
||||
}
|
||||
out->qos_to_release[i].qfi = item->qosFlowIdentifier;
|
||||
out->qos_to_release[i].cause = decode_ngap_cause(&item->cause);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_E(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
|
||||
return false;
|
||||
LOG_W(NGAP, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
|
||||
@@ -1262,7 +1308,8 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint
|
||||
if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) {
|
||||
msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
|
||||
if (!decodePDUSessionResourceModify(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer)) {
|
||||
NGAP_ERROR("Failed to decode pDUSessionResourceModifyRequestTransfer\n");
|
||||
NGAP_ERROR("Failed to decode pDUSessionResourceModifyRequestTransfer for PDU session %lu\n", item_p->pDUSessionID);
|
||||
itti_free(TASK_NGAP, message_p);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -95,5 +95,6 @@
|
||||
#include "NGAP_DRBStatusDL.h"
|
||||
#include "NGAP_DRBStatusDL18.h"
|
||||
#include "NGAP_DRBStatusDL12.h"
|
||||
|
||||
#include "NGAP_QosFlowListWithCause.h"
|
||||
#include "NGAP_QosFlowWithCauseItem.h"
|
||||
#endif // NGAP_MSG_INCLUDES_H
|
||||
|
||||
Reference in New Issue
Block a user