Skip to content

Commit

Permalink
Initial Context Setup improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
aligungr committed Sep 29, 2021
1 parent fbaea18 commit c89dd97
Showing 1 changed file with 179 additions and 10 deletions.
189 changes: 179 additions & 10 deletions src/gnb/ngap/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,43 @@
// and subject to the terms and conditions defined in LICENSE file.
//

#include "encode.hpp"
#include "task.hpp"
#include "utils.hpp"

#include <gnb/gtp/task.hpp>
#include <gnb/rrc/task.hpp>

#include <asn/ngap/ASN_NGAP_AMF-UE-NGAP-ID.h>
#include <asn/ngap/ASN_NGAP_AssociatedQosFlowItem.h>
#include <asn/ngap/ASN_NGAP_AssociatedQosFlowList.h>
#include <asn/ngap/ASN_NGAP_GTPTunnel.h>
#include <asn/ngap/ASN_NGAP_InitialContextSetupRequest.h>
#include <asn/ngap/ASN_NGAP_InitialContextSetupResponse.h>
#include <asn/ngap/ASN_NGAP_NGAP-PDU.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceFailedToSetupItemCxtRes.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceFailedToSetupItemSURes.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceItemCxtRelReq.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceReleaseCommand.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceReleaseResponse.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceReleaseResponseTransfer.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceReleasedItemRelRes.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupItemCxtReq.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupItemCxtRes.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupItemSUReq.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupItemSURes.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupListCxtReq.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupRequest.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupRequestTransfer.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupResponse.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupResponseTransfer.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h>
#include <asn/ngap/ASN_NGAP_PDUSessionResourceToReleaseItemRelCmd.h>
#include <asn/ngap/ASN_NGAP_ProtocolIE-Field.h>
#include <asn/ngap/ASN_NGAP_QosFlowPerTNLInformationItem.h>
#include <asn/ngap/ASN_NGAP_QosFlowPerTNLInformationList.h>
#include <asn/ngap/ASN_NGAP_QosFlowSetupRequestItem.h>
#include <asn/ngap/ASN_NGAP_QosFlowSetupRequestList.h>
#include <asn/ngap/ASN_NGAP_SuccessfulOutcome.h>
#include <asn/ngap/ASN_NGAP_UE-NGAP-ID-pair.h>
#include <asn/ngap/ASN_NGAP_UE-NGAP-IDs.h>
Expand All @@ -27,7 +52,6 @@
#include <asn/ngap/ASN_NGAP_UEContextReleaseCommand.h>
#include <asn/ngap/ASN_NGAP_UEContextReleaseComplete.h>
#include <asn/ngap/ASN_NGAP_UEContextReleaseRequest.h>
#include <asn/ngap/ASN_NGAP_UESecurityCapabilities.h>

namespace nr::gnb
{
Expand All @@ -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<ASN_NGAP_InitialContextSetupResponse>({});
sendNgapUeAssociated(ue->ctxId, response);
std::vector<ASN_NGAP_PDUSessionResourceSetupItemCxtRes *> successList;
std::vector<ASN_NGAP_PDUSessionResourceFailedToSetupItemCxtRes *> 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_NGAP_PDUSessionResourceSetupRequestTransfer>(
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<int>(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_NGAP_QosFlowSetupRequestList>();
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<ASN_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer>();
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<ASN_NGAP_PDUSessionResourceFailedToSetupItemCxtRes>();
res->pDUSessionID = resource->psi;
asn::SetOctetString(res->pDUSessionResourceSetupUnsuccessfulTransfer, encodedTr);

failedList.push_back(res);
}
else
{
auto *tr = asn::New<ASN_NGAP_PDUSessionResourceSetupResponseTransfer>();

auto &qosList = resource->qosFlows->list;
for (int iQos = 0; iQos < qosList.count; iQos++)
{
auto *associatedQosFlowItem = asn::New<ASN_NGAP_AssociatedQosFlowItem>();
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_NGAP_GTPTunnel>();
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<ASN_NGAP_PDUSessionResourceSetupItemCxtRes>();
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<ASN_NGAP_InitialContextSetupResponseIEs *> responseIes;

if (!successList.empty())
{
auto *ie = asn::New<ASN_NGAP_InitialContextSetupResponseIEs>();
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<ASN_NGAP_InitialContextSetupResponseIEs>();
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<ASN_NGAP_InitialContextSetupResponse>(responseIes);
sendNgapUeAssociated(ue->ctxId, response);

auto *w = new NmGnbNgapToGtp(NmGnbNgapToGtp::UE_CONTEXT_UPDATE);
w->update = std::make_unique<GtpUeContextUpdate>(true, ue->ctxId, ue->ueAmbr);
Expand Down

0 comments on commit c89dd97

Please sign in to comment.