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:
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = ¶ms->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 = ¶ms->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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user