Commit 88666ef9 authored by aligungr's avatar aligungr

SRA dev.

parent 7b7a22bc
......@@ -10,9 +10,9 @@
#include <gnb/app/task.hpp>
#include <gnb/gtp/task.hpp>
#include <gnb/mr/task.hpp>
#include <gnb/ngap/task.hpp>
#include <gnb/rrc/task.hpp>
#include <gnb/sra/task.hpp>
#include <gnb/sctp/task.hpp>
#include <utils/common.hpp>
#include <utils/printer.hpp>
......@@ -36,7 +36,7 @@ void GnbCmdHandler::sendError(const InetAddress &address, const std::string &out
void GnbCmdHandler::pauseTasks()
{
m_base->gtpTask->requestPause();
m_base->mrTask->requestPause();
m_base->sraTask->requestPause();
m_base->ngapTask->requestPause();
m_base->rrcTask->requestPause();
m_base->sctpTask->requestPause();
......@@ -45,7 +45,7 @@ void GnbCmdHandler::pauseTasks()
void GnbCmdHandler::unpauseTasks()
{
m_base->gtpTask->requestUnpause();
m_base->mrTask->requestUnpause();
m_base->sraTask->requestUnpause();
m_base->ngapTask->requestUnpause();
m_base->rrcTask->requestUnpause();
m_base->sctpTask->requestUnpause();
......@@ -55,7 +55,7 @@ bool GnbCmdHandler::isAllPaused()
{
if (!m_base->gtpTask->isPauseConfirmed())
return false;
if (!m_base->mrTask->isPauseConfirmed())
if (!m_base->sraTask->isPauseConfirmed())
return false;
if (!m_base->ngapTask->isPauseConfirmed())
return false;
......@@ -131,7 +131,6 @@ void GnbCmdHandler::handleCmdImpl(NwGnbCliCommand &msg)
for (auto &ue : m_base->ngapTask->m_ueCtx)
{
json.push(Json::Obj({
{"ue-name", m_base->mrTask->m_ueMap[ue.first].name},
{"ran-ngap-id", ue.second->ranUeNgapId},
{"amf-ngap-id", ue.second->amfUeNgapId},
}));
......
......@@ -9,14 +9,13 @@
#include "gnb.hpp"
#include "app/task.hpp"
#include "gtp/task.hpp"
#include "mr/task.hpp"
#include "sra/task.hpp"
#include "ngap/task.hpp"
#include "rrc/task.hpp"
#include "sra/task.hpp"
#include "sctp/task.hpp"
#include <app/cli_base.hpp>
#include <utils/common.hpp>
namespace nr::gnb
{
......@@ -34,7 +33,6 @@ GNodeB::GNodeB(GnbConfig *config, app::INodeListener *nodeListener, NtsTask *cli
base->ngapTask = new NgapTask(base);
base->rrcTask = new GnbRrcTask(base);
base->gtpTask = new GtpTask(base);
base->mrTask = new GnbMrTask(base);
base->sraTask = new GnbSraTask(base);
taskBase = base;
......@@ -47,7 +45,6 @@ GNodeB::~GNodeB()
taskBase->ngapTask->quit();
taskBase->rrcTask->quit();
taskBase->gtpTask->quit();
taskBase->mrTask->quit();
taskBase->sraTask->quit();
delete taskBase->appTask;
......@@ -55,7 +52,6 @@ GNodeB::~GNodeB()
delete taskBase->ngapTask;
delete taskBase->rrcTask;
delete taskBase->gtpTask;
delete taskBase->mrTask;
delete taskBase->sraTask;
delete taskBase->logBase;
......@@ -70,7 +66,6 @@ void GNodeB::start()
taskBase->ngapTask->start();
taskBase->rrcTask->start();
taskBase->sraTask->start();
taskBase->mrTask->start();
taskBase->gtpTask->start();
}
......
......@@ -10,7 +10,6 @@
#include <asn/ngap/ASN_NGAP_QosFlowSetupRequestItem.h>
#include <gnb/gtp/proto.hpp>
#include <gnb/mr/task.hpp>
#include <utils/constants.hpp>
#include <utils/libc_error.hpp>
......@@ -76,17 +75,17 @@ void GtpTask::onLoop()
}
break;
}
case NtsMessageType::GNB_MR_TO_GTP: {
auto *w = dynamic_cast<NwGnbMrToGtp *>(msg);
switch (w->present)
{
case NwGnbMrToGtp::UPLINK_DELIVERY: {
handleUplinkData(w->ueId, w->pduSessionId, std::move(w->data));
break;
}
}
break;
}
//case NtsMessageType::GNB_MR_TO_GTP: {
// auto *w = dynamic_cast<NwGnbMrToGtp *>(msg);
// switch (w->present)
// {
// case NwGnbMrToGtp::UPLINK_DELIVERY: {
// handleUplinkData(w->ueId, w->pduSessionId, std::move(w->data));
// break;
// }
// }
// break;
//}
case NtsMessageType::UDP_SERVER_RECEIVE:
handleUdpReceive(*dynamic_cast<udp::NwUdpServerReceive *>(msg));
break;
......@@ -239,11 +238,11 @@ void GtpTask::handleUdpReceive(const udp::NwUdpServerReceive &msg)
if (m_rateLimiter->allowDownlinkPacket(sessionInd, gtp->payload.length()))
{
auto *w = new NwGnbGtpToMr(NwGnbGtpToMr::DATA_PDU_DELIVERY);
w->ueId = GetUeId(sessionInd);
w->pduSessionId = GetPsi(sessionInd);
w->data = std::move(gtp->payload);
m_base->mrTask->push(w);
//auto *w = new NwGnbGtpToMr(NwGnbGtpToMr::DATA_PDU_DELIVERY);
//w->ueId = GetUeId(sessionInd);
//w->pduSessionId = GetPsi(sessionInd);
//w->data = std::move(gtp->payload);
//m_base->mrTask->push(w);
}
delete gtp;
......
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "rls.hpp"
#include <gnb/nts.hpp>
namespace nr::gnb
{
GnbRls::GnbRls(std::string nodeName, std::unique_ptr<Logger> logger, NtsTask *targetTask)
: RlsGnbEntity(std::move(nodeName)), m_logger(std::move(logger)), m_targetTask(targetTask)
{
}
void GnbRls::logWarn(const std::string &msg)
{
m_logger->warn(msg);
}
void GnbRls::logError(const std::string &msg)
{
m_logger->err(msg);
}
void GnbRls::onUeConnected(int ue, std::string name)
{
auto *w = new NwGnbMrToMr(NwGnbMrToMr::UE_CONNECTED);
w->ue = ue;
w->name = std::move(name);
m_targetTask->push(w);
}
void GnbRls::onUeReleased(int ue, rls::ECause cause)
{
auto *w = new NwGnbMrToMr(NwGnbMrToMr::UE_RELEASED);
w->ue = ue;
w->cause = cause;
m_targetTask->push(w);
}
void GnbRls::deliverUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload)
{
auto *w = new NwGnbMrToMr(NwGnbMrToMr::RECEIVE_OVER_UDP);
w->ue = ue;
w->type = type;
w->pdu = std::move(payload);
m_targetTask->push(w);
}
void GnbRls::sendRlsPdu(const InetAddress &address, OctetString &&pdu)
{
auto *w = new NwGnbMrToMr(NwGnbMrToMr::SEND_OVER_UDP);
w->address = address;
w->pdu = std::move(pdu);
m_targetTask->push(w);
}
} // namespace nr::gnb
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include <urs/rls/gnb_entity.hpp>
#include <utils/logger.hpp>
#include <utils/nts.hpp>
namespace nr::gnb
{
class GnbRls : public rls::RlsGnbEntity
{
private:
std::unique_ptr<Logger> m_logger;
NtsTask *m_targetTask;
public:
explicit GnbRls(std::string nodeName, std::unique_ptr<Logger> logger, NtsTask *targetTask);
protected:
void logWarn(const std::string &msg) override;
void logError(const std::string &msg) override;
void onUeConnected(int ue, std::string name) override;
void onUeReleased(int ue, rls::ECause cause) override;
void sendRlsPdu(const InetAddress &address, OctetString &&pdu) override;
void deliverUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload) override;
};
} // namespace nr::gnb
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "task.hpp"
#include "rls.hpp"
#include <gnb/gtp/task.hpp>
#include <gnb/nts.hpp>
#include <gnb/rrc/task.hpp>
#include <utils/constants.hpp>
#include <utils/libc_error.hpp>
static const int TIMER_ID_RLS_HEARTBEAT = 1;
namespace nr::gnb
{
GnbMrTask::GnbMrTask(TaskBase *base) : m_base{base}, m_udpTask{}, m_rlsEntity{}, m_ueMap{}
{
m_logger = m_base->logBase->makeUniqueLogger("mr");
}
void GnbMrTask::onStart()
{
m_rlsEntity = new GnbRls(m_base->config->name, m_base->logBase->makeUniqueLogger("rls"), this);
try
{
m_udpTask = new udp::UdpServerTask(m_base->config->portalIp, cons::PortalPort, this);
m_udpTask->start();
}
catch (const LibError &e)
{
m_logger->err("MR failure [%s]", e.what());
quit();
return;
}
setTimer(TIMER_ID_RLS_HEARTBEAT, rls::Constants::HB_PERIOD_UE_TO_GNB);
}
void GnbMrTask::onLoop()
{
NtsMessage *msg = take();
if (!msg)
return;
switch (msg->msgType)
{
case NtsMessageType::GNB_MR_TO_MR: {
auto *w = dynamic_cast<NwGnbMrToMr *>(msg);
switch (w->present)
{
case NwGnbMrToMr::UE_CONNECTED: {
onUeConnected(w->ue, w->name);
break;
}
case NwGnbMrToMr::UE_RELEASED: {
onUeReleased(w->ue, w->cause);
break;
}
case NwGnbMrToMr::SEND_OVER_UDP: {
m_udpTask->send(w->address, w->pdu);
break;
}
case NwGnbMrToMr::RECEIVE_OVER_UDP: {
receiveUplinkPayload(w->ue, w->type, std::move(w->pdu));
break;
}
}
break;
}
case NtsMessageType::GNB_GTP_TO_MR: {
auto *w = dynamic_cast<NwGnbGtpToMr *>(msg);
switch (w->present)
{
case NwGnbGtpToMr::DATA_PDU_DELIVERY: {
OctetString stream{};
stream.appendOctet4(static_cast<int>(w->pduSessionId));
stream.append(w->data);
m_rlsEntity->downlinkPayloadDelivery(w->ueId, rls::EPayloadType::DATA, std::move(stream));
break;
}
}
break;
}
case NtsMessageType::GNB_RRC_TO_MR: {
auto *w = dynamic_cast<NwGnbRrcToMr *>(msg);
switch (w->present)
{
case NwGnbRrcToMr::RRC_PDU_DELIVERY: {
OctetString stream{};
stream.appendOctet(static_cast<int>(w->channel));
stream.append(w->pdu);
m_rlsEntity->downlinkPayloadDelivery(w->ueId, rls::EPayloadType::RRC, std::move(stream));
break;
}
case NwGnbRrcToMr::NGAP_LAYER_INITIALIZED: {
m_rlsEntity->setAcceptConnections(true);
break;
}
case NwGnbRrcToMr::AN_RELEASE: {
m_rlsEntity->localReleaseConnection(w->ueId, rls::ECause::RRC_NORMAL_RELEASE);
break;
}
}
break;
}
case NtsMessageType::TIMER_EXPIRED: {
auto *w = dynamic_cast<NwTimerExpired *>(msg);
if (w->timerId == TIMER_ID_RLS_HEARTBEAT)
{
setTimer(TIMER_ID_RLS_HEARTBEAT, rls::Constants::HB_PERIOD_GNB_TO_UE);
m_rlsEntity->onHeartbeat();
}
break;
}
case NtsMessageType::UDP_SERVER_RECEIVE: {
auto *w = dynamic_cast<udp::NwUdpServerReceive *>(msg);
m_rlsEntity->onReceive(w->fromAddress, w->packet);
break;
}
default:
m_logger->unhandledNts(msg);
break;
}
delete msg;
}
void GnbMrTask::onQuit()
{
delete m_rlsEntity;
if (m_udpTask != nullptr)
m_udpTask->quit();
delete m_udpTask;
}
void GnbMrTask::onUeConnected(int ue, const std::string &name)
{
m_ueMap[ue] = {};
m_ueMap[ue].ueId = ue;
m_ueMap[ue].name = name;
m_logger->info("New UE connected to gNB. Total number of UEs [%d]", m_ueMap.size());
}
void GnbMrTask::onUeReleased(int ue, rls::ECause cause)
{
if (rls::IsRlf(cause))
{
m_logger->err("Radio link failure for UE[%d] with cause[%s]", ue, rls::CauseToString(cause));
auto *w = new NwGnbMrToRrc(NwGnbMrToRrc::RADIO_LINK_FAILURE);
w->ueId = ue;
m_base->rrcTask->push(w);
}
m_ueMap.erase(ue);
m_logger->info("A UE disconnected from gNB. Total number of UEs [%d]", m_ueMap.size());
}
void GnbMrTask::receiveUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload)
{
if (type == rls::EPayloadType::RRC)
{
//auto *nw = new NwGnbMrToRrc(NwGnbMrToRrc::RRC_PDU_DELIVERY);
//nw->ueId = ue;
//nw->channel = static_cast<rrc::RrcChannel>(payload.getI(0));
//nw->pdu = payload.subCopy(1);
//m_base->rrcTask->push(nw);
}
else if (type == rls::EPayloadType::DATA)
{
int psi = payload.get4I(0);
OctetString dataPayload = payload.subCopy(4);
auto *w = new NwGnbMrToGtp(NwGnbMrToGtp::UPLINK_DELIVERY);
w->ueId = ue;
w->pduSessionId = psi;
w->data = std::move(dataPayload);
m_base->gtpTask->push(w);
}
}
} // namespace nr::gnb
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include "rls.hpp"
#include <gnb/nts.hpp>
#include <gnb/types.hpp>
#include <memory>
#include <thread>
#include <udp/server_task.hpp>
#include <unordered_map>
#include <urs/rls/gnb_entity.hpp>
#include <utils/logger.hpp>
#include <utils/nts.hpp>
#include <vector>
namespace nr::gnb
{
class GnbMrTask : public NtsTask
{
private:
TaskBase *m_base;
std::unique_ptr<Logger> m_logger;
udp::UdpServerTask *m_udpTask;
GnbRls *m_rlsEntity;
std::unordered_map<int, MrUeContext> m_ueMap;
friend class GnbCmdHandler;
public:
explicit GnbMrTask(TaskBase *base);
~GnbMrTask() override = default;
protected:
void onStart() override;
void onLoop() override;
void onQuit() override;
private:
void onUeConnected(int ue, const std::string &name);
void onUeReleased(int ue, rls::ECause cause);
void receiveUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload);
};
} // namespace nr::gnb
\ No newline at end of file
......@@ -12,7 +12,6 @@
#include <app/cli_cmd.hpp>
#include <rrc/rrc.hpp>
#include <sctp/sctp.hpp>
#include <urs/rls/rls.hpp>
#include <utility>
#include <utils/network.hpp>
#include <utils/nts.hpp>
......@@ -24,21 +23,6 @@
namespace nr::gnb
{
struct NwGnbMrToRrc : NtsMessage
{
enum PR
{
RADIO_LINK_FAILURE,
} present;
// RADIO_LINK_FAILURE
int ueId{};
explicit NwGnbMrToRrc(PR present) : NtsMessage(NtsMessageType::GNB_MR_TO_RRC), present(present)
{
}
};
struct NwGnbSraToRrc : NtsMessage
{
enum PR
......@@ -58,28 +42,6 @@ struct NwGnbSraToRrc : NtsMessage
}
};
struct NwGnbRrcToMr : NtsMessage
{
enum PR
{
NGAP_LAYER_INITIALIZED,
RRC_PDU_DELIVERY,
AN_RELEASE,
} present;
// RRC_PDU_DELIVERY
// AN_RELEASE
int ueId{};
// RRC_PDU_DELIVERY
rrc::RrcChannel channel{};
OctetString pdu{};
explicit NwGnbRrcToMr(PR present) : NtsMessage(NtsMessageType::GNB_RRC_TO_MR), present(present)
{
}
};
struct NwGnbRrcToSra : NtsMessage
{
enum PR
......@@ -172,73 +134,6 @@ struct NwGnbNgapToGtp : NtsMessage
}
};
struct NwGnbMrToGtp : NtsMessage
{
enum PR
{
UPLINK_DELIVERY,
} present;
// UPLINK_DELIVERY
int ueId{};
int pduSessionId{};
OctetString data{};
explicit NwGnbMrToGtp(PR present) : NtsMessage(NtsMessageType::GNB_MR_TO_GTP), present(present)
{
}
};
struct NwGnbGtpToMr : NtsMessage
{
enum PR
{
DATA_PDU_DELIVERY,
} present;
// DATA_PDU_DELIVERY
int ueId{};
int pduSessionId{};
OctetString data{};
explicit NwGnbGtpToMr(PR present) : NtsMessage(NtsMessageType::GNB_GTP_TO_MR), present(present)
{
}
};
struct NwGnbMrToMr : NtsMessage
{
enum PR
{
UE_CONNECTED,
UE_RELEASED,
SEND_OVER_UDP,
RECEIVE_OVER_UDP,
} present;
// UE_CONNECTED
// UE_RELEASED
// RECEIVE_OVER_UDP
int ue{};
// UE_CONNECTED
std::string name{};
// UE_RELEASED
rls::ECause cause{};
// SEND_OVER_RLS
InetAddress address{};
OctetString pdu{};
// RECEIVE_OVER_UDP
rls::EPayloadType type{};
explicit NwGnbMrToMr(PR present) : NtsMessage(NtsMessageType::GNB_MR_TO_MR), present(present)
{
}
};
struct NwGnbSctp : NtsMessage
{
enum PR
......
......@@ -8,7 +8,6 @@
#include "task.hpp"
#include <gnb/mr/task.hpp>
#include <gnb/ngap/task.hpp>
#include <rrc/encode.hpp>
......@@ -155,11 +154,6 @@ void GnbRrcTask::releaseConnection(int ueId)
sendRrcMessage(ueId, pdu);
// Notify MR task
auto *w = new NwGnbRrcToMr(NwGnbRrcToMr::AN_RELEASE);
w->ueId = ueId;
m_base->mrTask->push(w);
// Delete UE RRC context
m_ueCtx.erase(ueId);
}
......
......@@ -9,7 +9,6 @@
#include "task.hpp"
#include <asn/rrc/ASN_RRC_DLInformationTransfer-IEs.h>
#include <asn/rrc/ASN_RRC_DLInformationTransfer.h>
#include <gnb/mr/task.hpp>
#include <gnb/nts.hpp>
#include <rrc/encode.hpp>
......@@ -38,17 +37,17 @@ void GnbRrcTask::onLoop()
switch (msg->msgType)
{
case NtsMessageType::GNB_MR_TO_RRC: {
auto *w = dynamic_cast<NwGnbMrToRrc *>(msg);
switch (w->present)
{
case NwGnbMrToRrc::RADIO_LINK_FAILURE: {
handleRadioLinkFailure(w->ueId);
break;
}
}
break;
}
//case NtsMessageType::GNB_MR_TO_RRC: {
// auto *w = dynamic_cast<NwGnbMrToRrc *>(msg);
// switch (w->present)
// {
// case NwGnbMrToRrc::RADIO_LINK_FAILURE: {
// handleRadioLinkFailure(w->ueId);
// break;
// }
// }
// break;
//}
case NtsMessageType::GNB_SRA_TO_RRC: {
auto *w = dynamic_cast<NwGnbSraToRrc *>(msg);
switch (w->present)
......@@ -65,7 +64,7 @@ void GnbRrcTask::onLoop()
switch (w->present)
{
case NwGnbNgapToRrc::NGAP_LAYER_INITIALIZED: {
m_base->mrTask->push(new NwGnbRrcToMr(NwGnbRrcToMr::NGAP_LAYER_INITIALIZED));
//m_base->mrTask->push(new NwGnbRrcToMr(NwGnbRrcToMr::NGAP_LAYER_INITIALIZED));
break;
}
case NwGnbNgapToRrc::NAS_DELIVERY: {
......
......@@ -14,7 +14,6 @@
#include <thread>
#include <udp/server_task.hpp>
#include <unordered_map>
#include <urs/rls/gnb_entity.hpp>
#include <urs/sra_pdu.hpp>
#include <utils/logger.hpp>
#include <utils/nts.hpp>
......
......@@ -24,7 +24,6 @@ namespace nr::gnb
class GnbAppTask;
class GtpTask;
class GnbMrTask;
class NgapTask;
class GnbRrcTask;
class GnbSraTask;
......@@ -335,7 +334,6 @@ struct TaskBase
GnbAppTask *appTask{};
GtpTask *gtpTask{};
GnbMrTask *mrTask{};
NgapTask *ngapTask{};
GnbRrcTask *rrcTask{};
SctpTask *sctpTask{};
......
......@@ -9,7 +9,6 @@
#include "cmd_handler.hpp"
#include <ue/app/task.hpp>
#include <ue/mr/task.hpp>
#include <ue/nas/task.hpp>
#include <ue/rrc/task.hpp>
#include <ue/sra/task.hpp>
......@@ -46,26 +45,26 @@ void UeCmdHandler::sendError(const InetAddress &address, const std::string &outp
void UeCmdHandler::pauseTasks()
{
m_base->mrTask->requestPause();
m_base->nasTask->requestPause();
m_base->rrcTask->requestPause();
m_base->sraTask->requestPause();
}
void UeCmdHandler::unpauseTasks()
{
m_base->mrTask->requestUnpause();
m_base->nasTask->requestUnpause();
m_base->rrcTask->requestUnpause();
m_base->sraTask->requestUnpause();
}
bool UeCmdHandler::isAllPaused()
{
if (!m_base->mrTask->isPauseConfirmed())
return false;
if (!m_base->nasTask->isPauseConfirmed())
return false;
if (!m_base->rrcTask->isPauseConfirmed())
return false;
if (!m_base->sraTask->isPauseConfirmed())
return false;
return true;
}
......
......@@ -9,7 +9,6 @@
#include "task.hpp"
#include "cmd_handler.hpp"
#include <nas/utils.hpp>
#include <ue/mr/task.hpp>
#include <ue/tun/tun.hpp>
#include <utils/common.hpp>
#include <utils/constants.hpp>
......@@ -50,33 +49,33 @@ void UeAppTask::onLoop()
switch (msg->msgType)
{
case NtsMessageType::UE_MR_TO_APP: {
auto *w = dynamic_cast<NwUeMrToApp *>(msg);
switch (w->present)
{
case NwUeMrToApp::DATA_PDU_DELIVERY: {
auto *tunTask = m_tunTasks[w->psi];
if (tunTask)
{
auto *nw = new NwAppToTun(NwAppToTun::DATA_PDU_DELIVERY);
nw->psi = w->psi;
nw->data = std::move(w->data);
tunTask->push(nw);
}
break;
}
}
break;
}
//case NtsMessageType::UE_MR_TO_APP: {
// auto *w = dynamic_cast<NwUeMrToApp *>(msg);
// switch (w->present)
// {
// case NwUeMrToApp::DATA_PDU_DELIVERY: {
// auto *tunTask = m_tunTasks[w->psi];
// if (tunTask)
// {
// auto *nw = new NwAppToTun(NwAppToTun::DATA_PDU_DELIVERY);
// nw->psi = w->psi;
// nw->data = std::move(w->data);
// tunTask->push(nw);
// }
// break;
// }
// }
// break;
//}
case NtsMessageType::UE_TUN_TO_APP: {
auto *w = dynamic_cast<NwUeTunToApp *>(msg);
switch (w->present)
{
case NwUeTunToApp::DATA_PDU_DELIVERY: {
auto *nw = new NwAppToMr(NwAppToMr::DATA_PDU_DELIVERY);
nw->psi = w->psi;
nw->data = std::move(w->data);
m_base->mrTask->push(nw);
//auto *nw = new NwAppToMr(NwAppToMr::DATA_PDU_DELIVERY);
//nw->psi = w->psi;
//nw->data = std::move(w->data);
//m_base->mrTask->push(nw);
break;
}
case NwUeTunToApp::TUN_ERROR: {
......
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "rls.hpp"
#include <ue/nts.hpp>
#include <urs/rls/ue_entity.hpp>
namespace nr::ue
{
UeRls::UeRls(const std::string &nodeName, const std::vector<InetAddress> &gnbSearchList, std::unique_ptr<Logger> logger,
NtsTask *targetTask)
: RlsUeEntity(nodeName, gnbSearchList), m_logger(std::move(logger)), m_targetTask(targetTask)
{
}
void UeRls::logWarn(const std::string &msg)
{
m_logger->warn(msg);
}
void UeRls::logError(const std::string &msg)
{
m_logger->err(msg);
}
void UeRls::startWaitingTimer(int period)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_START_WAITING_TIMER);
w->period = period;
m_targetTask->push(w);
}
void UeRls::searchFailure(rls::ECause cause)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_SEARCH_FAILURE);
w->cause = cause;
m_targetTask->push(w);
}
void UeRls::onRelease(rls::ECause cause)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_RELEASED);
w->cause = cause;
m_targetTask->push(w);
}
void UeRls::onConnect(const std::string &gnbName)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_CONNECTED);
w->gnbName = gnbName;
m_targetTask->push(w);
}
void UeRls::sendRlsPdu(const InetAddress &address, OctetString &&pdu)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_SEND_OVER_UDP);
w->address = address;
w->pdu = std::move(pdu);
m_targetTask->push(w);
}
void UeRls::deliverPayload(rls::EPayloadType type, OctetString &&payload)
{
auto *w = new NwUeMrToMr(NwUeMrToMr::RLS_RECEIVE_OVER_UDP);
w->type = type;
w->pdu = std::move(payload);
m_targetTask->push(w);
}
} // namespace nr::ue
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include <nas/nas.hpp>
#include <ue/types.hpp>
#include <urs/rls/ue_entity.hpp>
namespace nr::ue
{
class UeRls : public rls::RlsUeEntity
{
private:
std::unique_ptr<Logger> m_logger;
NtsTask *m_targetTask;
public:
UeRls(const std::string &nodeName, const std::vector<InetAddress> &gnbSearchList, std::unique_ptr<Logger> logger,
NtsTask *targetTask);
protected:
void logWarn(const std::string &msg) override;
void logError(const std::string &msg) override;
void startWaitingTimer(int period) override;
void searchFailure(rls::ECause cause) override;
void onRelease(rls::ECause cause) override;
void onConnect(const std::string &gnbName) override;
void sendRlsPdu(const InetAddress &address, OctetString &&pdu) override;
void deliverPayload(rls::EPayloadType type, OctetString &&payload) override;
};
} // namespace nr::ue
\ No newline at end of file
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "task.hpp"
#include <ue/app/task.hpp>
#include <ue/nts.hpp>
#include <ue/rrc/task.hpp>
#include <utils/common.hpp>
#include <utils/constants.hpp>
static const int TIMER_ID_RLS_WAITING_TIMER = 1;
static const int TIMER_ID_RLS_HEARTBEAT = 2;
namespace nr::ue
{
ue::UeMrTask::UeMrTask(TaskBase *base) : m_base{base}, m_udpTask{}, m_rlsEntity{}
{
m_logger = m_base->logBase->makeUniqueLogger(m_base->config->getLoggerPrefix() + "mr");
}
void UeMrTask::onStart()
{
m_udpTask = new udp::UdpServerTask(this);
std::vector<InetAddress> gnbSearchList{};
for (auto &ip : m_base->config->gnbSearchList)
gnbSearchList.emplace_back(ip, cons::PortalPort);
m_rlsEntity = new UeRls(m_base->config->getNodeName(), gnbSearchList,
m_base->logBase->makeUniqueLogger(m_base->config->getLoggerPrefix() + "rls"), this);
m_udpTask->start();
setTimer(TIMER_ID_RLS_HEARTBEAT, rls::Constants::HB_PERIOD_UE_TO_GNB);
}
void UeMrTask::onQuit()
{
delete m_rlsEntity;
m_udpTask->quit();
delete m_udpTask;
}
void UeMrTask::onLoop()
{
NtsMessage *msg = take();
if (!msg)
return;
switch (msg->msgType)
{
case NtsMessageType::UE_MR_TO_MR: {
auto *w = dynamic_cast<NwUeMrToMr *>(msg);
switch (w->present)
{
case NwUeMrToMr::RLS_CONNECTED: {
//auto tw = new NwUeMrToRrc(NwUeMrToRrc::PLMN_SEARCH_RESPONSE);
//tw->gnbName = std::move(w->gnbName);
//m_base->rrcTask->push(tw);
break;
}
case NwUeMrToMr::RLS_RELEASED: {
if (rls::IsRlf(w->cause))
{
m_logger->err("Radio link failure with cause[%s]", rls::CauseToString(w->cause));
m_base->rrcTask->push(new NwUeMrToRrc(NwUeMrToRrc::RADIO_LINK_FAILURE));
}
else
{
m_logger->debug("UE disconnected from gNB [%s]", rls::CauseToString(w->cause));
}
break;
}
case NwUeMrToMr::RLS_SEARCH_FAILURE: {
//long current = utils::CurrentTimeMillis();
//if (current - m_lastPlmnSearchFailurePrinted > PLMN_SEARCH_FAILED_PRINT_THRESHOLD)
//{
// m_logger->err("PLMN search failed [%s]", rls::CauseToString(w->cause));
// m_lastPlmnSearchFailurePrinted = current;
// m_base->rrcTask->push(new NwUeMrToRrc(NwUeMrToRrc::PLMN_SEARCH_FAILURE));
//}
break;
}
case NwUeMrToMr::RLS_START_WAITING_TIMER: {
setTimer(TIMER_ID_RLS_WAITING_TIMER, w->period);
break;
}
case NwUeMrToMr::RLS_SEND_OVER_UDP: {
m_udpTask->send(w->address, w->pdu);
break;
}
case NwUeMrToMr::RLS_RECEIVE_OVER_UDP: {
receiveDownlinkPayload(w->type, std::move(w->pdu));
break;
}
}
break;
}
case NtsMessageType::UE_APP_TO_MR: {
auto *w = dynamic_cast<NwAppToMr *>(msg);
switch (w->present)
{
case NwAppToMr::DATA_PDU_DELIVERY: {
// Append PDU session information
OctetString stream{};
stream.appendOctet4(w->psi);
stream.append(w->data);
m_rlsEntity->onUplinkDelivery(rls::EPayloadType::DATA, std::move(stream));
break;
}
}
break;
}
case NtsMessageType::TIMER_EXPIRED: {
auto *w = dynamic_cast<NwTimerExpired *>(msg);
if (w->timerId == TIMER_ID_RLS_WAITING_TIMER)
{
m_rlsEntity->onWaitingTimerExpire();
}
else if (w->timerId == TIMER_ID_RLS_HEARTBEAT)
{
setTimer(TIMER_ID_RLS_HEARTBEAT, rls::Constants::HB_PERIOD_UE_TO_GNB);
m_rlsEntity->onHeartbeat();
}
break;
}
case NtsMessageType::UDP_SERVER_RECEIVE: {
auto *w = dynamic_cast<udp::NwUdpServerReceive *>(msg);
m_rlsEntity->onReceive(w->fromAddress, w->packet);
break;
}
default:
m_logger->unhandledNts(msg);
break;
}
delete msg;
}
void UeMrTask::receiveDownlinkPayload(rls::EPayloadType type, OctetString &&payload)
{
if (type == rls::EPayloadType::RRC)
{
//auto *nw = new NwUeMrToRrc(NwUeMrToRrc::RRC_PDU_DELIVERY);
//nw->channel = static_cast<rrc::RrcChannel>(payload.getI(0));
//nw->pdu = payload.subCopy(1);
//m_base->rrcTask->push(nw);
}
else if (type == rls::EPayloadType::DATA)
{
auto *nw = new NwUeMrToApp(NwUeMrToApp::DATA_PDU_DELIVERY);
nw->psi = payload.get4I(0);
nw->data = payload.subCopy(4);
m_base->appTask->push(nw);
}
}
} // namespace nr::ue
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include "rls.hpp"
#include <memory>
#include <thread>
#include <udp/server_task.hpp>
#include <ue/types.hpp>
#include <unordered_map>
#include <utils/logger.hpp>
#include <utils/nts.hpp>
#include <vector>
namespace nr::ue
{
class UeMrTask : public NtsTask
{
private:
TaskBase *m_base;
std::unique_ptr<Logger> m_logger;
udp::UdpServerTask *m_udpTask;
UeRls *m_rlsEntity;
friend class UeCmdHandler;
public:
explicit UeMrTask(TaskBase *base);
~UeMrTask() override = default;
protected:
void onStart() override;
void onLoop() override;
void onQuit() override;
private:
void receiveDownlinkPayload(rls::EPayloadType type, OctetString &&payload);
};
} // namespace nr::ue
\ No newline at end of file
......@@ -13,7 +13,6 @@
#include <app/cli_base.hpp>
#include <nas/timer.hpp>
#include <rrc/rrc.hpp>
#include <urs/rls/rls.hpp>
#include <utility>
#include <utils/network.hpp>
#include <utils/nts.hpp>
......@@ -22,87 +21,6 @@
namespace nr::ue
{
struct NwUeMrToMr : NtsMessage
{
enum PR
{
RLS_CONNECTED,
RLS_RELEASED,
RLS_SEARCH_FAILURE,
RLS_START_WAITING_TIMER,
RLS_SEND_OVER_UDP,
RLS_RECEIVE_OVER_UDP
} present;
// RLS_CONNECTED
std::string gnbName{};
// RLS_RELEASED
// RLS_SEARCH_FAILURE
rls::ECause cause{};
// RLS_START_WAITING_TIMER
int period{};
// RLS_SEND_OVER_UDP
InetAddress address{};
// RLS_RECEIVE_OVER_UDP
rls::EPayloadType type{};
// RLS_SEND_OVER_UDP
// RLS_RECEIVE_OVER_UDP
OctetString pdu{};
explicit NwUeMrToMr(PR present) : NtsMessage(NtsMessageType::UE_MR_TO_MR), present(present)
{
}
};
struct NwUeMrToRrc : NtsMessage
{
enum PR
{
RADIO_LINK_FAILURE
} present;
explicit NwUeMrToRrc(PR present) : NtsMessage(NtsMessageType::UE_MR_TO_RRC), present(present)
{
}
};
struct NwUeMrToApp : NtsMessage
{
enum PR
{
DATA_PDU_DELIVERY
} present;
// DATA_PDU_DELIVERY
int psi{};
OctetString data{};
explicit NwUeMrToApp(PR present) : NtsMessage(NtsMessageType::UE_MR_TO_APP), present(present)
{
}
};
struct NwAppToMr : NtsMessage
{
enum PR
{
DATA_PDU_DELIVERY
} present;
// DATA_PDU_DELIVERY
int psi{};
OctetString data{};
explicit NwAppToMr(PR present) : NtsMessage(NtsMessageType::UE_APP_TO_MR), present(present)
{
}
};
struct NwAppToTun : NtsMessage
{
enum PR
......
......@@ -9,7 +9,6 @@
#include "task.hpp"
#include <asn/utils/utils.hpp>
#include <rrc/encode.hpp>
#include <ue/mr/task.hpp>
#include <ue/nas/task.hpp>
#include <ue/nts.hpp>
#include <utils/common.hpp>
......
......@@ -13,7 +13,6 @@
#include <asn/rrc/ASN_RRC_ULInformationTransfer.h>
#include <rrc/encode.hpp>
#include <ue/app/task.hpp>
#include <ue/mr/task.hpp>
#include <ue/nas/task.hpp>
#include <ue/sra/task.hpp>
#include <utils/common.hpp>
......@@ -45,17 +44,17 @@ void UeRrcTask::onLoop()
switch (msg->msgType)
{
case NtsMessageType::UE_MR_TO_RRC: {
auto *w = dynamic_cast<NwUeMrToRrc *>(msg);
switch (w->present)
{
case NwUeMrToRrc::RADIO_LINK_FAILURE: {
handleRadioLinkFailure();
break;
}
}
break;
}
//case NtsMessageType::UE_MR_TO_RRC: {
// auto *w = dynamic_cast<NwUeMrToRrc *>(msg);
// switch (w->present)
// {
// case NwUeMrToRrc::RADIO_LINK_FAILURE: {
// handleRadioLinkFailure();
// break;
// }
// }
// break;
//}
case NtsMessageType::UE_NAS_TO_RRC: {
auto *w = dynamic_cast<NwUeNasToRrc *>(msg);
switch (w->present)
......
......@@ -24,7 +24,6 @@ namespace nr::ue
{
class UeAppTask;
class UeMrTask;
class NasTask;
class UeRrcTask;
class UeSraTask;
......@@ -123,7 +122,6 @@ struct TaskBase
NtsTask *cliCallbackTask{};
UeAppTask *appTask{};
UeMrTask *mrTask{};
NasTask *nasTask{};
UeRrcTask *rrcTask{};
UeSraTask *sraTask{};
......
......@@ -9,7 +9,7 @@
#include "ue.hpp"
#include "app/task.hpp"
#include "mr/task.hpp"
#include "sra/task.hpp"
#include "nas/task.hpp"
#include "rrc/task.hpp"
#include "sra/task.hpp"
......@@ -30,7 +30,6 @@ UserEquipment::UserEquipment(UeConfig *config, app::IUeController *ueController,
base->nasTask = new NasTask(base);
base->rrcTask = new UeRrcTask(base);
base->mrTask = new UeMrTask(base);
base->appTask = new UeAppTask(base);
base->sraTask = new UeSraTask(base);
......@@ -41,13 +40,11 @@ UserEquipment::~UserEquipment()
{
taskBase->nasTask->quit();
taskBase->rrcTask->quit();
taskBase->mrTask->quit();
taskBase->sraTask->quit();
taskBase->appTask->quit();
delete taskBase->nasTask;
delete taskBase->rrcTask;
delete taskBase->mrTask;
delete taskBase->sraTask;
delete taskBase->appTask;
......@@ -60,7 +57,6 @@ void UserEquipment::start()
{
taskBase->nasTask->start();
taskBase->rrcTask->start();
taskBase->mrTask->start();
taskBase->sraTask->start();
taskBase->appTask->start();
}
......
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "gnb_entity.hpp"
#include <utils/common.hpp>
#include <utils/constants.hpp>
static const octet3 AppVersion = octet3{cons::Major, cons::Minor, cons::Patch};
namespace rls
{
RlsGnbEntity::RlsGnbEntity(std::string nodeName)
: nodeName(std::move(nodeName)), token(utils::Random64()), ueIdMap(), idUeMap(), ueAddressMap(), heartbeatMap(),
setupCompleteWaiting(), acceptConnections()
{
}
void RlsGnbEntity::onHeartbeat()
{
uint64_t current = utils::CurrentTimeMillis();
std::vector<int> uesToRemove{};
for (auto &v : heartbeatMap)
{
if (current - v.second > Constants::HB_TIMEOUT_UE_TO_GNB)
uesToRemove.push_back(v.first);
else
sendHeartbeat(v.first);
}
for (int ue : uesToRemove)
removeUe(ue, ECause::HEARTBEAT_TIMEOUT);
}
void RlsGnbEntity::downlinkPayloadDelivery(int ue, EPayloadType type, OctetString &&payload)
{
if (!idUeMap.count(ue))
{
logWarn("UE connection released or not established");
return;
}
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_PAYLOAD_TRANSPORT;
m.appVersion = AppVersion;
m.ueToken = idUeMap[ue];
m.gnbToken = token;
m.payloadType = type;
m.payload = std::move(payload);
sendRlsMessage(ue, m);
}
void RlsGnbEntity::setAcceptConnections(bool accept)
{
acceptConnections = accept;
}
void RlsGnbEntity::releaseConnection(int ue, ECause cause)
{
sendReleaseIndication(ue, cause);
removeUe(ue, cause);
}
void RlsGnbEntity::localReleaseConnection(int ue, ECause cause)
{
removeUe(ue, cause);
}
void RlsGnbEntity::sendRlsMessage(int ue, const RlsMessage &msg)
{
OctetString buf{};
if (!Encode(msg, buf))
{
logError("PDU encoding failed");
return;
}
sendRlsPdu(ueAddressMap[ue], std::move(buf));
}
void RlsGnbEntity::sendHeartbeat(int ue)
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_HEARTBEAT;
m.appVersion = AppVersion;
m.ueToken = idUeMap[ue];
m.gnbToken = token;
sendRlsMessage(ue, m);
}
void RlsGnbEntity::sendReleaseIndication(int ue, ECause cause)
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_RELEASE_INDICATION;
m.appVersion = AppVersion;
m.ueToken = idUeMap[ue];
m.gnbToken = token;
m.cause = cause;
sendRlsMessage(ue, m);
}
void RlsGnbEntity::removeUe(int ue, ECause cause)
{
if (idUeMap.count(ue) == 0)
return;
uint64_t ueToken = idUeMap[ue];
ueIdMap.erase(ueToken);
idUeMap.erase(ue);
ueAddressMap.erase(ue);
heartbeatMap.erase(ue);
if (!setupCompleteWaiting.count(ue))
onUeReleased(ue, cause);
setupCompleteWaiting.erase(ue);
}
void RlsGnbEntity::onReceive(const InetAddress &address, const OctetString &pdu)
{
RlsMessage msg{};
auto res = Decode(OctetView{pdu}, msg, AppVersion);
if (res == DecodeRes::FAILURE)
{
logError("PDU decoding failed");
return;
}
if (res == DecodeRes::VERSION_MISMATCH)
{
logError("Version mismatch between UE and gNB");
return;
}
if (msg.msgCls == EMessageClass::ERROR_INDICATION)
{
logError("RLS error indication received | " + std::to_string((int)msg.cause) + " | " + msg.str);
return;
}
if (msg.ueToken == 0)
{
logWarn("UE gNB token received");
return;
}
if (msg.msgType == EMessageType::RLS_SETUP_REQUEST)
{
if (!acceptConnections)
{
// ignore setup request
return;
}
if (ueIdMap.count(msg.ueToken))
{
sendSetupFailure(address, msg.ueToken, ECause::TOKEN_CONFLICT);
return;
}
int ueId = utils::NextId();
ueIdMap[msg.ueToken] = ueId;
idUeMap[ueId] = msg.ueToken;
ueAddressMap[ueId] = address;
heartbeatMap[ueId] = utils::CurrentTimeMillis();
setupCompleteWaiting.insert(ueId);
sendSetupResponse(ueId);
return;
}
if (!ueIdMap.count(msg.ueToken))
{
logWarn("Unknown UE token");
return;
}
int ue = ueIdMap[msg.ueToken];
heartbeatMap[ue] = utils::CurrentTimeMillis();
if (msg.msgType == EMessageType::RLS_SETUP_COMPLETE)
{
setupCompleteWaiting.erase(ue);
onUeConnected(ue, msg.str);
}
else if (msg.msgType == EMessageType::RLS_HEARTBEAT)
{
heartbeatMap[ue] = utils::CurrentTimeMillis();
}
else if (msg.msgType == EMessageType::RLS_RELEASE_INDICATION)
{
removeUe(ue, msg.cause);
}
else if (msg.msgType == EMessageType::RLS_PAYLOAD_TRANSPORT)
{
deliverUplinkPayload(ue, msg.payloadType, std::move(msg.payload));
}
else
{
logWarn("Bad message type received from UE");
}
}
void RlsGnbEntity::sendSetupResponse(int ue)
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_SETUP_RESPONSE;
m.appVersion = AppVersion;
m.ueToken = idUeMap[ue];
m.gnbToken = token;
m.str = nodeName;
sendRlsMessage(ue, m);
}
void RlsGnbEntity::sendSetupFailure(const InetAddress &address, uint64_t ueToken, ECause cause)
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_SETUP_FAILURE;
m.appVersion = AppVersion;
m.ueToken = ueToken;
m.gnbToken = token;
m.cause = cause;
OctetString buf{};
if (!Encode(m, buf))
{
logWarn("PDU encoding failed");
return;
}
sendRlsPdu(address, std::move(buf));
}
} // namespace rls
\ No newline at end of file
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include "rls.hpp"
#include <optional>
#include <set>
#include <unordered_map>
#include <utils/network.hpp>
namespace rls
{
class RlsGnbEntity
{
private:
std::string nodeName;
uint64_t token;
std::unordered_map<uint64_t, int> ueIdMap; // UE token to gNB-internal UE id.
std::unordered_map<int, uint64_t> idUeMap; // gNB-internal UE id to UE token.
std::unordered_map<int, InetAddress> ueAddressMap; // UE token to address
std::unordered_map<int, uint64_t> heartbeatMap; // UE token to last heartbeat time
std::set<int> setupCompleteWaiting;
bool acceptConnections;
public:
explicit RlsGnbEntity(std::string nodeName);
virtual ~RlsGnbEntity() = default;
protected:
virtual void logWarn(const std::string &msg) = 0;
virtual void logError(const std::string &msg) = 0;
virtual void onUeConnected(int ue, std::string name) = 0;
virtual void onUeReleased(int ue, ECause cause) = 0;
virtual void sendRlsPdu(const InetAddress &address, OctetString &&pdu) = 0;
virtual void deliverUplinkPayload(int ue, EPayloadType type, OctetString &&payload) = 0;
public:
void onHeartbeat();
void onReceive(const InetAddress &address, const OctetString &pdu);
void downlinkPayloadDelivery(int ue, EPayloadType type, OctetString &&payload);
void setAcceptConnections(bool accept);
void releaseConnection(int ue, ECause cause);
void localReleaseConnection(int ue, ECause cause);
private:
void sendReleaseIndication(int ue, ECause cause);
void sendHeartbeat(int ue);
void removeUe(int ue, ECause cause);
void sendRlsMessage(int ue, const RlsMessage &msg);
void sendSetupFailure(const InetAddress &address, uint64_t ueToken, ECause cause);
void sendSetupResponse(int ue);
};
} // namespace rls
\ No newline at end of file
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "rls.hpp"
namespace rls
{
DecodeRes Decode(const OctetView &stream, RlsMessage &output, octet3 appVersion)
{
output.msgCls = static_cast<EMessageClass>(stream.readI());
if (output.msgCls == EMessageClass::ERROR_INDICATION)
{
output.cause = static_cast<ECause>(stream.readI());
uint16_t errLen = stream.read2US();
output.str = stream.readUtf8String(errLen);
return DecodeRes::OK;
}
if (output.msgCls == EMessageClass::NORMAL_MESSAGE)
{
output.appVersion = stream.read3();
if ((int)output.appVersion != (int)appVersion)
return DecodeRes::VERSION_MISMATCH;
output.msgType = static_cast<EMessageType>(stream.readI());
if (output.msgType != EMessageType::RLS_SETUP_REQUEST && output.msgType != EMessageType::RLS_SETUP_COMPLETE &&
output.msgType != EMessageType::RLS_SETUP_FAILURE && output.msgType != EMessageType::RLS_HEARTBEAT &&
output.msgType != EMessageType::RLS_RELEASE_INDICATION &&
output.msgType != EMessageType::RLS_PAYLOAD_TRANSPORT && output.msgType != EMessageType::RLS_SETUP_RESPONSE)
return DecodeRes::FAILURE;
output.ueToken = stream.read8UL();
output.gnbToken = stream.read8UL();
output.payloadType = static_cast<EPayloadType>(stream.readI());
uint16_t len = stream.read2US();
output.payload = stream.readOctetString(len);
output.cause = static_cast<ECause>(stream.readI());
len = stream.read2US();
output.str = stream.readUtf8String(len);
return DecodeRes::OK;
}
return DecodeRes::FAILURE;
}
bool Encode(const RlsMessage &msg, OctetString &stream)
{
stream.appendOctet(static_cast<int>(msg.msgCls));
if (msg.msgCls == EMessageClass::ERROR_INDICATION)
{
stream.appendOctet(static_cast<int>(msg.cause));
stream.appendOctet2(msg.str.length());
for (char c : msg.str)
stream.appendOctet(c);
return true;
}
if (msg.msgCls == EMessageClass::NORMAL_MESSAGE)
{
if (msg.msgType != EMessageType::RLS_SETUP_REQUEST && msg.msgType != EMessageType::RLS_SETUP_COMPLETE &&
msg.msgType != EMessageType::RLS_SETUP_FAILURE && msg.msgType != EMessageType::RLS_HEARTBEAT &&
msg.msgType != EMessageType::RLS_RELEASE_INDICATION && msg.msgType != EMessageType::RLS_PAYLOAD_TRANSPORT &&
msg.msgType != EMessageType::RLS_SETUP_RESPONSE)
return false;
stream.appendOctet3(msg.appVersion);
stream.appendOctet(static_cast<int>(msg.msgType));
stream.appendOctet8(msg.ueToken);
stream.appendOctet8(msg.gnbToken);
stream.appendOctet(static_cast<int>(msg.payloadType));
stream.appendOctet2(msg.payload.length());
stream.append(msg.payload);
stream.appendOctet(static_cast<int>(msg.cause));
stream.appendOctet2(msg.str.length());
stream.appendUtf8(msg.str);
return true;
}
return false;
}
const char *CauseToString(ECause cause)
{
switch (cause)
{
case ECause::UNSPECIFIED:
return "RLS-UNSPECIFIED";
case ECause::TOKEN_CONFLICT:
return "RLS-TOKEN-CONFLICT";
case ECause::EMPTY_SEARCH_LIST:
return "RLS-EMPTY-SEARCH-LIST";
case ECause::SETUP_TIMEOUT:
return "RLS-SETUP-TIMEOUT";
case ECause::HEARTBEAT_TIMEOUT:
return "RLS-HEARTBEAT-TIMEOUT";
case ECause::RRC_NORMAL_RELEASE:
return "RLS-RRC-NORMAL-RELEASE";
case ECause::RRC_LOCAL_RELEASE:
return "RLS-RRC-LOCAL-RELEASE";
default:
return "?";
}
}
} // namespace rls
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include <memory>
#include <utility>
#include <utils/octet_string.hpp>
#include <utils/octet_view.hpp>
namespace rls
{
enum class EUeState
{
IDLE,
SEARCH,
CONNECTED,
RELEASED,
};
enum class EMessageClass : uint8_t
{
RESERVED = 0,
ERROR_INDICATION,
NORMAL_MESSAGE
};
enum class EMessageType : uint8_t
{
RESERVED = 0,
RLS_SETUP_REQUEST,
RLS_SETUP_RESPONSE,
RLS_SETUP_FAILURE,
RLS_SETUP_COMPLETE,
RLS_HEARTBEAT,
RLS_RELEASE_INDICATION,
RLS_PAYLOAD_TRANSPORT
};
enum class ECause : uint8_t
{
// Error causes (treated as radio link failure)
UNSPECIFIED = 0,
TOKEN_CONFLICT,
EMPTY_SEARCH_LIST,
SETUP_TIMEOUT,
HEARTBEAT_TIMEOUT,
// Successful causes
RRC_NORMAL_RELEASE, // release with UE-gNB coordination over RRC
RRC_LOCAL_RELEASE, // release locally without UE-gNB coordination
};
// Checks if the cause treated as radio link failure
inline bool IsRlf(ECause cause)
{
return cause != ECause::RRC_NORMAL_RELEASE && cause != ECause::RRC_LOCAL_RELEASE;
}
enum class EPayloadType : uint8_t
{
RRC,
DATA,
};
struct Constants
{
static constexpr const int UE_WAIT_TIMEOUT = 500;
static constexpr const int HB_TIMEOUT_GNB_TO_UE = 3000;
static constexpr const int HB_TIMEOUT_UE_TO_GNB = 5000;
static constexpr const int HB_PERIOD_GNB_TO_UE = 1500;
static constexpr const int HB_PERIOD_UE_TO_GNB = 2000;
};
struct RlsMessage
{
EMessageClass msgCls{};
ECause cause{}; // only for RLS_SETUP_FAILURE and error indication messages
std::string str{}; // only for error indication, RLS_SETUP_RESPONSE, RLS_SETUP_COMPLETE, RLS_SETUP_FAILURE
octet3 appVersion{}; // only for normal messages
EMessageType msgType{}; // only for normal messages
uint64_t ueToken{}; // only for normal messages
uint64_t gnbToken{}; // only for normal messages except RLS_SETUP_REQUEST
EPayloadType payloadType{}; // only for RLC_PAYLOAD_TRANSPORT
OctetString payload{}; // only for RLC_PAYLOAD_TRANSPORT
};
enum class DecodeRes
{
OK,
VERSION_MISMATCH,
FAILURE,
};
DecodeRes Decode(const OctetView &stream, RlsMessage &output, octet3 appVersion);
bool Encode(const RlsMessage &msg, OctetString &stream);
const char *CauseToString(ECause cause);
} // namespace rls
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "ue_entity.hpp"
#include <utility>
#include <utils/common.hpp>
#include <utils/constants.hpp>
static const octet3 AppVersion = octet3{cons::Major, cons::Minor, cons::Patch};
namespace rls
{
RlsUeEntity::RlsUeEntity(std::string nodeName, std::vector<InetAddress> gnbSearchList)
: nodeName(std::move(nodeName)), gnbSearchList(std::move(gnbSearchList)), state(EUeState::IDLE), nextSearch(0),
ueToken(0), gnbToken(0), lastGnbHeartbeat(0), lastError(ECause::UNSPECIFIED)
{
}
void RlsUeEntity::onHeartbeat()
{
if (state != EUeState::CONNECTED)
return;
if (utils::CurrentTimeMillis() - lastGnbHeartbeat > Constants::HB_TIMEOUT_GNB_TO_UE)
{
state = EUeState::RELEASED;
nextSearch = 0;
ueToken = 0;
gnbToken = 0;
lastGnbHeartbeat = 0;
lastError = ECause::UNSPECIFIED;
onRelease(ECause::HEARTBEAT_TIMEOUT);
return;
}
RlsMessage msg;
msg.gnbToken = gnbToken;
msg.ueToken = ueToken;
msg.msgType = EMessageType::RLS_HEARTBEAT;
msg.msgCls = EMessageClass::NORMAL_MESSAGE;
msg.appVersion = AppVersion;
sendRlsMessage(selected, msg);
}
void RlsUeEntity::onWaitingTimerExpire()
{
if (state != EUeState::SEARCH)
return;
if (nextSearch + 1 >= gnbSearchList.size())
{
resetEntity();
searchFailure(ECause::SETUP_TIMEOUT);
}
else
{
nextSearch++;
ueToken = utils::Random64();
startWaitingTimer(Constants::UE_WAIT_TIMEOUT);
sendSetupRequest();
}
}
void RlsUeEntity::onUplinkDelivery(EPayloadType type, OctetString &&payload)
{
if (state != EUeState::CONNECTED)
{
logWarn("RLS uplink delivery request without connection");
return;
}
RlsMessage msg;
msg.gnbToken = gnbToken;
msg.ueToken = ueToken;
msg.msgType = EMessageType::RLS_PAYLOAD_TRANSPORT;
msg.msgCls = EMessageClass::NORMAL_MESSAGE;
msg.appVersion = AppVersion;
msg.payloadType = type;
msg.payload = std::move(payload);
sendRlsMessage(selected, msg);
}
void RlsUeEntity::startGnbSearch()
{
if (state == EUeState::SEARCH)
return;
if (state != EUeState::IDLE)
{
logWarn("gNB search request while in not IDLE state");
return;
}
if (gnbSearchList.empty())
{
searchFailure(ECause::EMPTY_SEARCH_LIST);
return;
}
nextSearch = 0;
ueToken = utils::Random64();
startWaitingTimer(Constants::UE_WAIT_TIMEOUT);
state = EUeState::SEARCH;
sendSetupRequest();
}
void RlsUeEntity::onReceive(const InetAddress &address, const OctetString &pdu)
{
if (ueToken == 0)
{
logWarn("Received PDU ignored, UE entity is not initialized");
return;
}
RlsMessage msg{};
auto res = Decode(OctetView{pdu}, msg, AppVersion);
if (res == DecodeRes::FAILURE)
{
logError("PDU decoding failed");
return;
}
if (res == DecodeRes::VERSION_MISMATCH)
{
logError("Version mismatch between UE and gNB");
return;
}
if (msg.msgCls == EMessageClass::ERROR_INDICATION)
{
logError("RLS error indication received | " + std::to_string((int)msg.cause) + " | " + msg.str);
return;
}
if (msg.ueToken != ueToken)
{
logWarn("UE token mismatched message received");
return;
}
if (msg.gnbToken == 0)
{
logWarn("Bad gNB token received");
return;
}
if (state != EUeState::CONNECTED && state != EUeState::SEARCH)
{
logWarn("RLS received while in not CONNECTED or SEARCH");
return;
}
if (state == EUeState::CONNECTED)
{
if (gnbToken != msg.gnbToken)
{
logWarn("gNB token mismatched message received");
return;
}
lastGnbHeartbeat = utils::CurrentTimeMillis();
if (msg.msgType == EMessageType::RLS_PAYLOAD_TRANSPORT)
{
deliverPayload(msg.payloadType, std::move(msg.payload));
}
else if (msg.msgType == EMessageType::RLS_HEARTBEAT)
{
lastGnbHeartbeat = utils::CurrentTimeMillis();
}
else if (msg.msgType == EMessageType::RLS_RELEASE_INDICATION)
{
state = EUeState::RELEASED;
nextSearch = 0;
ueToken = 0;
gnbToken = 0;
lastGnbHeartbeat = 0;
lastError = ECause::UNSPECIFIED;
onRelease(msg.cause);
}
else
{
logWarn("RLS receive invalid message type in CONNECTED " + std::to_string((int)msg.msgType));
}
}
if (state == EUeState::SEARCH)
{
if (msg.msgType == EMessageType::RLS_SETUP_RESPONSE)
{
state = EUeState::CONNECTED;
gnbToken = msg.gnbToken;
lastError = ECause::UNSPECIFIED;
nextSearch = 0;
lastGnbHeartbeat = utils::CurrentTimeMillis();
selected = address;
sendSetupComplete();
onConnect(msg.str);
}
else if (msg.msgType == EMessageType::RLS_SETUP_FAILURE)
{
if (msg.cause != ECause::UNSPECIFIED)
lastError = msg.cause;
if (nextSearch + 1 >= gnbSearchList.size())
{
searchFailure(lastError);
resetEntity();
}
else
{
nextSearch++;
ueToken = utils::Random64();
startWaitingTimer(Constants::UE_WAIT_TIMEOUT);
sendSetupRequest();
}
}
else
{
logWarn("RLS receive invalid message type in IDLE " + std::to_string((int)msg.msgType));
}
}
}
void RlsUeEntity::releaseConnection(ECause cause)
{
sendReleaseIndication(cause);
localReleaseConnection(cause);
}
void RlsUeEntity::resetEntity()
{
state = EUeState::IDLE;
nextSearch = 0;
ueToken = 0;
gnbToken = 0;
lastError = ECause::UNSPECIFIED;
lastGnbHeartbeat = 0;
selected = {};
}
void RlsUeEntity::sendSetupRequest()
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_SETUP_REQUEST;
m.appVersion = AppVersion;
m.ueToken = ueToken;
m.gnbToken = 0;
sendRlsMessage(gnbSearchList[nextSearch], m);
}
void RlsUeEntity::sendSetupComplete()
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_SETUP_COMPLETE;
m.appVersion = AppVersion;
m.ueToken = ueToken;
m.gnbToken = gnbToken;
m.str = nodeName;
sendRlsMessage(selected, m);
}
void RlsUeEntity::sendReleaseIndication(ECause cause)
{
RlsMessage m;
m.msgCls = EMessageClass::NORMAL_MESSAGE;
m.msgType = EMessageType::RLS_RELEASE_INDICATION;
m.appVersion = AppVersion;
m.ueToken = ueToken;
m.gnbToken = gnbToken;
m.cause = cause;
sendRlsMessage(selected, m);
}
void RlsUeEntity::sendRlsMessage(const InetAddress &address, const RlsMessage &msg)
{
OctetString stream{};
if (!Encode(msg, stream))
{
logWarn("PDU encoding failed");
return;
}
//sendRlsPdu(address, std::move(stream));
}
void RlsUeEntity::localReleaseConnection(ECause cause)
{
state = EUeState::RELEASED;
nextSearch = 0;
ueToken = 0;
gnbToken = 0;
lastGnbHeartbeat = 0;
lastError = ECause::UNSPECIFIED;
onRelease(cause);
}
} // namespace rls
\ No newline at end of file
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#pragma once
#include "rls.hpp"
#include <utils/network.hpp>
#include <optional>
namespace rls
{
class RlsUeEntity
{
private:
std::string nodeName;
std::vector<InetAddress> gnbSearchList;
EUeState state;
size_t nextSearch;
uint64_t ueToken;
uint64_t gnbToken;
uint64_t lastGnbHeartbeat;
ECause lastError;
InetAddress selected;
public:
explicit RlsUeEntity(std::string nodeName, std::vector<InetAddress> gnbSearchList);
virtual ~RlsUeEntity() = default;
protected:
virtual void logWarn(const std::string &msg) = 0;
virtual void logError(const std::string &msg) = 0;
virtual void startWaitingTimer(int period) = 0;
virtual void searchFailure(ECause cause) = 0;
virtual void onRelease(ECause cause) = 0;
virtual void onConnect(const std::string &gnbName) = 0;
virtual void sendRlsPdu(const InetAddress &address, OctetString &&pdu) = 0;
virtual void deliverPayload(EPayloadType type, OctetString &&payload) = 0;
public:
void onHeartbeat();
void onWaitingTimerExpire();
void onReceive(const InetAddress &address, const OctetString &pdu);
void onUplinkDelivery(EPayloadType type, OctetString &&payload);
void startGnbSearch();
void releaseConnection(ECause cause);
void localReleaseConnection(ECause cause);
void resetEntity();
private:
void sendSetupRequest();
void sendSetupComplete();
void sendReleaseIndication(ECause cause);
void sendRlsMessage(const InetAddress &address, const RlsMessage &msg);
};
} // namespace rls
\ No newline at end of file
......@@ -34,21 +34,15 @@ enum class NtsMessageType
UDP_SERVER_RECEIVE,
CLI_SEND_RESPONSE,
GNB_MR_TO_MR,
GNB_MR_TO_RRC,
GNB_SRA_TO_RRC,
GNB_RRC_TO_MR,
GNB_RRC_TO_SRA,
GNB_NGAP_TO_RRC,
GNB_RRC_TO_NGAP,
GNB_NGAP_TO_GTP,
GNB_MR_TO_GTP,
GNB_GTP_TO_MR,
GNB_SCTP,
UE_MR_TO_MR,
UE_MR_TO_RRC,
UE_MR_TO_APP,
UE_APP_TO_MR,
UE_APP_TO_TUN,
UE_TUN_TO_APP,
......
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