Refactor NGAP decodePDUSessionResourceSetup/Modify to improve RRC/NGAP separation

Motivation of the commit:

Previously, the RRC module on the NGAP interface directly handled ASN.1 decoding
of NGAP PDU Session Resource items, that was directly stored in pdusession_t, i.e.
in the UE context. Decode logic between Setup and Modify was also duplicated.,
e.g. fill_qos/fill_qos2. The idea behind this change is to achieve this flow:
(1) NGAP handler: decoding (2) ITTI to RRC: transfer decoded message (3) RRC
handler: process decoded message, e.g. store in UE context, etc..

The goal of this commit is to:

* improve the NGAP decoding library by adding decoding functions
* let RRC handle the already decoded data
* enhance error handling, with decode failures now consistently detected and rejected early
* have a cleaner, more maintainable code with fewer duplications and a clearer separation of modules

Changes:
* Moved all ASN.1 decode logic for PDU Session Resource items into the NGAP library
* Introduced decode functions for NGAP IEs whenever necessary, e.g. decode_TNLInformation
decode_pdusession_transfer
* Removed duplicate fill_qos functions and centralized QoS handling in NGAP
* Added function to copy from NGAP PDU Session Resource item to RRC pdusession_t: this actually
  replaces decodePDUSessionResourceSetup in RRC, copying from the decoded NGAP struct to
  the UE context pdusession_t
This commit is contained in:
Guido Casati
2025-06-18 10:52:15 +02:00
parent 48a4c2b0ab
commit 0c408875a3
5 changed files with 177 additions and 223 deletions
+10 -1
View File
@@ -538,12 +538,21 @@ typedef struct ngap_downlink_nas_s {
byte_array_t nas_pdu;
} ngap_downlink_nas_t;
/* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */
typedef struct {
uint8_t nb_qos;
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
pdu_session_type_t pdu_session_type;
// UPF endpoint of the NG-U (N3) transport bearer
gtpu_tunnel_t n3_incoming;
} pdusession_transfer_t;
/* PDU Session Resource Setup/Modify Request Item */
typedef struct {
int pdusession_id;
byte_array_t nas_pdu;
nssai_t nssai;
byte_array_t pdusessionTransfer;
pdusession_transfer_t pdusessionTransfer;
} pdusession_resource_item_t;
typedef struct ngap_initial_context_setup_req_s {
-1
View File
@@ -103,7 +103,6 @@ typedef struct pdusession_s {
/* Unique pdusession_id for the UE. */
int pdusession_id;
byte_array_t nas_pdu;
byte_array_t pdusessionTransfer;
uint8_t nb_qos;
/* Quality of service for this pdusession */
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
+21 -214
View File
@@ -161,6 +161,20 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn)
return guami;
}
/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */
static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src)
{
dst->pdusession_id = src->pdusession_id;
dst->nas_pdu = src->nas_pdu;
dst->nb_qos = src->pdusessionTransfer.nb_qos;
for (uint8_t i = 0; i < src->pdusessionTransfer.nb_qos && i < QOSFLOW_MAX_VALUE; ++i) {
dst->qos[i] = src->pdusessionTransfer.qos[i];
}
dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type;
dst->n3_incoming = src->pdusessionTransfer.n3_incoming;
dst->nssai = src->nssai;
}
/**
* @brief Prepare the Initial UE Message (Uplink NAS) to be forwarded to the AMF over N2
* extracts NAS PDU, Selected PLMN and Registered AMF from the RRCSetupComplete
@@ -225,113 +239,6 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p);
}
static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session)
{
DevAssert(qos->list.count > 0);
DevAssert(qos->list.count <= NGAP_maxnoofQosFlows);
for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) {
NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx];
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = NON_DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority;
tmp->priority_level = tmp2->priorityLevelARP;
tmp->pre_emp_capability = tmp2->pre_emptionCapability;
tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability;
}
session->nb_qos = qos->list.count;
}
static int decodePDUSessionResourceSetup(pdusession_t *out, const pdusession_resource_item_t *session)
{
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL;
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
asn_dec_rval_t dec_rval = aper_decode(&st,
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
(void **)&pdusessionTransfer,
session->pdusessionTransfer.buf,
session->pdusessionTransfer.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "can not decode PDUSessionResourceSetupRequestTransfer\n");
return -1;
}
for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) {
NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i];
switch (pdusessionTransfer_ies->id) {
/* optional PDUSessionAggregateMaximumBitRate */
case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
break;
/* mandatory UL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: {
NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel;
/* Set the transport layer address */
memcpy(out->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
out->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused;
/* GTP tunnel endpoint ID */
OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out->n3_incoming.teid);
}
break;
/* optional AdditionalUL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
break;
/* optional DataForwardingNotPossible */
case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible:
break;
/* mandatory PDUSessionType */
case NGAP_ProtocolIE_ID_id_PDUSessionType:
out->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
break;
/* optional SecurityIndication */
case NGAP_ProtocolIE_ID_id_SecurityIndication:
break;
/* optional NetworkInstance */
case NGAP_ProtocolIE_ID_id_NetworkInstance:
break;
/* mandatory QosFlowSetupRequestList */
case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, out);
break;
/* optional CommonNetworkInstance */
case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
break;
default:
LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
return -1;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer);
return 0;
}
/**
* @brief Triggers bearer setup for the specified UE.
*
@@ -363,7 +270,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions);
session->pdu_session_type = sessions[i].pdu_session_type;
session->nas_pdu = sessions[i].nas_pdu;
session->pdusessionTransfer = sessions[i].pdusessionTransfer;
session->nssai = sessions[i].nssai;
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
security_information_t *secInfo = &bearer_req.secInfo;
@@ -519,9 +425,8 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
UE->n_initial_pdu = req->nb_of_pdusessions;
UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus));
AssertFatal(UE->initial_pdus != NULL, "out of memory\n");
for (int i = 0; i < UE->n_initial_pdu; ++i) {
decodePDUSessionResourceSetup(&UE->initial_pdus[i], &req->pdusession[i]);
}
for (int i = 0; i < UE->n_initial_pdu; ++i)
cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]);
}
/* security */
@@ -935,9 +840,9 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
}
pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0};
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) {
decodePDUSessionResourceSetup(&to_setup[i], &msg->pdusession[i]);
}
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i)
cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]);
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) {
// Reject PDU Session Resource setup if there's no CU-UP associated
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id);
@@ -949,104 +854,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
}
}
static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *session)
{
// we need to duplicate the function fill_qos because all data types are slightly different
DevAssert(qos->list.count > 0);
DevAssert(qos->list.count <= NGAP_maxnoofQosFlows);
for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) {
NGAP_QosFlowAddOrModifyRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx];
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = NON_DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority;
tmp->priority_level = tmp2->priorityLevelARP;
tmp->pre_emp_capability = tmp2->pre_emptionCapability;
tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability;
}
session->nb_qos = qos->list.count;
}
static void decodePDUSessionResourceModify(pdusession_t *param, const byte_array_t pdu)
{
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = NULL;
asn_dec_rval_t dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
(void **)&pdusessionTransfer,
pdu.buf,
pdu.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "could not decode PDUSessionResourceModifyRequestTransfer\n");
return;
}
for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) {
NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j];
switch (pdusessionTransfer_ies->id) {
/* optional PDUSessionAggregateMaximumBitRate */
case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate\n");
break;
/* optional UL-NGU-UP-TNLModifyList */
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList\n");
break;
/* optional NetworkInstance */
case NGAP_ProtocolIE_ID_id_NetworkInstance:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_NetworkInstance\n");
break;
/* optional QosFlowAddOrModifyRequestList */
case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList:
fill_qos2(&pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList, param);
break;
/* optional QosFlowToReleaseList */
case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList:
// TODO
LOG_E(NR_RRC, "Can't handle NGAP_ProtocolIE_ID_id_QosFlowToReleaseList\n");
break;
/* optional AdditionalUL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation\n");
break;
/* optional CommonNetworkInstance */
case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_CommonNetworkInstance\n");
break;
default:
LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
return;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,pdusessionTransfer );
}
//------------------------------------------------------------------------------
int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t instance)
//------------------------------------------------------------------------------
@@ -1090,8 +897,8 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
if (sessMod->nas_pdu.buf != NULL) {
UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
}
// Save new pdu session parameters, qos, upf addr, teid
decodePDUSessionResourceModify(&sess->param, UE->pduSession[i].param.pdusessionTransfer);
for (int i = 0; i < req->nb_pdusessions_tomodify; ++i)
cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]);
}
}
+139 -7
View File
@@ -694,6 +694,99 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
return 0;
}
static void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf)
{
void *decoded = NULL;
asn_codec_ctx_t ctx = {.max_stack_size = 100 * 1000};
asn_dec_rval_t rval = aper_decode(&ctx, td, &decoded, buf.buf, buf.size, 0, 0);
if (rval.code != RC_OK) {
NGAP_ERROR("Decoding failed for %s\n", td->name);
return NULL;
}
return decoded;
}
static pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params)
{
pdusession_level_qos_parameter_t out = {0};
// QFI
out.qfi = qfi;
AssertFatal(params != NULL, "QoS parameters are NULL\n");
// QosCharacteristics
const NGAP_QosCharacteristics_t *qosChar = &params->qosCharacteristics;
AssertFatal(qosChar != NULL, "QoS characteristics are NULL\n");
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.nonDynamic5QI != NULL, "nonDynamic5QI is NULL\n");
out.fiveQI_type = NON_DYNAMIC;
out.fiveQI = qosChar->choice.nonDynamic5QI->fiveQI;
} else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI != NULL, "dynamic5QI is NULL\n");
out.fiveQI_type = DYNAMIC;
out.fiveQI = *qosChar->choice.dynamic5QI->fiveQI;
} else {
AssertFatal(0, "Unsupported QoS Characteristics present value: %d\n", qosChar->present);
}
// Allocation and Retention Priority
const NGAP_AllocationAndRetentionPriority_t *arp = &params->allocationAndRetentionPriority;
out.allocation_retention_priority.priority_level = arp->priorityLevelARP;
out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability;
out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability;
return out;
}
static gtpu_tunnel_t decode_TNLInformation(const NGAP_GTPTunnel_t *gTPTunnel_p)
{
gtpu_tunnel_t out = {0};
// Transport layer address
memcpy(out.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
out.addr.length = gTPTunnel_p->transportLayerAddress.size - gTPTunnel_p->transportLayerAddress.bits_unused;
// GTP tunnel endpoint ID
OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out.teid);
return out;
}
/** @brief Decode PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */
static bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in)
{
void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, in);
if (!decoded) {
LOG_E(NR_RRC, "Failed to decode PDUSessionResourceSetupRequestTransfer\n");
return false;
}
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceSetupRequestTransfer_t *)decoded;
for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) {
NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i];
switch (pdusessionTransfer_ies->id) {
// UL NG-U UP TNL Information (Mandatory)
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation:
out->n3_incoming = decode_TNLInformation(pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel);
break;
// PDU Session Type (Mandatory)
case NGAP_ProtocolIE_ID_id_PDUSessionType:
out->pdu_session_type = pdusessionTransfer_ies->value.choice.PDUSessionType;
break;
// QoS Flow Setup Request List (Mandatory)
case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count;
for (int i = 0; i < out->nb_qos; i++) {
NGAP_QosFlowSetupRequestItem_t *item = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[i];
out->qos[i] = fill_qos(item->qosFlowIdentifier, &item->qosFlowLevelQosParameters);
}
break;
default:
LOG_D(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer);
return true;
}
static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
int i;
@@ -767,8 +860,11 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
if (item_p->nAS_PDU) {
msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
}
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
if (!ret) {
NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Initial Context Setup Request\n");
return -1;
}
}
}
@@ -941,11 +1037,14 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3
// S-NSSAI
msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf);
msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
if (!ret) {
NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Setup Request\n");
return -1;
}
}
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);
return 0;
}
@@ -1039,6 +1138,37 @@ 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)
{
void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, in);
if (!decoded) {
LOG_E(NR_RRC, "Failed to decode PDUSessionResourceModifyRequestTransfer\n");
return false;
}
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];
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);
}
break;
default:
LOG_E(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
return false;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
return true;
}
static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
ngap_gNB_amf_data_t *amf_desc_p = NULL;
@@ -1121,8 +1251,10 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint
// check for the NAS PDU
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);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer;
msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
if (!decodePDUSessionResourceModify(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer)) {
NGAP_ERROR("Failed to decode pDUSessionResourceModifyRequestTransfer\n");
return -1;
}
} else {
LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID);
continue;
+7
View File
@@ -71,5 +71,12 @@
#include "NGAP_UnsuccessfulOutcome.h"
#include "NGAP_UserLocationInformationNR.h"
#include "NGAP_asn_constant.h"
#include "NGAP_PDUSessionResourceSetupRequestTransfer.h"
#include "NGAP_QosFlowSetupRequestItem.h"
#include "NGAP_QosCharacteristics.h"
#include "NGAP_NonDynamic5QIDescriptor.h"
#include "NGAP_Dynamic5QIDescriptor.h"
#include "NGAP_PDUSessionResourceModifyRequestTransfer.h"
#include "NGAP_QosFlowAddOrModifyRequestItem.h"
#endif // NGAP_MSG_INCLUDES_H