Commit 22a5e921 authored by aligungr's avatar aligungr

PS establishment over CLI

parent bdddb08c
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <map> #include <map>
#include <optional> #include <optional>
#include <sstream> #include <sstream>
#include <utility>
#include <utils/common.hpp> #include <utils/common.hpp>
#include <utils/constants.hpp> #include <utils/constants.hpp>
#include <utils/options.hpp> #include <utils/options.hpp>
...@@ -21,14 +22,6 @@ ...@@ -21,14 +22,6 @@
return nullptr; \ return nullptr; \
} }
static opt::OptionsDescription DefaultDesc(const std::string &subCommand, const std::string &desc,
const std::string &usage, bool helpIfEmpty)
{
return {{}, {}, desc, {}, subCommand, {usage}, helpIfEmpty, true};
}
using DescType = decltype(&DefaultDesc);
class OptionsHandler : public opt::IOptionsHandler class OptionsHandler : public opt::IOptionsHandler
{ {
public: public:
...@@ -47,113 +40,75 @@ class OptionsHandler : public opt::IOptionsHandler ...@@ -47,113 +40,75 @@ class OptionsHandler : public opt::IOptionsHandler
} }
}; };
static std::string DumpCommands(const OrderedMap<std::string, std::string> &descTable)
struct CmdEntry
{
using DescType = opt::OptionsDescription (*)(const std::string &, const CmdEntry &);
std::string descriptionText;
std::string usageText;
DescType descriptionFunc;
bool helpIfEmpty;
CmdEntry() = delete;
CmdEntry(std::string descriptionText, std::string usageText, DescType descriptionFunc, bool helpIfEmpty)
: descriptionText(std::move(descriptionText)), usageText(std::move(usageText)),
descriptionFunc(descriptionFunc), helpIfEmpty(helpIfEmpty)
{
}
};
static std::string DumpCommands(const OrderedMap<std::string, CmdEntry> &entryTable)
{ {
size_t maxLength = 0; size_t maxLength = 0;
for (auto &item : descTable) for (auto &item : entryTable)
maxLength = std::max(maxLength, item.size()); maxLength = std::max(maxLength, item.size());
std::stringstream ss{}; std::stringstream ss{};
for (auto &item : descTable) for (auto &item : entryTable)
ss << item << std::string(maxLength - item.size(), ' ') << " | " << descTable[item] << "\n"; ss << item << std::string(maxLength - item.size(), ' ') << " | " << entryTable[item].descriptionText << "\n";
std::string output = ss.str(); std::string output = ss.str();
utils::Trim(output); utils::Trim(output);
return output; return output;
} }
namespace app //======================================================================================================
{ // IMPLEMENTATION
//======================================================================================================
static OrderedMap<std::string, DescType> g_gnbCmdToDescFunc = {
{"status", DefaultDesc}, {"info", DefaultDesc}, {"amf-list", DefaultDesc},
{"amf-info", DefaultDesc}, {"ue-list", DefaultDesc}, {"ue-count", DefaultDesc},
};
static OrderedMap<std::string, std::string> g_gnbCmdToDescription = {
{"status", "Show some status information about the gNB"},
{"info", "Show some information about the gNB"},
{"amf-list", "List all AMFs associated with the gNB"},
{"amf-info", "Show some status information about the given AMF"},
{"ue-list", "List all UEs associated with the gNB"},
{"ue-count", "Print the total number of UEs connected the this gNB"},
};
static OrderedMap<std::string, std::string> g_gnbCmdToUsage = {
{"status", ""}, {"info", ""}, {"amf-list", ""}, {"amf-info", "<amf-id>"}, {"ue-list", ""}, {"ue-count", ""},
};
static OrderedMap<std::string, bool> g_gnbCmdToHelpIfEmpty = {{"status", false}, {"info", false},
{"amf-list", false}, {"amf-info", true},
{"ue-list", false}, {"ue-count", false}};
static OrderedMap<std::string, DescType> g_ueCmdToDescFunc = { static opt::OptionsDescription DefaultDesc(const std::string &subCommand, const CmdEntry &entry)
{"info", DefaultDesc}, {"status", DefaultDesc}, {"timers", DefaultDesc}, {
{"deregister", DefaultDesc}, {"ps-establish", DefaultDesc}, {"ps-release", DefaultDesc}, return {{}, {}, entry.descriptionText, {}, subCommand, {entry.usageText}, entry.helpIfEmpty, true};
{"ps-release-all", DefaultDesc}, }
};
static OrderedMap<std::string, std::string> g_ueCmdToDescription = { namespace app
{"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 a de-registration by the UE"},
{"ps-establish", "Trigger a PDU session establishment procedure"},
{"ps-release", "Trigger a PDU session release procedure"},
{"ps-release-all", "Trigger PDU session release procedures for all active sessions"},
};
static std::map<std::string, std::string> g_ueCmdToUsage = { static OrderedMap<std::string, CmdEntry> g_gnbCmdEntries = {
{"info", ""}, {"status", ""}, {"info", {"Show some information about the gNB", "", DefaultDesc, false}},
{"timers", ""}, {"deregister", "<normal|disable-5g|switch-off|remove-sim>"}, {"status", {"Show some status information about the gNB", "", DefaultDesc, false}},
{"ps-establish", ""}, {"ps-release", "<pdu-session-id>..."}, {"amf-list", {"List all AMFs associated with the gNB", "", DefaultDesc, false}},
{"ps-release-all", ""}, {"amf-info", {"Show some status information about the given AMF", "<amf-id>", DefaultDesc, true}},
{"ue-list", {"List all UEs associated with the gNB", "", DefaultDesc, false}},
{"ue-count", {"Print the total number of UEs connected the this gNB", "", DefaultDesc, false}},
}; };
static std::map<std::string, bool> g_ueCmdToHelpIfEmpty = { static OrderedMap<std::string, CmdEntry> g_ueCmdEntries = {
{"info", false}, {"status", false}, {"timers", false}, {"deregister", true}, {"info", {"Show some information about the UE", "", DefaultDesc, false}},
{"ps-establish", true}, {"ps-release", true}, {"ps-release-all", false}, {"status", {"Show some status information about the UE", "", DefaultDesc, false}},
{"timers", {"Dump current status of the timers in the UE", "", DefaultDesc, false}},
{"deregister",
{"Perform a de-registration by the UE", "<normal|disable-5g|switch-off|remove-sim>", DefaultDesc, true}},
{"ps-establish", {"Trigger a PDU session establishment procedure", "", DefaultDesc, true}},
{"ps-release", {"Trigger a PDU session release procedure", "<pdu-session-id>...", DefaultDesc, true}},
{"ps-release-all", {"Trigger PDU session release procedures for all active sessions", "", DefaultDesc, false}},
}; };
std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tokens, std::string &error, static std::unique_ptr<GnbCliCommand> GnbCliParseImpl(const std::string &subCmd, const opt::OptionsResult &options,
std::string &output) std::string &error)
{ {
if (tokens.empty())
{
error = "Empty command";
return nullptr;
}
std::string &subCmd = tokens[0];
if (subCmd == "commands")
{
output = DumpCommands(g_gnbCmdToDescription);
return nullptr;
}
if (g_gnbCmdToDescription.count(subCmd) == 0 || g_gnbCmdToUsage.count(subCmd) == 0 ||
g_gnbCmdToHelpIfEmpty.count(subCmd) == 0)
{
error = "Command not recognized: " + subCmd;
return nullptr;
}
opt::OptionsDescription desc = g_gnbCmdToDescFunc[subCmd](subCmd, g_gnbCmdToDescription[subCmd],
g_gnbCmdToUsage[subCmd], g_gnbCmdToHelpIfEmpty[subCmd]);
OptionsHandler handler{};
opt::OptionsResult options{tokens, desc, &handler};
error = handler.m_err.str();
output = handler.m_output.str();
utils::Trim(error);
utils::Trim(output);
if (!error.empty() || !output.empty())
return nullptr;
if (subCmd == "info") if (subCmd == "info")
{ {
return std::make_unique<GnbCliCommand>(GnbCliCommand::INFO); return std::make_unique<GnbCliCommand>(GnbCliCommand::INFO);
...@@ -190,45 +145,9 @@ std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tok ...@@ -190,45 +145,9 @@ std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tok
return nullptr; return nullptr;
} }
std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&tokens, std::string &error, static std::unique_ptr<UeCliCommand> UeCliParseImpl(const std::string &subCmd, const opt::OptionsResult &options,
std::string &output) std::string &error)
{ {
if (tokens.empty())
{
error = "Empty command";
return nullptr;
}
std::string &subCmd = tokens[0];
if (subCmd == "commands")
{
output = DumpCommands(g_ueCmdToDescription);
return nullptr;
}
if (g_ueCmdToDescription.count(subCmd) == 0 || g_ueCmdToUsage.count(subCmd) == 0 ||
g_ueCmdToHelpIfEmpty.count(subCmd) == 0)
{
error = "Command not recognized: " + subCmd;
return nullptr;
}
opt::OptionsDescription desc = g_ueCmdToDescFunc[subCmd](subCmd, g_ueCmdToDescription[subCmd],
g_ueCmdToUsage[subCmd], g_ueCmdToHelpIfEmpty[subCmd]);
OptionsHandler handler{};
opt::OptionsResult options{tokens, desc, &handler};
error = handler.m_err.str();
output = handler.m_output.str();
utils::Trim(error);
utils::Trim(output);
if (!error.empty() || !output.empty())
return nullptr;
if (subCmd == "info") if (subCmd == "info")
{ {
return std::make_unique<UeCliCommand>(UeCliCommand::INFO); return std::make_unique<UeCliCommand>(UeCliCommand::INFO);
...@@ -290,4 +209,65 @@ std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&token ...@@ -290,4 +209,65 @@ std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&token
return nullptr; return nullptr;
} }
static std::optional<opt::OptionsResult> ParseCliCommandCommon(OrderedMap<std::string, CmdEntry> &cmdEntries,
std::vector<std::string> &&tokens, std::string &error,
std::string &output, std::string &subCmd)
{
if (tokens.empty())
{
error = "Empty command";
return {};
}
subCmd = tokens[0];
if (subCmd == "commands")
{
output = DumpCommands(cmdEntries);
return {};
}
if (cmdEntries.count(subCmd) == 0)
{
error = "Command not recognized: " + subCmd;
return {};
}
opt::OptionsDescription desc = cmdEntries[subCmd].descriptionFunc(subCmd, cmdEntries[subCmd]);
OptionsHandler handler{};
opt::OptionsResult options{tokens, desc, &handler};
error = handler.m_err.str();
output = handler.m_output.str();
utils::Trim(error);
utils::Trim(output);
if (!error.empty() || !output.empty())
return {};
return options;
}
std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tokens, std::string &error,
std::string &output)
{
std::string subCmd{};
auto options = ParseCliCommandCommon(g_gnbCmdEntries, std::move(tokens), error, output, subCmd);
if (options.has_value())
return GnbCliParseImpl(subCmd, *options, error);
return nullptr;
}
std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&tokens, std::string &error,
std::string &output)
{
std::string subCmd{};
auto options = ParseCliCommandCommon(g_ueCmdEntries, std::move(tokens), error, output, subCmd);
if (options.has_value())
return UeCliParseImpl(subCmd, *options, error);
return nullptr;
}
} // namespace app } // namespace app
...@@ -27,11 +27,11 @@ class OrderedMap ...@@ -27,11 +27,11 @@ class OrderedMap
{ {
if (!m_map.count(pair.first)) if (!m_map.count(pair.first))
m_keyOrder.push_back(pair.first); m_keyOrder.push_back(pair.first);
m_map[pair.first] = pair.second; m_map.insert(pair);
} }
} }
inline auto count(const TKey &key) inline auto count(const TKey &key) const
{ {
return m_map.count(key); return m_map.count(key);
} }
......
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