Unverified Commit 382e8b4f authored by Alan_Chang's avatar Alan_Chang Committed by GitHub

Merge branch 'aligungr:master' into master

parents c508e5e4 baffde2d
......@@ -24,7 +24,8 @@
namespace nr::gnb
{
void NgapTask::handleInitialNasTransport(int ueId, const OctetString &nasPdu, long rrcEstablishmentCause)
void NgapTask::handleInitialNasTransport(int ueId, const OctetString &nasPdu, long rrcEstablishmentCause,
const std::optional<GutiMobileIdentity> &sTmsi)
{
m_logger->debug("Initial NAS message received from UE[%d]", ueId);
......@@ -54,25 +55,43 @@ void NgapTask::handleInitialNasTransport(int ueId, const OctetString &nasPdu, lo
amfCtx->nextStream += 1;
ueCtx->uplinkStream = amfCtx->nextStream;
std::vector<ASN_NGAP_InitialUEMessage_IEs *> ies;
auto *ieEstablishmentCause = asn::New<ASN_NGAP_InitialUEMessage_IEs>();
ieEstablishmentCause->id = ASN_NGAP_ProtocolIE_ID_id_RRCEstablishmentCause;
ieEstablishmentCause->criticality = ASN_NGAP_Criticality_ignore;
ieEstablishmentCause->value.present = ASN_NGAP_InitialUEMessage_IEs__value_PR_RRCEstablishmentCause;
ieEstablishmentCause->value.choice.RRCEstablishmentCause = rrcEstablishmentCause;
ies.push_back(ieEstablishmentCause);
auto *ieCtxRequest = asn::New<ASN_NGAP_InitialUEMessage_IEs>();
ieCtxRequest->id = ASN_NGAP_ProtocolIE_ID_id_UEContextRequest;
ieCtxRequest->criticality = ASN_NGAP_Criticality_ignore;
ieCtxRequest->value.present = ASN_NGAP_InitialUEMessage_IEs__value_PR_UEContextRequest;
ieCtxRequest->value.choice.UEContextRequest = ASN_NGAP_UEContextRequest_requested;
ies.push_back(ieCtxRequest);
auto *ieNasPdu = asn::New<ASN_NGAP_InitialUEMessage_IEs>();
ieNasPdu->id = ASN_NGAP_ProtocolIE_ID_id_NAS_PDU;
ieNasPdu->criticality = ASN_NGAP_Criticality_reject;
ieNasPdu->value.present = ASN_NGAP_InitialUEMessage_IEs__value_PR_NAS_PDU;
asn::SetOctetString(ieNasPdu->value.choice.NAS_PDU, nasPdu);
ies.push_back(ieNasPdu);
if (sTmsi)
{
auto *ieTmsi = asn::New<ASN_NGAP_InitialUEMessage_IEs>();
ieTmsi->id = ASN_NGAP_ProtocolIE_ID_id_FiveG_S_TMSI;
ieTmsi->criticality = ASN_NGAP_Criticality_reject;
ieTmsi->value.present = ASN_NGAP_InitialUEMessage_IEs__value_PR_FiveG_S_TMSI;
asn::SetBitStringInt<10>(sTmsi->amfSetId, ieTmsi->value.choice.FiveG_S_TMSI.aMFSetID);
asn::SetBitStringInt<6>(sTmsi->amfPointer, ieTmsi->value.choice.FiveG_S_TMSI.aMFPointer);
asn::SetOctetString4(ieTmsi->value.choice.FiveG_S_TMSI.fiveG_TMSI, sTmsi->tmsi);
ies.push_back(ieTmsi);
}
auto *pdu = asn::ngap::NewMessagePdu<ASN_NGAP_InitialUEMessage>({ieEstablishmentCause, ieCtxRequest, ieNasPdu});
auto *pdu = asn::ngap::NewMessagePdu<ASN_NGAP_InitialUEMessage>(ies);
sendNgapUeAssociated(ueId, pdu);
}
......
......@@ -55,7 +55,7 @@ void NgapTask::onLoop()
switch (w->present)
{
case NmGnbRrcToNgap::INITIAL_NAS_DELIVERY: {
handleInitialNasTransport(w->ueId, w->pdu, w->rrcEstablishmentCause);
handleInitialNasTransport(w->ueId, w->pdu, w->rrcEstablishmentCause, w->sTmsi);
break;
}
case NmGnbRrcToNgap::UPLINK_NAS_DELIVERY: {
......
......@@ -98,7 +98,8 @@ 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, long rrcEstablishmentCause);
void handleInitialNasTransport(int ueId, const OctetString &nasPdu, long rrcEstablishmentCause,
const std::optional<GutiMobileIdentity> &sTmsi);
void handleUplinkNasTransport(int ueId, const OctetString &nasPdu);
void receiveDownlinkNasTransport(int amfId, ASN_NGAP_DownlinkNASTransport *msg);
void deliverDownlinkNas(int ueId, OctetString &&nasPdu);
......@@ -108,7 +109,7 @@ class NgapTask : public NtsTask
/* PDU session management */
void receiveSessionResourceSetupRequest(int amfId, ASN_NGAP_PDUSessionResourceSetupRequest *msg);
void receiveSessionResourceReleaseCommand(int amfId, ASN_NGAP_PDUSessionResourceReleaseCommand *msg);
std::optional<NgapCause> setupPduSessionResource(NgapUeContext* ue, PduSessionResource *resource);
std::optional<NgapCause> setupPduSessionResource(NgapUeContext *ue, PduSessionResource *resource);
/* UE context management */
void receiveInitialContextSetup(int amfId, ASN_NGAP_InitialContextSetupRequest *msg);
......
......@@ -204,6 +204,7 @@ struct NmGnbRrcToNgap : NtsMessage
// INITIAL_NAS_DELIVERY
long rrcEstablishmentCause{};
std::optional<GutiMobileIdentity> sTmsi{};
explicit NmGnbRrcToNgap(PR present) : NtsMessage(NtsMessageType::GNB_RRC_TO_NGAP), present(present)
{
......
......@@ -49,28 +49,26 @@ void GnbRrcTask::receiveRrcSetupRequest(int ueId, const ASN_RRC_RRCSetupRequest
return;
}
if (msg.rrcSetupRequest.ue_Identity.present == ASN_RRC_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1)
if (msg.rrcSetupRequest.ue_Identity.present == ASN_RRC_InitialUE_Identity_PR_NOTHING)
{
m_logger->err("RRC Setup Request with TMSI not implemented yet");
m_logger->err("Bad constructed RRC message ignored");
return;
}
if (msg.rrcSetupRequest.ue_Identity.present != ASN_RRC_InitialUE_Identity_PR_randomValue)
ue = createUe(ueId);
if (msg.rrcSetupRequest.ue_Identity.present == ASN_RRC_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1)
{
m_logger->err("Bad constructed RRC message ignored");
return;
ue->initialId = asn::GetBitStringLong<39>(msg.rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1);
ue->isInitialIdSTmsi = true;
}
int64_t initialRandomId = asn::GetBitStringLong<39>(msg.rrcSetupRequest.ue_Identity.choice.randomValue);
if (tryFindByInitialRandomId(initialRandomId) != nullptr)
else
{
m_logger->err("Initial random ID conflict [%ld], discarding RRC Setup Request", initialRandomId);
return;
ue->initialId = asn::GetBitStringLong<39>(msg.rrcSetupRequest.ue_Identity.choice.randomValue);
ue->isInitialIdSTmsi = false;
}
ue = createUe(ueId);
ue->initialRandomId = initialRandomId;
ue->establishmentCause = msg.rrcSetupRequest.establishmentCause;
ue->establishmentCause = static_cast<long>(msg.rrcSetupRequest.establishmentCause);
// Prepare RRC Setup
auto *pdu = asn::New<ASN_RRC_DL_CCCH_Message>();
......@@ -100,10 +98,35 @@ void GnbRrcTask::receiveRrcSetupComplete(int ueId, const ASN_RRC_RRCSetupComplet
auto setupComplete = msg.criticalExtensions.choice.rrcSetupComplete;
if (msg.criticalExtensions.choice.rrcSetupComplete)
{
// Handle received 5G S-TMSI if any
if (msg.criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value)
{
ue->sTmsi = std::nullopt;
auto &sTmsiValue = msg.criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value;
if (sTmsiValue->present == ASN_RRC_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI)
{
ue->sTmsi = GutiMobileIdentity::FromSTmsi(asn::GetBitStringLong<48>(sTmsiValue->choice.ng_5G_S_TMSI));
}
else if (sTmsiValue->present == ASN_RRC_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2)
{
if (ue->isInitialIdSTmsi)
{
int64_t part2 = asn::GetBitStringLong<9>(sTmsiValue->choice.ng_5G_S_TMSI_Part2);
ue->sTmsi = GutiMobileIdentity::FromSTmsi((part2 << 39) | (ue->initialId));
}
}
}
}
auto *w = new NmGnbRrcToNgap(NmGnbRrcToNgap::INITIAL_NAS_DELIVERY);
w->ueId = ueId;
w->pdu = asn::GetOctetString(setupComplete->dedicatedNAS_Message);
w->rrcEstablishmentCause = ue->establishmentCause;
w->sTmsi = ue->sTmsi;
m_base->ngapTask->push(w);
}
......
......@@ -11,17 +11,6 @@
namespace nr::gnb
{
RrcUeContext *GnbRrcTask::tryFindByInitialRandomId(int64_t id)
{
if (id == -1)
return nullptr;
// TODO: Optimize
for (auto &item : m_ueCtx)
if (item.second->initialRandomId == id)
return item.second;
return nullptr;
}
int GnbRrcTask::getNextTid()
{
m_tidCounter++;
......
......@@ -66,7 +66,6 @@ class GnbRrcTask : public NtsTask
private:
/* Management */
RrcUeContext *tryFindByInitialRandomId(int64_t id);
int getNextTid();
/* Handlers */
......
......@@ -145,8 +145,10 @@ struct RrcUeContext
{
const int ueId{};
int64_t initialRandomId = -1;
int64_t initialId = -1; // 39-bit value, or -1
bool isInitialIdSTmsi{}; // TMSI-part-1 or a random value
long establishmentCause{};
std::optional<GutiMobileIdentity> sTmsi{};
explicit RrcUeContext(const int ueId) : ueId(ueId)
{
......
......@@ -41,6 +41,7 @@ static ASN_RRC_UL_CCCH_Message *ConstructSetupRequest(ASN_RRC_InitialUE_Identity
void UeRrcTask::startConnectionEstablishment(OctetString &&nasPdu)
{
/* Check the protocol state */
if (m_state != ERrcState::RRC_IDLE)
{
m_logger->err("RRC establishment could not start, UE not in RRC-IDLE state");
......@@ -48,6 +49,7 @@ void UeRrcTask::startConnectionEstablishment(OctetString &&nasPdu)
return;
}
/* Check the current cell */
int activeCell = m_base->shCtx.currentCell.get<int>([](auto &item) { return item.cellId; });
if (activeCell == 0)
{
......@@ -56,11 +58,28 @@ void UeRrcTask::startConnectionEstablishment(OctetString &&nasPdu)
return;
}
m_initialId.present = ASN_RRC_InitialUE_Identity_PR_randomValue;
asn::SetBitStringLong<39>(Random::Mixed(m_base->config->getNodeName()).nextL(), m_initialId.choice.randomValue);
/* Handle Initial UE Identity (S-TMSI or 39-bit random value) */
std::optional<GutiMobileIdentity> gutiOrTmsi = m_base->shCtx.providedGuti.get();
if (!gutiOrTmsi)
gutiOrTmsi = m_base->shCtx.providedTmsi.get();
if (gutiOrTmsi)
{
m_initialId.present = ASN_RRC_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1;
asn::SetBitStringLong<39>(static_cast<int64_t>(gutiOrTmsi->tmsi) |
(static_cast<int64_t>((gutiOrTmsi->amfPointer & 0b1111111)) << 39ull),
m_initialId.choice.ng_5G_S_TMSI_Part1);
}
else
{
m_initialId.present = ASN_RRC_InitialUE_Identity_PR_randomValue;
asn::SetBitStringLong<39>(Random::Mixed(m_base->config->getNodeName()).nextL(), m_initialId.choice.randomValue);
}
/* Set the Initial NAS PDU */
m_initialNasPdu = std::move(nasPdu);
/* Send the message */
m_logger->debug("Sending RRC Setup Request");
auto *rrcSetupRequest =
......@@ -93,6 +112,18 @@ void UeRrcTask::receiveRrcSetup(int cellId, const ASN_RRC_RRCSetup &msg)
ies->selectedPLMN_Identity = 1;
asn::SetOctetString(ies->dedicatedNAS_Message, m_initialNasPdu);
/* Send S-TMSI if available */
std::optional<GutiMobileIdentity> gutiOrTmsi = m_base->shCtx.providedGuti.get();
if (!gutiOrTmsi)
gutiOrTmsi = m_base->shCtx.providedTmsi.get();
if (gutiOrTmsi)
{
auto &sTmsi = setupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value =
asn::New<ASN_RRC_RRCSetupComplete_IEs::ASN_RRC_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value>();
sTmsi->present = ASN_RRC_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI;
asn::SetBitStringLong<48>(gutiOrTmsi->toTmsiValue(), sTmsi->choice.ng_5G_S_TMSI);
}
m_initialNasPdu = {};
sendRrcMessage(pdu);
......
......@@ -178,8 +178,8 @@ struct UeSharedContext
Locked<ActiveCellInfo> currentCell;
Locked<std::vector<Tai>> forbiddenTaiRoaming;
Locked<std::vector<Tai>> forbiddenTaiRps;
Locked<GutiMobileIdentity> providedGuti;
Locked<GutiMobileIdentity> providedTmsi;
Locked<std::optional<GutiMobileIdentity>> providedGuti;
Locked<std::optional<GutiMobileIdentity>> providedTmsi;
Plmn getCurrentPlmn();
Tai getCurrentTai();
......
......@@ -29,6 +29,21 @@ Supi Supi::Parse(const std::string &supi)
throw std::runtime_error("invalid SUPI value");
}
int64_t GutiMobileIdentity::toTmsiValue() const
{
return (static_cast<int64_t>(this->tmsi)) | (static_cast<int64_t>(this->amfPointer) << 32LL) |
(static_cast<int64_t>(this->amfSetId) << 38LL);
}
GutiMobileIdentity GutiMobileIdentity::FromSTmsi(int64_t sTmsi)
{
GutiMobileIdentity res;
res.tmsi = octet4{static_cast<uint32_t>(sTmsi & 0xFFFFFFLL)};
res.amfPointer = static_cast<int>(((sTmsi >> 32LL) & 0b111111LL));
res.amfSetId = static_cast<int>(((sTmsi >> 38LL) & 0b1111111111LL));
return res;
}
Json ToJson(const Supi &v)
{
return v.type + "-" + v.value;
......
......@@ -90,6 +90,10 @@ struct GutiMobileIdentity
: plmn(plmn), amfRegionId(amfRegionId), amfSetId(amfSetId), amfPointer(amfPointer), tmsi(tmsi)
{
}
[[nodiscard]] int64_t toTmsiValue() const;
static GutiMobileIdentity FromSTmsi(int64_t sTmsi);
};
struct ImsiMobileIdentity
......
......@@ -177,6 +177,16 @@ struct octet4
return value;
}
inline explicit constexpr operator int64_t() const
{
return static_cast<int64_t>(value);
}
inline explicit constexpr operator uint64_t() const
{
return static_cast<int64_t>(value);
}
inline bool operator==(const octet4 &other) const
{
return value == other.value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment