Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
aligungr committed Feb 27, 2021
2 parents 5cc5b0d + 7a4a246 commit a39a01d
Show file tree
Hide file tree
Showing 79 changed files with 1,536 additions and 508 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<a href="https://github.com/aligungr/UERANSIM"><img src="/.github/logo.png" width="75" title="UERANSIM"></a>
</p>
<p align="center">
<img src="https://img.shields.io/badge/UERANSIM-v3.1.0-blue" />
<img src="https://img.shields.io/badge/UERANSIM-v3.1.1-blue" />
<img src="https://img.shields.io/badge/3GPP-R15-orange" />
<img src="https://img.shields.io/badge/License-GPL--3.0-green"/>
</p>
Expand All @@ -29,7 +29,7 @@ And, since the project is rapidly developing, please make sure that you have alw

## Contributing

Implementing UE and RAN is not an easy task and requires a lot of time. We are always open to public contributions and pull requests.
Implementing UE and RAN is not an easy task and is very time-consuming. We are always open to public contributions and pull requests.

## Supporting

Expand Down
31 changes: 24 additions & 7 deletions src/app/cli_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
static opt::OptionsDescription Desc(const std::string &subCommand, const std::string &desc, const std::string &usage,
bool helpIfEmpty)
{
return {subCommand, cons::Tag, desc, {}, subCommand, {usage}, helpIfEmpty};
return {{}, {}, desc, {}, subCommand, {usage}, helpIfEmpty, true};
}

class OptionsHandler : public opt::IOptionsHandler
Expand Down Expand Up @@ -71,9 +71,7 @@ static std::map<std::string, std::string> g_gnbCmdToDescription = {
};

static std::map<std::string, std::string> g_gnbCmdToUsage = {
{"status", "[option...]"}, {"info", "[option...]"},
{"amf-list", "[option...]"}, {"amf-info", "<amf-id> [option...]"},
{"ue-list", "[option...]"}, {"ue-count", "[option...]"},
{"status", ""}, {"info", ""}, {"amf-list", ""}, {"amf-info", "<amf-id>"}, {"ue-list", ""}, {"ue-count", ""},
};

static std::map<std::string, bool> g_gnbCmdToHelpIfEmpty = {{"status", false}, {"info", false},
Expand All @@ -84,18 +82,21 @@ static std::map<std::string, std::string> g_ueCmdToDescription = {
{"info", "Show some information about the UE"},
{"status", "Show some status information about the UE"},
{"timers", "Dump current status of the timers in the UE"},
{"deregister", "Perform de-registration by the UE"},
};

static std::map<std::string, std::string> g_ueCmdToUsage = {
{"info", "[option...]"},
{"status", "[option...]"},
{"timers", "[option...]"},
{"info", ""},
{"status", ""},
{"timers", ""},
{"deregister", "<normal|disable-5g|switch-off>"},
};

static std::map<std::string, bool> g_ueCmdToHelpIfEmpty = {
{"info", false},
{"status", false},
{"timers", false},
{"deregister", true},
};

std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tokens, std::string &error,
Expand Down Expand Up @@ -224,6 +225,22 @@ std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&token
{
return std::make_unique<UeCliCommand>(UeCliCommand::TIMERS);
}
else if (subCmd == "deregister")
{
auto cmd = std::make_unique<UeCliCommand>(UeCliCommand::DE_REGISTER);
if (options.positionalCount() == 0)
CMD_ERR("De-registration type is expected")
if (options.positionalCount() > 1)
CMD_ERR("Only one de-registration type is expected")
auto type = options.getPositional(0);
if (type == "switch-off")
cmd->isSwitchOff = true;
else if (type == "disable-5g")
cmd->dueToDisable5g = true;
else if (type != "normal")
CMD_ERR("Invalid de-registration type, possible values are: \"normal\", \"disable-5g\", \"switch-off\"")
return cmd;
}

return nullptr;
}
Expand Down
5 changes: 5 additions & 0 deletions src/app/cli_cmd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ struct UeCliCommand
INFO,
STATUS,
TIMERS,
DE_REGISTER,
} present;

// DE_REGISTER
bool isSwitchOff{};
bool dueToDisable5g{};

explicit UeCliCommand(PR present) : present(present)
{
}
Expand Down
1 change: 1 addition & 0 deletions src/app/monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum class StateType
MM_SUB,
RM,
CM,
U5,
};

class INodeListener
Expand Down
9 changes: 9 additions & 0 deletions src/app/proc_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <string>
#include <unordered_map>
#include <utils/concurrent_map.hpp>
#include <vector>

namespace app
Expand Down Expand Up @@ -41,4 +42,12 @@ inline void CreateProcTable(const std::unordered_map<std::string, T> &nodeMap, i
CreateProcTable(nodes, cmdPort);
}

template <typename T>
inline void CreateProcTable(const ConcurrentMap<std::string, T> &nodeMap, int cmdPort)
{
std::vector<std::string> nodes{};
nodeMap.invokeForeach([&nodes](const auto &node) { nodes.push_back(node.first); });
CreateProcTable(nodes, cmdPort);
}

} // namespace app
9 changes: 9 additions & 0 deletions src/app/ue_ctl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// 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_ctl.hpp"
25 changes: 25 additions & 0 deletions src/app/ue_ctl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// 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

namespace nr::ue
{
class UserEquipment;
}

namespace app
{

class IUeController
{
public:
virtual void performSwitchOff(nr::ue::UserEquipment *ue) = 0;
};

} // namespace app
3 changes: 2 additions & 1 deletion src/asn/utils/ngap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,9 @@ int GetProcedureCode(NgapMessageType messageType)
return 40;
case NgapMessageType::UEContextReleaseCommand:
case NgapMessageType::UEContextReleaseComplete:
case NgapMessageType::UEContextReleaseRequest:
return 41;
case NgapMessageType::UEContextReleaseRequest:
return 42;
case NgapMessageType::UERadioCapabilityCheckRequest:
case NgapMessageType::UERadioCapabilityCheckResponse:
case NgapMessageType::UERadioCapabilityInfoIndication:
Expand Down
2 changes: 1 addition & 1 deletion src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static void ReadOptions(int argc, char **argv)
{
opt::OptionsDescription desc{"UERANSIM", cons::Tag, "Command Line Interface",
cons::Owner, "nr-cli", {"<node-name> [option...]", "--dump"},
true};
true, false};

opt::OptionItem itemDump = {'d', "dump", "List all UE and gNBs in the environment", std::nullopt};
opt::OptionItem itemExec = {'e', "exec", "Execute the given command directly without an interactive shell",
Expand Down
15 changes: 9 additions & 6 deletions src/gnb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void ReadOptions(int argc, char **argv)
{
opt::OptionsDescription desc{cons::Project, cons::Tag, "5G-SA gNB implementation",
cons::Owner, "nr-gnb", {"-c <config-file> [option...]"},
true};
true, false};

opt::OptionItem itemConfigFile = {'c', "config", "Use specified configuration file for gNB", "config-file"};
opt::OptionItem itemDisableCmd = {'l', "disable-cmd", "Disable command line functionality for this instance",
Expand Down Expand Up @@ -153,7 +153,7 @@ static void ReceiveCommand(app::CliMessage &msg)
}

auto *gnb = g_gnbMap[msg.nodeName];
gnb->pushCommand(std::move(cmd), msg.clientAddr, g_cliRespTask);
gnb->pushCommand(std::move(cmd), msg.clientAddr);
}

static void Loop()
Expand Down Expand Up @@ -196,15 +196,18 @@ int main(int argc, char **argv)

std::cout << cons::Name << std::endl;

auto *gnb = new nr::gnb::GNodeB(g_refConfig, nullptr);
if (!g_options.disableCmd)
{
g_cliServer = new app::CliServer{};
g_cliRespTask = new app::CliResponseTask(g_cliServer);
}

auto *gnb = new nr::gnb::GNodeB(g_refConfig, nullptr, g_cliRespTask);
g_gnbMap[g_refConfig->name] = gnb;

if (!g_options.disableCmd)
{
g_cliServer = new app::CliServer{};
app::CreateProcTable(g_gnbMap, g_cliServer->assignedAddress().getPort());

g_cliRespTask = new app::CliResponseTask(g_cliServer);
g_cliRespTask->start();
}

Expand Down
84 changes: 47 additions & 37 deletions src/gnb/app/cmd_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,52 @@
namespace nr::gnb
{

void GnbCmdHandler::PauseTasks(TaskBase &base)
void GnbCmdHandler::sendResult(const InetAddress &address, const std::string &output)
{
base.gtpTask->requestPause();
base.mrTask->requestPause();
base.ngapTask->requestPause();
base.rrcTask->requestPause();
base.sctpTask->requestPause();
m_base->cliCallbackTask->push(new app::NwCliSendResponse(address, output, false));
}

void GnbCmdHandler::UnpauseTasks(TaskBase &base)
void GnbCmdHandler::sendError(const InetAddress &address, const std::string &output)
{
base.gtpTask->requestUnpause();
base.mrTask->requestUnpause();
base.ngapTask->requestUnpause();
base.rrcTask->requestUnpause();
base.sctpTask->requestUnpause();
m_base->cliCallbackTask->push(new app::NwCliSendResponse(address, output, true));
}

bool GnbCmdHandler::IsAllPaused(TaskBase &base)
void GnbCmdHandler::pauseTasks()
{
if (!base.gtpTask->isPauseConfirmed())
m_base->gtpTask->requestPause();
m_base->mrTask->requestPause();
m_base->ngapTask->requestPause();
m_base->rrcTask->requestPause();
m_base->sctpTask->requestPause();
}

void GnbCmdHandler::unpauseTasks()
{
m_base->gtpTask->requestUnpause();
m_base->mrTask->requestUnpause();
m_base->ngapTask->requestUnpause();
m_base->rrcTask->requestUnpause();
m_base->sctpTask->requestUnpause();
}

bool GnbCmdHandler::isAllPaused()
{
if (!m_base->gtpTask->isPauseConfirmed())
return false;
if (!base.mrTask->isPauseConfirmed())
if (!m_base->mrTask->isPauseConfirmed())
return false;
if (!base.ngapTask->isPauseConfirmed())
if (!m_base->ngapTask->isPauseConfirmed())
return false;
if (!base.rrcTask->isPauseConfirmed())
if (!m_base->rrcTask->isPauseConfirmed())
return false;
if (!base.sctpTask->isPauseConfirmed())
if (!m_base->sctpTask->isPauseConfirmed())
return false;
return true;
}

void GnbCmdHandler::HandleCmd(TaskBase &base, NwGnbCliCommand &msg)
void GnbCmdHandler::handleCmd(NwGnbCliCommand &msg)
{
PauseTasks(base);
pauseTasks();

uint64_t currentTime = utils::CurrentTimeMillis();
uint64_t endTime = currentTime + PAUSE_CONFIRM_TIMEOUT;
Expand All @@ -67,7 +77,7 @@ void GnbCmdHandler::HandleCmd(TaskBase &base, NwGnbCliCommand &msg)
while (currentTime < endTime)
{
currentTime = utils::CurrentTimeMillis();
if (IsAllPaused(base))
if (isAllPaused())
{
isPaused = true;
break;
Expand All @@ -77,60 +87,60 @@ void GnbCmdHandler::HandleCmd(TaskBase &base, NwGnbCliCommand &msg)

if (!isPaused)
{
msg.sendError("gNB is unable process command due to pausing timeout");
sendError(msg.address, "gNB is unable process command due to pausing timeout");
}
else
{
HandleCmdImpl(base, msg);
handleCmdImpl(msg);
}

UnpauseTasks(base);
unpauseTasks();
}

void GnbCmdHandler::HandleCmdImpl(TaskBase &base, NwGnbCliCommand &msg)
void GnbCmdHandler::handleCmdImpl(NwGnbCliCommand &msg)
{
switch (msg.cmd->present)
{
case app::GnbCliCommand::STATUS: {
msg.sendResult(ToJson(base.appTask->m_statusInfo).dumpYaml());
sendResult(msg.address, ToJson(m_base->appTask->m_statusInfo).dumpYaml());
break;
}
case app::GnbCliCommand::INFO: {
msg.sendResult(ToJson(*base.config).dumpYaml());
sendResult(msg.address, ToJson(*m_base->config).dumpYaml());
break;
}
case app::GnbCliCommand::AMF_LIST: {
Json json = Json::Arr({});
for (auto &amf : base.ngapTask->m_amfCtx)
for (auto &amf : m_base->ngapTask->m_amfCtx)
json.push(Json::Obj({{"id", amf.first}}));
msg.sendResult(json.dumpYaml());
sendResult(msg.address, json.dumpYaml());
break;
}
case app::GnbCliCommand::AMF_INFO: {
if (base.ngapTask->m_amfCtx.count(msg.cmd->amfId) == 0)
msg.sendError("AMF not found with given ID");
if (m_base->ngapTask->m_amfCtx.count(msg.cmd->amfId) == 0)
sendError(msg.address, "AMF not found with given ID");
else
{
auto amf = base.ngapTask->m_amfCtx[msg.cmd->amfId];
msg.sendResult(ToJson(*amf).dumpYaml());
auto amf = m_base->ngapTask->m_amfCtx[msg.cmd->amfId];
sendResult(msg.address, ToJson(*amf).dumpYaml());
}
break;
}
case app::GnbCliCommand::UE_LIST: {
Json json = Json::Arr({});
for (auto &ue : base.ngapTask->m_ueCtx)
for (auto &ue : m_base->ngapTask->m_ueCtx)
{
json.push(Json::Obj({
{"ue-name", base.mrTask->m_ueMap[ue.first].name},
{"ue-name", m_base->mrTask->m_ueMap[ue.first].name},
{"ran-ngap-id", ue.second->ranUeNgapId},
{"amf-ngap-id", ue.second->amfUeNgapId},
}));
}
msg.sendResult(json.dumpYaml());
sendResult(msg.address, json.dumpYaml());
break;
}
case app::GnbCliCommand::UE_COUNT: {
msg.sendResult(std::to_string(base.ngapTask->m_ueCtx.size()));
sendResult(msg.address, std::to_string(m_base->ngapTask->m_ueCtx.size()));
break;
}
}
Expand Down
Loading

0 comments on commit a39a01d

Please sign in to comment.