Commit 22a5e921 authored by aligungr's avatar aligungr

PS establishment over CLI

parent bdddb08c
......@@ -10,6 +10,7 @@
#include <map>
#include <optional>
#include <sstream>
#include <utility>
#include <utils/common.hpp>
#include <utils/constants.hpp>
#include <utils/options.hpp>
......@@ -21,14 +22,6 @@
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
{
public:
......@@ -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;
for (auto &item : descTable)
for (auto &item : entryTable)
maxLength = std::max(maxLength, item.size());
std::stringstream ss{};
for (auto &item : descTable)
ss << item << std::string(maxLength - item.size(), ' ') << " | " << descTable[item] << "\n";
for (auto &item : entryTable)
ss << item << std::string(maxLength - item.size(), ' ') << " | " << entryTable[item].descriptionText << "\n";
std::string output = ss.str();
utils::Trim(output);
return output;
}
namespace app
{
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}};
//======================================================================================================
// IMPLEMENTATION
//======================================================================================================
static OrderedMap<std::string, DescType> g_ueCmdToDescFunc = {
{"info", DefaultDesc}, {"status", DefaultDesc}, {"timers", DefaultDesc},
{"deregister", DefaultDesc}, {"ps-establish", DefaultDesc}, {"ps-release", DefaultDesc},
{"ps-release-all", DefaultDesc},
};
static opt::OptionsDescription DefaultDesc(const std::string &subCommand, const CmdEntry &entry)
{
return {{}, {}, entry.descriptionText, {}, subCommand, {entry.usageText}, entry.helpIfEmpty, true};
}
static OrderedMap<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 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"},
};
namespace app
{
static std::map<std::string, std::string> g_ueCmdToUsage = {
{"info", ""}, {"status", ""},
{"timers", ""}, {"deregister", "<normal|disable-5g|switch-off|remove-sim>"},
{"ps-establish", ""}, {"ps-release", "<pdu-session-id>..."},
{"ps-release-all", ""},
static OrderedMap<std::string, CmdEntry> g_gnbCmdEntries = {
{"info", {"Show some information about the gNB", "", DefaultDesc, false}},
{"status", {"Show some status information about the gNB", "", DefaultDesc, false}},
{"amf-list", {"List all AMFs associated with the gNB", "", DefaultDesc, false}},
{"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 = {
{"info", false}, {"status", false}, {"timers", false}, {"deregister", true},
{"ps-establish", true}, {"ps-release", true}, {"ps-release-all", false},
static OrderedMap<std::string, CmdEntry> g_ueCmdEntries = {
{"info", {"Show some information about the UE", "", DefaultDesc, 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,
std::string &output)
static std::unique_ptr<GnbCliCommand> GnbCliParseImpl(const std::string &subCmd, const opt::OptionsResult &options,
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")
{
return std::make_unique<GnbCliCommand>(GnbCliCommand::INFO);
......@@ -190,45 +145,9 @@ std::unique_ptr<GnbCliCommand> ParseGnbCliCommand(std::vector<std::string> &&tok
return nullptr;
}
std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&tokens, std::string &error,
std::string &output)
static std::unique_ptr<UeCliCommand> UeCliParseImpl(const std::string &subCmd, const opt::OptionsResult &options,
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")
{
return std::make_unique<UeCliCommand>(UeCliCommand::INFO);
......@@ -290,4 +209,65 @@ std::unique_ptr<UeCliCommand> ParseUeCliCommand(std::vector<std::string> &&token
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
......@@ -27,11 +27,11 @@ class OrderedMap
{
if (!m_map.count(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);
}
......
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