Commit 50653056 authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

Get AMF configuration from Json

parent e871b3db
......@@ -152,12 +152,19 @@ void amf_app_task(void*) {
} break;
case SBI_AMF_CONFIGURATION: {
Logger::amf_app().debug("Received N11_AMF_CONFIGURATION");
Logger::amf_app().debug("Received SBI_AMF_CONFIGURATION");
itti_sbi_amf_configuration* m =
dynamic_cast<itti_sbi_amf_configuration*>(msg);
amf_app_inst->handle_itti_message(ref(*m));
} break;
case SBI_UPDATE_AMF_CONFIGURATION: {
Logger::amf_app().debug("Received SBI_UPDATE_AMF_CONFIGURATION");
itti_sbi_update_amf_configuration* m =
dynamic_cast<itti_sbi_update_amf_configuration*>(msg);
amf_app_inst->handle_itti_message(ref(*m));
} break;
case TIME_OUT: {
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) {
......@@ -733,12 +740,45 @@ void amf_app::handle_itti_message(itti_sbi_amf_configuration& itti_msg) {
}
}
//---------------------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_sbi_update_amf_configuration& itti_msg) {
Logger::amf_app().info(
"Handle a request UpdateAMFConfiguration from a NF (HTTP version "
"%d)",
itti_msg.http_version);
// Process the request and trigger the response from AMF API Server
nlohmann::json response_data = {};
response_data["content"] = {};
if (update_amf_configuration(response_data["content"])) {
Logger::amf_app().debug(
"AMF configuration:\n %s", response_data["content"].dump().c_str());
response_data["httpResponseCode"] = 200; // TODO:
} else {
response_data["httpResponseCode"] = 400; // TODO:
oai::amf::model::ProblemDetails problem_details = {};
// TODO set problem_details
to_json(response_data["ProblemDetails"], problem_details);
}
// Notify to the result
if (itti_msg.promise_id > 0) {
trigger_process_response(itti_msg.promise_id, response_data);
return;
}
}
//---------------------------------------------------------------------------------------------
bool amf_app::read_amf_configuration(nlohmann::json& json_data) {
amf_cfg.to_json(json_data);
return true;
}
//---------------------------------------------------------------------------------------------
bool amf_app::update_amf_configuration(nlohmann::json& json_data) {
return amf_cfg.from_json(json_data);
}
//---------------------------------------------------------------------------------------------
void amf_app::add_n1n2_message_subscription(
const std::string& ue_ctx_id, const n1n2sub_id_t& sub_id,
......
......@@ -159,7 +159,15 @@ class amf_app {
*/
void handle_itti_message(itti_sbi_amf_configuration& itti_msg);
/*
* Handle ITTI message (Update AMF configuration)
* @param [itti_sbi_update_amf_configuration&]: ITTI message
* @return void
*/
void handle_itti_message(itti_sbi_update_amf_configuration& itti_msg);
bool read_amf_configuration(nlohmann::json& json_data);
bool update_amf_configuration(nlohmann::json& json_data);
/*
* Verify if a UE context associated with an AMF UE NGAP ID exist
......
......@@ -707,12 +707,16 @@ void amf_config::display() {
std::string str = {};
str = str.append(" SST")
.append(
(plmn_list[i].slice_list[j].sst > 127) ? ", SD " : " ....")
(plmn_list[i].slice_list[j].sst >
SST_MAX_STANDARDIZED_VALUE) ?
", SD " :
" ....")
.append("...........: ")
.append(std::to_string(plmn_list[i].slice_list[j].sst))
.append("")
.append(
(plmn_list[i].slice_list[j].sst > 127) ?
(plmn_list[i].slice_list[j].sst >
SST_MAX_STANDARDIZED_VALUE) ?
", " + std::to_string(plmn_list[i].slice_list[j].sd) :
" ");
Logger::config().info(str.c_str());
......@@ -954,15 +958,15 @@ void amf_config::to_json(nlohmann::json& json_data) const {
}
if (support_features.enable_external_nssf) {
json_data["nrf"] = nssf_addr.to_json();
json_data["nssf"] = nssf_addr.to_json();
}
if (support_features.enable_external_ausf) {
json_data["nrf"] = ausf_addr.to_json();
json_data["ausf"] = ausf_addr.to_json();
}
if (support_features.enable_external_udm) {
json_data["nrf"] = udm_addr.to_json();
json_data["udm"] = udm_addr.to_json();
}
json_data["smf_pool"] = nlohmann::json::array();
......@@ -970,4 +974,109 @@ void amf_config::to_json(nlohmann::json& json_data) const {
json_data["smf_pool"].push_back(s.to_json());
}
}
bool amf_config::from_json(nlohmann::json& json_data) {
try {
if (json_data.find("instance") != json_data.end()) {
instance = json_data["instance"].get<int>();
}
if (json_data.find("pid_dir") != json_data.end()) {
pid_dir = json_data["pid_dir"].get<std::string>();
}
if (json_data.find("amf_name") != json_data.end()) {
AMF_Name = json_data["amf_name"].get<std::string>();
}
if (json_data.find("guami") != json_data.end()) {
guami.from_json(json_data["guami"]);
}
if (json_data.find("guami_list") != json_data.end()) {
for (auto s : json_data["guami_list"]) {
guami_t g = {};
g.from_json(s);
guami_list.push_back(g);
}
}
if (json_data.find("relativeAMFCapacity") != json_data.end()) {
relativeAMFCapacity = json_data["relativeAMFCapacity"].get<int>();
}
if (json_data.find("plmn_list") != json_data.end()) {
for (auto s : json_data["plmn_list"]) {
plmn_item_t p = {};
p.from_json(s);
plmn_list.push_back(p);
}
}
if (json_data.find("is_emergency_support") != json_data.end()) {
is_emergency_support =
json_data["is_emergency_support"].get<std::string>();
}
if (json_data.find("is_emergency_support") != json_data.end()) {
auth_para.from_json(json_data["auth_para"]);
}
if (json_data.find("n2") != json_data.end()) {
n2.from_json(json_data["n2"]);
}
if (json_data.find("n11") != json_data.end()) {
n2.from_json(json_data["n11"]);
}
if (json_data.find("sbi_http2_port") != json_data.end()) {
sbi_http2_port = json_data["sbi_http2_port"].get<int>();
}
if (json_data.find("support_features") != json_data.end()) {
support_features.from_json(json_data["support_features"]);
}
if (support_features.enable_external_nrf) {
if (json_data.find("nrf") != json_data.end()) {
nrf_addr.from_json(json_data["nrf"]);
}
}
if (support_features.enable_external_nssf) {
if (json_data.find("nssf") != json_data.end()) {
nssf_addr.from_json(json_data["nssf"]);
}
}
if (support_features.enable_external_ausf) {
if (json_data.find("ausf") != json_data.end()) {
ausf_addr.from_json(json_data["ausf"]);
}
}
if (support_features.enable_external_udm) {
if (json_data.find("udm") != json_data.end()) {
udm_addr.from_json(json_data["udm"]);
}
}
if (json_data.find("smf_pool") != json_data.end()) {
for (auto s : json_data["smf_pool"]) {
smf_inst_t smf_item = {};
smf_item.from_json(s);
smf_pool.push_back(smf_item);
}
}
} catch (nlohmann::detail::exception& e) {
Logger::amf_app().error(
"Exception when reading configuration from json %s", e.what());
return false;
} catch (std::exception& e) {
Logger::amf_app().error(
"Exception when reading configuration from json %s", e.what());
return false;
}
return true;
}
} // namespace config
......@@ -37,9 +37,14 @@
#include <nlohmann/json.hpp>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "amf_config.hpp"
#include "amf.hpp"
#include "if.hpp"
#include "string.hpp"
#include "thread_sched.hpp"
#include "common_defs.h"
#define AMF_CONFIG_STRING_AMF_CONFIG "AMF"
#define AMF_CONFIG_STRING_PID_DIRECTORY "PID_DIRECTORY"
......@@ -134,6 +139,15 @@ typedef struct {
json_data["random"] = this->random;
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->mysql_server = json_data["mysql_server"].get<std::string>();
this->mysql_user = json_data["mysql_user"].get<std::string>();
this->mysql_pass = json_data["mysql_pass"].get<std::string>();
this->mysql_db = json_data["mysql_db"].get<std::string>();
this->random = json_data["random"].get<std::string>();
}
} auth_conf;
typedef struct interface_cfg_s {
......@@ -157,6 +171,33 @@ typedef struct interface_cfg_s {
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->if_name = json_data["if_name"].get<std::string>();
std::string addr4_str = {};
addr4_str = json_data["addr4"].get<std::string>();
if (boost::iequals(addr4_str, "read")) {
if (get_inet_addr_infos_from_iface(
this->if_name, this->addr4, this->network4, this->mtu)) {
Logger::amf_app().error(
"Could not read %s network interface configuration", this->if_name);
return;
}
} else {
IPV4_STR_ADDR_TO_INADDR(
util::trim(addr4_str).c_str(), this->addr4,
"BAD IPv4 ADDRESS FORMAT FOR INTERFACE !");
std::string network4_str = json_data["network4"].get<std::string>();
IPV4_STR_ADDR_TO_INADDR(
util::trim(network4_str).c_str(), this->network4,
"BAD IPv4 ADDRESS FORMAT FOR INTERFACE !");
// TODO: addr6
this->mtu = json_data["mtu"].get<int>();
this->port = json_data["port"].get<int>();
}
}
} interface_cfg_t;
typedef struct itti_cfg_s {
......@@ -183,6 +224,14 @@ typedef struct guami_s {
json_data["AmfPointer"] = this->AmfPointer;
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->mcc = json_data["mcc"].get<std::string>();
this->mnc = json_data["mnc"].get<std::string>();
this->regionID = json_data["regionID"].get<std::string>();
this->AmfSetID = json_data["AmfSetID"].get<std::string>();
this->AmfPointer = json_data["AmfPointer"].get<std::string>();
}
} guami_t;
typedef struct slice_s {
......@@ -205,10 +254,15 @@ typedef struct slice_s {
nlohmann::json to_json() const {
nlohmann::json json_data = {};
json_data["sst"] = this->sst;
if (sst > 127) json_data["sd"] = this->sd;
if (sst > SST_MAX_STANDARDIZED_VALUE) json_data["sd"] = this->sd;
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->sst = json_data["sst"].get<int>();
if (this->sst > SST_MAX_STANDARDIZED_VALUE)
this->sd = json_data["sd"].get<int>();
}
} slice_t;
typedef struct plmn_support_item_s {
......@@ -228,6 +282,20 @@ typedef struct plmn_support_item_s {
}
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->mcc = json_data["mcc"].get<std::string>();
this->mnc = json_data["mnc"].get<std::string>();
this->tac = json_data["tac"].get<int>();
json_data["slice_list"] = nlohmann::json::array();
for (auto s : json_data["slice_list"]) {
slice_t sl = {};
sl.from_json(s);
slice_list.push_back(sl);
}
}
} plmn_item_t;
typedef struct {
......@@ -269,6 +337,17 @@ typedef struct {
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->id = json_data["id"].get<int>();
this->ipv4 = json_data["ipv4"].get<std::string>();
this->port = json_data["port"]
.get<std::string>(); // TODO: use int instead of string
this->http2_port = json_data["http2_port"].get<int>();
this->version = json_data["version"].get<std::string>();
this->selected = json_data["selected"].get<bool>();
this->fqdn = json_data["fqdn"].get<std::string>();
}
} smf_inst_t;
typedef struct nf_addr_s {
......@@ -283,6 +362,16 @@ typedef struct nf_addr_s {
json_data["api_version"] = this->api_version;
return json_data;
}
void from_json(nlohmann::json& json_data) {
std::string ipv4_addr_str = json_data["ipv4_addr"].get<std::string>();
IPV4_STR_ADDR_TO_INADDR(
util::trim(ipv4_addr_str).c_str(), this->ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR INTERFACE !");
this->port = json_data["port"].get<int>();
this->api_version = json_data["api_version"].get<std::string>();
}
} nf_addr_t;
class amf_config {
......@@ -362,6 +451,13 @@ class amf_config {
*/
void to_json(nlohmann::json& json_data) const;
/*
* Update AMF's config from Json
* @param [nlohmann::json &] json_data: Updated configuration in json format
* @return true if success otherwise return false
*/
bool from_json(nlohmann::json& json_data);
unsigned int instance;
std::string pid_dir;
interface_cfg_t n2;
......@@ -404,6 +500,23 @@ class amf_config {
json_data["use_http2"] = this->use_http2;
return json_data;
}
void from_json(nlohmann::json& json_data) {
this->enable_nf_registration =
json_data["enable_nf_registration"].get<bool>();
this->enable_external_nrf = json_data["enable_external_nrf"].get<bool>();
this->enable_smf_selection =
json_data["enable_smf_selection"].get<bool>();
this->enable_external_nrf = json_data["enable_external_nrf"].get<bool>();
this->enable_external_ausf =
json_data["enable_external_ausf"].get<bool>();
this->enable_external_udm = json_data["enable_external_udm"].get<bool>();
this->enable_external_nssf =
json_data["enable_external_nssf"].get<bool>();
this->use_fqdn_dns = json_data["use_fqdn_dns"].get<bool>();
this->use_http2 = json_data["use_http2"].get<bool>();
}
} support_features;
nf_addr_t nrf_addr;
......
......@@ -95,6 +95,7 @@ typedef enum {
N11_NF_INSTANCE_DISCOVERY,
N11_N1_MESSAGE_NOTIFY,
SBI_AMF_CONFIGURATION,
SBI_UPDATE_AMF_CONFIGURATION,
SBI_EVENT_EXPOSURE_REQUEST,
SBI_NOTIFICATION_DATA,
SBI_NOTIFY_SUBSCRIBED_EVENT,
......
......@@ -225,4 +225,19 @@ class itti_sbi_amf_configuration : public itti_sbi_msg {
uint32_t promise_id;
};
//-----------------------------------------------------------------------------
class itti_sbi_update_amf_configuration : public itti_sbi_msg {
public:
itti_sbi_update_amf_configuration(
const task_id_t orig, const task_id_t dest, uint32_t pid)
: itti_sbi_msg(SBI_UPDATE_AMF_CONFIGURATION, orig, dest),
http_version(1),
promise_id(pid) {}
const char* get_msg_name() { return "SBI_UPDATE_AMF_CONFIGURATION"; };
uint8_t http_version;
uint32_t promise_id;
nlohmann::json configuration;
};
#endif /* ITTI_MSG_SBI_HPP_INCLUDED_ */
......@@ -45,7 +45,11 @@ void AMFConfigurationApi::setupRoutes() {
*router, base + amf_cfg.sbi_api_version + "/configuration/",
Routes::bind(&AMFConfigurationApi::read_configuration_handler, this));
Routes::PUT(
Routes::Put(
*router, base + amf_cfg.sbi_api_version + "/configuration/",
Routes::bind(&AMFConfigurationApi::update_configuration_handler, this));
Routes::Put(
*router, base + amf_cfg.sbi_api_version + "/configuration/nssai",
Routes::bind(&AMFConfigurationApi::create_nssai_handler, this));
......@@ -73,6 +77,46 @@ void AMFConfigurationApi::read_configuration_handler(
}
}
void AMFConfigurationApi::update_configuration_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response) {
try {
auto configuration_info = nlohmann::json::parse(request.body());
this->update_configuration(configuration_info, response);
} catch (nlohmann::detail::exception& e) {
// send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (Pistache::Http::HttpError& e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception& e) {
// send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void AMFConfigurationApi::create_nssai_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response) {
try {
auto json_data = nlohmann::json::parse(request.body());
this->create_nssai(json_data, response);
} catch (nlohmann::detail::exception& e) {
// send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (Pistache::Http::HttpError& e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception& e) {
// send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void AMFConfigurationApi::configuration_api_default_handler(
const Pistache::Rest::Request&, Pistache::Http::ResponseWriter response) {
response.send(
......
......@@ -27,6 +27,8 @@
#include <pistache/optional.h>
#include <pistache/router.h>
#include <nlohmann/json.hpp>
namespace oai::amf::api {
class AMFConfigurationApi {
......@@ -43,6 +45,12 @@ class AMFConfigurationApi {
void read_configuration_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response);
void update_configuration_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response);
void create_nssai_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response);
void configuration_api_default_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response);
......@@ -50,6 +58,11 @@ class AMFConfigurationApi {
std::shared_ptr<Pistache::Rest::Router> router;
virtual void read_configuration(Pistache::Http::ResponseWriter& response) = 0;
virtual void update_configuration(
nlohmann::json& configuration_info,
Pistache::Http::ResponseWriter& response) = 0;
virtual void create_nssai(
nlohmann::json& json_data, Pistache::Http::ResponseWriter& response) = 0;
};
} // namespace oai::amf::api
......
......@@ -102,4 +102,78 @@ void AMFConfigurationApiImpl::read_configuration(
}
}
void AMFConfigurationApiImpl::update_configuration(
nlohmann::json& configuration_info,
Pistache::Http::ResponseWriter& response) {
Logger::amf_server().debug("Update AMFConfiguration, handling...");
// Generate a promise and associate this promise to the ITTI message
uint32_t promise_id = m_amf_app->generate_promise_id();
Logger::amf_n1().debug("Promise ID generated %d", promise_id);
boost::shared_ptr<boost::promise<nlohmann::json>> p =
boost::make_shared<boost::promise<nlohmann::json>>();
boost::shared_future<nlohmann::json> f = p->get_future();
m_amf_app->add_promise(promise_id, p);
// Handle the AMFConfiguration in amf_app
std::shared_ptr<itti_sbi_update_amf_configuration> itti_msg =
std::make_shared<itti_sbi_update_amf_configuration>(
TASK_AMF_SBI, TASK_AMF_APP, promise_id);
itti_msg->http_version = 1;
itti_msg->promise_id = promise_id;
itti_msg->configuration = configuration_info;
int ret = itti_inst->send_msg(itti_msg);
if (0 != ret) {
Logger::amf_server().error(
"Could not send ITTI message %s to task TASK_AMF_APP",
itti_msg->get_msg_name());
}
boost::future_status status;
// wait for timeout or ready
status = f.wait_for(boost::chrono::milliseconds(FUTURE_STATUS_TIMEOUT_MS));
if (status == boost::future_status::ready) {
assert(f.is_ready());
assert(f.has_value());
assert(!f.has_exception());
// Wait for the result from APP
// result includes json content and http response code
nlohmann::json result = f.get();
Logger::amf_server().debug("Got result for promise ID %d", promise_id);
// process data
uint32_t http_response_code = 0;
nlohmann::json json_data = {};
if (result.find("httpResponseCode") != result.end()) {
http_response_code = result["httpResponseCode"].get<int>();
}
if (http_response_code == 200) {
if (result.find("content") != result.end()) {
json_data = result["content"];
}
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType("application/json"));
response.send(Pistache::Http::Code::Ok, json_data.dump().c_str());
} else {
// Problem details
if (result.find("ProblemDetails") != result.end()) {
json_data = result["ProblemDetails"];
}
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType("application/problem+json"));
response.send(
Pistache::Http::Code(http_response_code), json_data.dump().c_str());
}
}
}
void AMFConfigurationApiImpl::create_nssai(
nlohmann::json& json_data, Pistache::Http::ResponseWriter& response) {}
} // namespace oai::amf::api
......@@ -41,6 +41,11 @@ class AMFConfigurationApiImpl : public oai::amf::api::AMFConfigurationApi {
~AMFConfigurationApiImpl() {}
void read_configuration(Pistache::Http::ResponseWriter& response);
void update_configuration(
nlohmann::json& configuration_info,
Pistache::Http::ResponseWriter& response);
void create_nssai(
nlohmann::json& json_data, Pistache::Http::ResponseWriter& response);
};
} // namespace oai::amf::api
......
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