From c89dd97e8837933bac102c82444a2e24f68cab17 Mon Sep 17 00:00:00 2001 From: aligungr Date: Wed, 29 Sep 2021 16:24:31 +0300 Subject: [PATCH] Initial Context Setup improvements --- src/gnb/ngap/context.cpp | 189 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 179 insertions(+), 10 deletions(-) diff --git a/src/gnb/ngap/context.cpp b/src/gnb/ngap/context.cpp index 231a6864f..584fb5504 100644 --- a/src/gnb/ngap/context.cpp +++ b/src/gnb/ngap/context.cpp @@ -6,6 +6,7 @@ // and subject to the terms and conditions defined in LICENSE file. // +#include "encode.hpp" #include "task.hpp" #include "utils.hpp" @@ -13,11 +14,35 @@ #include #include +#include +#include +#include #include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include #include @@ -27,7 +52,6 @@ #include #include #include -#include namespace nr::gnb { @@ -40,19 +64,164 @@ void NgapTask::receiveInitialContextSetup(int amfId, ASN_NGAP_InitialContextSetu if (ue == nullptr) return; - auto *ie = asn::ngap::GetProtocolIe(msg, ASN_NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate); - if (ie) + auto *reqIe = asn::ngap::GetProtocolIe(msg, ASN_NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate); + if (reqIe) { - ue->ueAmbr.dlAmbr = asn::GetUnsigned64(ie->UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL) / 8ull; - ue->ueAmbr.ulAmbr = asn::GetUnsigned64(ie->UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL) / 8ull; + ue->ueAmbr.dlAmbr = asn::GetUnsigned64(reqIe->UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL) / 8ull; + ue->ueAmbr.ulAmbr = asn::GetUnsigned64(reqIe->UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL) / 8ull; } - auto *response = asn::ngap::NewMessagePdu({}); - sendNgapUeAssociated(ue->ctxId, response); + std::vector successList; + std::vector failedList; - ie = asn::ngap::GetProtocolIe(msg, ASN_NGAP_ProtocolIE_ID_id_NAS_PDU); - if (ie) - deliverDownlinkNas(ue->ctxId, asn::GetOctetString(ie->NAS_PDU)); + reqIe = asn::ngap::GetProtocolIe(msg, ASN_NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq); + if (reqIe) + { + auto &list = reqIe->PDUSessionResourceSetupListCxtReq.list; + for (int i = 0; i < list.count; i++) + { + auto &item = list.array[i]; + auto *transfer = ngap_encode::Decode( + asn_DEF_ASN_NGAP_PDUSessionResourceSetupRequestTransfer, item->pDUSessionResourceSetupRequestTransfer); + if (transfer == nullptr) + { + m_logger->err( + "Unable to decode a PDU session resource setup request transfer. Ignoring the relevant item"); + asn::Free(asn_DEF_ASN_NGAP_PDUSessionResourceSetupRequestTransfer, transfer); + continue; + } + + auto *resource = new PduSessionResource(ue->ctxId, static_cast(item->pDUSessionID)); + + auto *ie = asn::ngap::GetProtocolIe(transfer, ASN_NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate); + if (ie) + { + resource->sessionAmbr.dlAmbr = + asn::GetUnsigned64(ie->PDUSessionAggregateMaximumBitRate.pDUSessionAggregateMaximumBitRateDL) / + 8ull; + resource->sessionAmbr.ulAmbr = + asn::GetUnsigned64(ie->PDUSessionAggregateMaximumBitRate.pDUSessionAggregateMaximumBitRateUL) / + 8ull; + } + + ie = asn::ngap::GetProtocolIe(transfer, ASN_NGAP_ProtocolIE_ID_id_DataForwardingNotPossible); + if (ie) + resource->dataForwardingNotPossible = true; + + ie = asn::ngap::GetProtocolIe(transfer, ASN_NGAP_ProtocolIE_ID_id_PDUSessionType); + if (ie) + resource->sessionType = ngap_utils::PduSessionTypeFromAsn(ie->PDUSessionType); + + ie = asn::ngap::GetProtocolIe(transfer, ASN_NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation); + if (ie) + { + resource->upTunnel.teid = + (uint32_t)asn::GetOctet4(ie->UPTransportLayerInformation.choice.gTPTunnel->gTP_TEID); + + resource->upTunnel.address = + asn::GetOctetString(ie->UPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress); + } + + ie = asn::ngap::GetProtocolIe(transfer, ASN_NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList); + if (ie) + { + auto *ptr = asn::New(); + asn::DeepCopy(asn_DEF_ASN_NGAP_QosFlowSetupRequestList, ie->QosFlowSetupRequestList, ptr); + + resource->qosFlows = asn::WrapUnique(ptr, asn_DEF_ASN_NGAP_QosFlowSetupRequestList); + } + + auto error = setupPduSessionResource(ue, resource); + if (error.has_value()) + { + auto *tr = asn::New(); + ngap_utils::ToCauseAsn_Ref(error.value(), tr->cause); + + OctetString encodedTr = + ngap_encode::EncodeS(asn_DEF_ASN_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, tr); + + if (encodedTr.length() == 0) + throw std::runtime_error("PDUSessionResourceSetupUnsuccessfulTransfer encoding failed"); + + asn::Free(asn_DEF_ASN_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, tr); + + auto *res = asn::New(); + res->pDUSessionID = resource->psi; + asn::SetOctetString(res->pDUSessionResourceSetupUnsuccessfulTransfer, encodedTr); + + failedList.push_back(res); + } + else + { + auto *tr = asn::New(); + + auto &qosList = resource->qosFlows->list; + for (int iQos = 0; iQos < qosList.count; iQos++) + { + auto *associatedQosFlowItem = asn::New(); + associatedQosFlowItem->qosFlowIdentifier = qosList.array[iQos]->qosFlowIdentifier; + asn::SequenceAdd(tr->dLQosFlowPerTNLInformation.associatedQosFlowList, associatedQosFlowItem); + } + + auto &upInfo = tr->dLQosFlowPerTNLInformation.uPTransportLayerInformation; + upInfo.present = ASN_NGAP_UPTransportLayerInformation_PR_gTPTunnel; + upInfo.choice.gTPTunnel = asn::New(); + asn::SetBitString(upInfo.choice.gTPTunnel->transportLayerAddress, resource->downTunnel.address); + asn::SetOctetString4(upInfo.choice.gTPTunnel->gTP_TEID, (octet4)resource->downTunnel.teid); + + OctetString encodedTr = + ngap_encode::EncodeS(asn_DEF_ASN_NGAP_PDUSessionResourceSetupResponseTransfer, tr); + + if (encodedTr.length() == 0) + throw std::runtime_error("PDUSessionResourceSetupResponseTransfer encoding failed"); + + asn::Free(asn_DEF_ASN_NGAP_PDUSessionResourceSetupResponseTransfer, tr); + + auto *res = asn::New(); + res->pDUSessionID = resource->psi; + asn::SetOctetString(res->pDUSessionResourceSetupResponseTransfer, encodedTr); + + successList.push_back(res); + } + + asn::Free(asn_DEF_ASN_NGAP_PDUSessionResourceSetupRequestTransfer, transfer); + } + } + + reqIe = asn::ngap::GetProtocolIe(msg, ASN_NGAP_ProtocolIE_ID_id_NAS_PDU); + if (reqIe) + deliverDownlinkNas(ue->ctxId, asn::GetOctetString(reqIe->NAS_PDU)); + + std::vector responseIes; + + if (!successList.empty()) + { + auto *ie = asn::New(); + ie->id = ASN_NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtRes; + ie->criticality = ASN_NGAP_Criticality_ignore; + ie->value.present = ASN_NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceSetupListCxtRes; + + for (auto &item : successList) + asn::SequenceAdd(ie->value.choice.PDUSessionResourceSetupListCxtRes, item); + + responseIes.push_back(ie); + } + + if (!failedList.empty()) + { + auto *ie = asn::New(); + ie->id = ASN_NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListCxtRes; + ie->criticality = ASN_NGAP_Criticality_ignore; + ie->value.present = ASN_NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListCxtRes; + + for (auto &item : failedList) + asn::SequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListCxtRes, item); + + responseIes.push_back(ie); + } + + auto *response = asn::ngap::NewMessagePdu(responseIes); + sendNgapUeAssociated(ue->ctxId, response); auto *w = new NmGnbNgapToGtp(NmGnbNgapToGtp::UE_CONTEXT_UPDATE); w->update = std::make_unique(true, ue->ctxId, ue->ueAmbr);