Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added intelligent AMF selection at gNB #731

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/gnb/ngap/management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void NgapTask::createAmfContext(const GnbAmfConfig &conf)
m_amfCtx[ctx->ctxId] = ctx;
}

void NgapTask::createUeContext(int ueId)
void NgapTask::createUeContext(int ueId, const int32_t &requestedSliceType)
{
auto *ctx = new NgapUeContext(ueId);
ctx->amfUeNgapId = -1;
Expand All @@ -42,7 +42,7 @@ void NgapTask::createUeContext(int ueId)
m_ueCtx[ctx->ctxId] = ctx;

// Perform AMF selection
auto *amf = selectAmf(ueId);
auto *amf = selectAmf(ueId, requestedSliceType);
if (amf == nullptr)
m_logger->err("AMF selection for UE[%d] failed. Could not find a suitable AMF.", ueId);
else
Expand Down
45 changes: 42 additions & 3 deletions src/gnb/ngap/nas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,52 @@
#include <asn/ngap/ASN_NGAP_ProtocolIE-Field.h>
#include <asn/ngap/ASN_NGAP_RerouteNASRequest.h>
#include <asn/ngap/ASN_NGAP_UplinkNASTransport.h>
#include <ue/nas/enc.hpp>
#include "encode.hpp"
#include <stdexcept>

namespace nr::gnb
{

void NgapTask::handleInitialNasTransport(int ueId, const OctetString &nasPdu, int64_t rrcEstablishmentCause,
const std::optional<GutiMobileIdentity> &sTmsi)
int32_t extractSliceInfoAndModifyPdu(OctetString &nasPdu) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why the modification is needed for the original PDU

Copy link

@prateekbhaisora prateekbhaisora Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sure. In the current implementation, the UE is removing the information elements (including slice information), before sending the NAS PDU to gNB [ RemoveCleartextIEs() ]. gNB then selects one AMF blindly and forwards the request to the selected AMF.

Now, to support intelligent AMF selection based on slice type, I have prevented removal of slice info from the PDU, when the UE sends it. Now, at the gNB end, the gNB uses this slice info., to select an appropriate AMF. Before forwarding the PDU to AMF, I had to remove the slice information from the PDU at gNB, else it leads to a "Unsupported Message Type received" error on AMF end.

nas::RegistrationRequest *regRequest = nullptr;
int32_t requestedSliceType = -1;
auto m_data = nasPdu.getData();
OctetView octetView(m_data.data(), m_data.size());
auto nasMessage = nas::DecodeNasMessage(octetView);
if (nasMessage->epd == nas::EExtendedProtocolDiscriminator::MOBILITY_MANAGEMENT_MESSAGES)
{
nas::MmMessage *mmMessage = dynamic_cast<nas::MmMessage *>(nasMessage.get());
if (mmMessage)
{
nas::PlainMmMessage *plainMmMessage = dynamic_cast<nas::PlainMmMessage *>(mmMessage);
if (plainMmMessage)
{
regRequest = dynamic_cast<nas::RegistrationRequest *>(plainMmMessage);
if (regRequest)
{
auto sz = regRequest->requestedNSSAI->sNssais.size();
if (sz > 0) {
requestedSliceType = static_cast<int32_t>(regRequest->requestedNSSAI->sNssais[0].sst.getValue());
}
}
}
}
}
if (regRequest && regRequest->requestedNSSAI)
regRequest->requestedNSSAI = std::nullopt;

OctetString modifiedNasPdu;
nas::EncodeNasMessage(*nasMessage, modifiedNasPdu);
nasPdu = std::move(modifiedNasPdu);
return requestedSliceType;
}

void NgapTask::handleInitialNasTransport(int ueId, OctetString &nasPdu, int64_t rrcEstablishmentCause,
const std::optional<GutiMobileIdentity> &sTmsi)
{
int32_t requestedSliceType = extractSliceInfoAndModifyPdu(nasPdu);

m_logger->debug("Initial NAS message received from UE[%d]", ueId);

if (m_ueCtx.count(ueId))
Expand All @@ -35,7 +74,7 @@ void NgapTask::handleInitialNasTransport(int ueId, const OctetString &nasPdu, in
return;
}

createUeContext(ueId);
createUeContext(ueId, requestedSliceType);

auto *ueCtx = findUeContext(ueId);
if (ueCtx == nullptr)
Expand Down
15 changes: 11 additions & 4 deletions src/gnb/ngap/nnsf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
namespace nr::gnb
{

NgapAmfContext *NgapTask::selectAmf(int ueId)
NgapAmfContext *NgapTask::selectAmf(int ueId, const int32_t &requestedSliceType)
{
// todo:
for (auto &amf : m_amfCtx)
return amf.second; // return the first one
for (auto &amf : m_amfCtx) {
for (const auto &PlmnSupport : amf.second->plmnSupportList) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use lower-case for SingleSlice and SingleSlice. Because they are loop variables.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Will do that.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename const auto &PlmnSupport to const auto &plmnSupport

and

const auto &SingleSlice to const auto &singleSlice


And please replace const int32_t &requestedSliceType to just int32_t requestedSliceType

for (const auto &SingleSlice : PlmnSupport->sliceSupportList.slices) {
int32_t supportedSliceType = static_cast<int32_t>(SingleSlice.sst.getValue());
if (supportedSliceType == requestedSliceType) {
return amf.second;
}
}
}
}
return nullptr;
}

Expand Down
6 changes: 3 additions & 3 deletions src/gnb/ngap/task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class NgapTask : public NtsTask
/* Utility functions */
void createAmfContext(const GnbAmfConfig &config);
NgapAmfContext *findAmfContext(int ctxId);
void createUeContext(int ueId);
void createUeContext(int ueId, const int32_t &requestedSliceType);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also make just int32_t requestedSliceType

NgapUeContext *findUeContext(int ctxId);
NgapUeContext *findUeByRanId(int64_t ranUeNgapId);
NgapUeContext *findUeByAmfId(int64_t amfUeNgapId);
Expand All @@ -98,7 +98,7 @@ class NgapTask : public NtsTask
bool handleSctpStreamId(int amfId, int stream, const ASN_NGAP_NGAP_PDU &pdu);

/* NAS transport */
void handleInitialNasTransport(int ueId, const OctetString &nasPdu, int64_t rrcEstablishmentCause,
void handleInitialNasTransport(int ueId, OctetString &nasPdu, int64_t rrcEstablishmentCause,
const std::optional<GutiMobileIdentity> &sTmsi);
void handleUplinkNasTransport(int ueId, const OctetString &nasPdu);
void receiveDownlinkNasTransport(int amfId, ASN_NGAP_DownlinkNASTransport *msg);
Expand All @@ -118,7 +118,7 @@ class NgapTask : public NtsTask
void sendContextRelease(int ueId, NgapCause cause);

/* NAS Node Selection */
NgapAmfContext *selectAmf(int ueId);
NgapAmfContext *selectAmf(int ueId, const int32_t &requestedSliceType);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing please

NgapAmfContext *selectNewAmfForReAllocation(int ueId, int initiatedAmfId, int amfSetId);

/* Radio resource control */
Expand Down
1 change: 0 additions & 1 deletion src/ue/nas/mm/messaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ static void RemoveCleartextIEs(nas::PlainMmMessage &msg, OctetString &&nasMsgCon
regReq.micoIndication = std::nullopt;
regReq.networkSlicingIndication = std::nullopt;
regReq.mmCapability = std::nullopt;
regReq.requestedNSSAI = std::nullopt;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain this remove?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to prevent the UE from removing Slice information, before sending the NAS PDU. It is in reference to the comment here.

regReq.requestedDrxParameters = std::nullopt;
regReq.uesUsageSetting = std::nullopt;
regReq.updateType = std::nullopt;
Expand Down
5 changes: 5 additions & 0 deletions src/utils/octet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ struct octet
{
}

inline uint8_t getValue() const
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this function.

You can directly cast to uint8_t in order to convert octet to uint8_t

uint8_t aaa = (uint8_t)bbb;

Copy link

@prateekbhaisora prateekbhaisora Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have used the getValue() getter method here as value is a private variable of struct octet and this appeared to me as the most appropriate way to access the value variable from outside, i.e., in the extractSliceInfoAndModifyPdu method. Please let me know, if there is a more recommended way.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

octet has a special converter for uint8_t. Please directly use this converter, and remove the getValue().

Example:

octet someOctet = ....
uint8_t someUint8 = (uint8_t)someOctet 

{
return value;
}

/* no explicit */ octet(int32_t value) noexcept : value(static_cast<uint8_t>(value & 0xFF))
{
}
Expand Down
5 changes: 5 additions & 0 deletions src/utils/octet_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class OctetString
{
}

const std::vector<uint8_t>& getData() const
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data is already present. Please remove this method.

Copy link

@prateekbhaisora prateekbhaisora Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I used this getter() as m_data was a private member of the Octetstring class and for extractSliceInfoAndModifyPdu(), I needed the data from NAS PDU. Please let me know, if there is a more suitable alternative.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes m_data is private, however we have public data() function. Please use data() function instead.

{
return m_data;
}

explicit OctetString(std::vector<uint8_t> &&data) : m_data(std::move(data))
{
}
Expand Down