Commit 508b7d51 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'amf_configuration_nssai' into 'develop'

Amf configuration nssai

See merge request oai/cn5g/oai-cn5g-amf!129
parents 3c6b0792 6d9342a0
......@@ -88,7 +88,10 @@ amf_app::amf_app(const amf_config& amf_cfg)
throw;
}
// Generate an AMF profile (including NF instance)
// Generate NF Instance ID (UUID)
generate_uuid();
// Generate an AMF profile
generate_amf_profile();
// Register to NRF if needed
......@@ -152,12 +155,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 +743,73 @@ 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"] = itti_msg.configuration;
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:
// Update AMF profile
generate_amf_profile();
// Update AMF profile (complete replacement of the existing profile by a new
// one)
if (amf_cfg.support_features.enable_nf_registration and
amf_cfg.support_features.enable_external_nrf)
register_to_nrf();
} 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) {
if (stacs.get_number_connected_gnbs() > 0) {
Logger::amf_app().info(
"Could not update AMF configuration (connected with gNBs)");
return false;
}
return amf_cfg.from_json(json_data);
}
//---------------------------------------------------------------------------------------------
void amf_app::get_number_registered_ues(uint32_t& num_ues) const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
num_ues = amf_ue_ngap_id2ue_ctx.size();
return;
}
//---------------------------------------------------------------------------------------------
uint32_t amf_app::get_number_registered_ues() const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
return amf_ue_ngap_id2ue_ctx.size();
}
//---------------------------------------------------------------------------------------------
void amf_app::add_n1n2_message_subscription(
const std::string& ue_ctx_id, const n1n2sub_id_t& sub_id,
......@@ -939,15 +1010,14 @@ void amf_app::get_ee_subscriptions(
//---------------------------------------------------------------------------------------------
void amf_app::generate_amf_profile() {
// generate UUID
generate_uuid();
nf_instance_profile.set_nf_instance_id(amf_instance_id);
nf_instance_profile.set_nf_instance_name("OAI-AMF");
nf_instance_profile.set_nf_instance_name(amf_cfg.amf_name);
nf_instance_profile.set_nf_type("AMF");
nf_instance_profile.set_nf_status("REGISTERED");
nf_instance_profile.set_nf_heartBeat_timer(50);
nf_instance_profile.set_nf_priority(1);
nf_instance_profile.set_nf_capacity(100);
nf_instance_profile.delete_nf_ipv4_addresses();
nf_instance_profile.add_nf_ipv4_addresses(amf_cfg.n11.addr4);
// NF services
......@@ -955,7 +1025,7 @@ void amf_app::generate_amf_profile() {
nf_service.service_instance_id = "namf_communication";
nf_service.service_name = "namf_communication";
nf_service_version_t version = {};
version.api_version_in_uri = "v1";
version.api_version_in_uri = amf_cfg.sbi_api_version;
version.api_full_version = "1.0.0"; // TODO: to be updated
nf_service.versions.push_back(version);
nf_service.scheme = "http";
......@@ -967,6 +1037,7 @@ void amf_app::generate_amf_profile() {
endpoint.port = amf_cfg.n11.port;
nf_service.ip_endpoints.push_back(endpoint);
nf_instance_profile.delete_nf_services();
nf_instance_profile.add_nf_service(nf_service);
// TODO: custom info
......
......@@ -159,8 +159,41 @@ 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);
/*
* Get the current AMF's configuration
* @param [nlohmann::json&]: json_data: Store AMF configuration
* @return true if success, otherwise return false
*/
bool read_amf_configuration(nlohmann::json& json_data);
/*
* Update AMF configuration
* @param [nlohmann::json&]: json_data: New AMF configuration
* @return true if success, otherwise return false
*/
bool update_amf_configuration(nlohmann::json& json_data);
/*
* Get number of registered UEs to this AMF
* @param [uint32_t&]: num_ues: Store the number of registered UEs
* @return void
*/
void get_number_registered_ues(uint32_t& num_ues) const;
/*
* Get number of registered UEs to this AMF
* @param void
* @return: number of registered UEs
*/
uint32_t get_number_registered_ues() const;
/*
* Verify if a UE context associated with an AMF UE NGAP ID exist
* @param [const long&] amf_ue_ngap_id: AMF UE NGAP ID
......
......@@ -78,7 +78,7 @@ amf_config::amf_config() {
statistics_interval = 0;
guami = {};
guami_list = {};
relativeAMFCapacity = 0;
relative_amf_capacity = 0;
plmn_list = {};
auth_conf auth_para = {};
nas_cfg = {};
......@@ -158,7 +158,7 @@ int amf_config::load(const std::string& config_file) {
// AMF Name
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_AMF_NAME, AMF_Name);
amf_cfg.lookupValue(AMF_CONFIG_STRING_AMF_NAME, amf_name);
} catch (const SettingNotFoundException& nfex) {
Logger::amf_app().error(
"%s : %s, using defaults", nfex.what(), nfex.getPath());
......@@ -200,7 +200,7 @@ int amf_config::load(const std::string& config_file) {
// AMF Capacity
try {
amf_cfg.lookupValue(
AMF_CONFIG_STRING_RELATIVE_AMF_CAPACITY, relativeAMFCapacity);
AMF_CONFIG_STRING_RELATIVE_AMF_CAPACITY, relative_amf_capacity);
} catch (const SettingNotFoundException& nfex) {
Logger::amf_app().error(
"%s : %s, using defaults", nfex.what(), nfex.getPath());
......@@ -375,6 +375,9 @@ int amf_config::load(const std::string& config_file) {
std::string smf_api_version = {};
std::string selected = {};
// Store FQDN
smf_addr_item.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, smf_inst.fqdn);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_ID, smf_inst.id);
if (!support_features.use_fqdn_dns) {
smf_addr_item.lookupValue(
......@@ -401,9 +404,7 @@ int amf_config::load(const std::string& config_file) {
throw(AMF_CONFIG_STRING_SMF_INSTANCE_VERSION "failed");
}
} else {
std::string smf_fqdn = {};
smf_addr_item.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, smf_fqdn);
smf_inst.fqdn = smf_fqdn;
smf_addr_item.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, smf_inst.fqdn);
}
smf_addr_item.lookupValue(
......@@ -423,6 +424,9 @@ int amf_config::load(const std::string& config_file) {
string address = {};
if (!support_features.use_fqdn_dns) {
// Store FQDN
nrf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nrf_addr.fqdn);
nrf_cfg.lookupValue(AMF_CONFIG_STRING_NRF_IPV4_ADDRESS, address);
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nrf_ipv4_addr,
......@@ -440,10 +444,9 @@ int amf_config::load(const std::string& config_file) {
}
nrf_addr.api_version = nrf_api_version;
} else {
std::string nrf_fqdn = {};
nrf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nrf_fqdn);
nrf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nrf_addr.fqdn);
uint8_t addr_type = {};
fqdn::resolve(nrf_fqdn, address, nrf_port, addr_type);
fqdn::resolve(nrf_addr.fqdn, address, nrf_port, addr_type);
if (addr_type != 0) { // IPv6: TODO
throw("DO NOT SUPPORT IPV6 ADDR FOR NRF!");
} else { // IPv4
......@@ -472,6 +475,9 @@ int amf_config::load(const std::string& config_file) {
std::string ausf_api_version = {};
if (!support_features.use_fqdn_dns) {
// Store FQDN
ausf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, ausf_addr.fqdn);
ausf_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), ausf_ipv4_addr,
......@@ -490,10 +496,9 @@ int amf_config::load(const std::string& config_file) {
}
ausf_addr.api_version = ausf_api_version;
} else {
std::string ausf_fqdn = {};
ausf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, ausf_fqdn);
ausf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, ausf_addr.fqdn);
uint8_t addr_type = {};
fqdn::resolve(ausf_fqdn, address, ausf_port, addr_type);
fqdn::resolve(ausf_addr.fqdn, address, ausf_port, addr_type);
if (addr_type != 0) { // IPv6: TODO
throw("DO NOT SUPPORT IPV6 ADDR FOR AUSF!");
} else { // IPv4
......@@ -520,6 +525,9 @@ int amf_config::load(const std::string& config_file) {
std::string udm_api_version = {};
if (!support_features.use_fqdn_dns) {
// Store FQDN
udm_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, udm_addr.fqdn);
udm_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), udm_ipv4_addr,
......@@ -538,10 +546,9 @@ int amf_config::load(const std::string& config_file) {
}
udm_addr.api_version = udm_api_version;
} else {
std::string udm_fqdn = {};
udm_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, udm_fqdn);
udm_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, udm_addr.fqdn);
uint8_t addr_type = {};
fqdn::resolve(udm_fqdn, address, udm_port, addr_type);
fqdn::resolve(udm_addr.fqdn, address, udm_port, addr_type);
if (addr_type != 0) { // IPv6: TODO
throw("DO NOT SUPPORT IPV6 ADDR FOR UDM!");
} else { // IPv4
......@@ -563,6 +570,8 @@ int amf_config::load(const std::string& config_file) {
std::string nssf_api_version = {};
if (!support_features.use_fqdn_dns) {
// Store FQDN
nssf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nssf_addr.fqdn);
nssf_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nssf_ipv4_addr,
......@@ -581,10 +590,9 @@ int amf_config::load(const std::string& config_file) {
}
nssf_addr.api_version = nssf_api_version;
} else {
std::string nssf_fqdn = {};
nssf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nssf_fqdn);
nssf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nssf_addr.fqdn);
uint8_t addr_type = {};
fqdn::resolve(nssf_fqdn, address, nssf_port, addr_type);
fqdn::resolve(nssf_addr.fqdn, address, nssf_port, addr_type);
if (addr_type != 0) { // IPv6: TODO
throw("DO NOT SUPPORT IPV6 ADDR FOR NSSF!");
} else { // IPv4
......@@ -682,7 +690,7 @@ void amf_config::display() {
Logger::config().info("Configuration AMF:");
Logger::config().info("- Instance ................: %d", instance);
Logger::config().info("- PID dir .................: %s", pid_dir.c_str());
Logger::config().info("- AMF NAME.................: %s", AMF_Name.c_str());
Logger::config().info("- AMF NAME.................: %s", amf_name.c_str());
Logger::config().info(
"- GUAMI (MCC, MNC, Region ID, AMF Set ID, AMF pointer): ");
Logger::config().info(
......@@ -695,7 +703,8 @@ void amf_config::display() {
guami_list[i].mnc.c_str(), guami_list[i].regionID.c_str(),
guami_list[i].AmfSetID.c_str(), guami_list[i].AmfPointer.c_str());
}
Logger::config().info("- Relative Capacity .......: %d", relativeAMFCapacity);
Logger::config().info(
"- Relative Capacity .......: %d", relative_amf_capacity);
Logger::config().info("- PLMN Support: ");
for (int i = 0; i < plmn_list.size(); i++) {
Logger::config().info(
......@@ -707,12 +716,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());
......@@ -721,7 +734,7 @@ void amf_config::display() {
Logger::config().info(
"- Emergency Support .......: %s", is_emergency_support.c_str());
Logger::config().info("- Database : ");
Logger::config().info("- Database: ");
Logger::config().info(
" MySQL Server Addr .....: %s", auth_para.mysql_server.c_str());
Logger::config().info(
......@@ -731,6 +744,19 @@ void amf_config::display() {
Logger::config().info(
" MySQL DB ..............: %s", auth_para.mysql_db.c_str());
// TODO:
/*
Logger::config().info("- Supported NAS Algorithm: ");
Logger::config().info(
" Integrity Algorithm ...: %s","");
Logger::config().info(
" Ciphering Algorithm ...: %s", "");
st::string nas_itegrity_algorithm_list = {};
for(auto s: nas_cfg.prefered_integrity_algorithm){
}
*/
Logger::config().info("- N2 Networking:");
Logger::config().info(" Iface .................: %s", n2.if_name.c_str());
Logger::config().info(" IP Addr ...............: %s", inet_ntoa(n2.addr4));
......@@ -871,6 +897,26 @@ int amf_config::load_interface(
return RETURNok;
}
//------------------------------------------------------------------------------
bool amf_config::resolve_fqdn(
const std::string& fqdn, struct in_addr& ipv4_addr) {
uint8_t addr_type = {};
unsigned int port = 0;
string address = {};
fqdn::resolve(fqdn, address, port, addr_type);
if (addr_type != 0) { // IPv6: TODO
Logger::amf_app().error("DO NOT SUPPORT IPV6 ADDR FOR THIS NF");
return false;
} else { // IPv4
if (inet_aton(util::trim(address).c_str(), &ipv4_addr) <= 0) return false;
// IPV4_STR_ADDR_TO_INADDR(
// util::trim(address).c_str(), ipv4_addr,
// "BAD IPv4 ADDRESS FORMAT FOR NF !");
}
return true;
}
//------------------------------------------------------------------------------
std::string amf_config::get_amf_n1n2_message_subscribe_uri(
const std::string& ue_cxt_id) {
......@@ -926,14 +972,14 @@ std::string amf_config::get_ausf_ue_authentications_uri() {
void amf_config::to_json(nlohmann::json& json_data) const {
json_data["instance"] = instance;
json_data["pid_dir"] = pid_dir;
json_data["amf_name"] = AMF_Name; // TODO: amf_name
json_data["amf_name"] = amf_name;
json_data["guami"] = guami.to_json();
json_data["guami_list"] = nlohmann::json::array();
for (auto s : guami_list) {
json_data["guami_list"].push_back(s.to_json());
}
json_data["relativeAMFCapacity"] = relativeAMFCapacity;
json_data["relative_amf_capacity"] = relative_amf_capacity;
json_data["plmn_list"] = nlohmann::json::array();
for (auto s : plmn_list) {
......@@ -954,15 +1000,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 +1016,135 @@ 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()) {
guami_list.clear();
for (auto s : json_data["guami_list"]) {
guami_t g = {};
g.from_json(s);
guami_list.push_back(g);
}
}
if (json_data.find("relative_amf_capacity") != json_data.end()) {
relative_amf_capacity = json_data["relative_amf_capacity"].get<int>();
}
if (json_data.find("plmn_list") != json_data.end()) {
plmn_list.clear();
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("auth_para") != 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()) {
n11.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 use FQDN -> update IP addr accordingly
if (support_features.use_fqdn_dns) {
resolve_fqdn(nrf_addr.fqdn, nrf_addr.ipv4_addr);
}
}
}
if (support_features.enable_external_nssf) {
if (json_data.find("nssf") != json_data.end()) {
nssf_addr.from_json(json_data["nssf"]);
// if use FQDN -> update IP addr accordingly
if (support_features.use_fqdn_dns) {
resolve_fqdn(nssf_addr.fqdn, nssf_addr.ipv4_addr);
}
}
}
if (support_features.enable_external_ausf) {
if (json_data.find("ausf") != json_data.end()) {
ausf_addr.from_json(json_data["ausf"]);
// if use FQDN -> update IP addr accordingly
if (support_features.use_fqdn_dns) {
resolve_fqdn(ausf_addr.fqdn, ausf_addr.ipv4_addr);
}
}
}
if (support_features.enable_external_udm) {
if (json_data.find("udm") != json_data.end()) {
udm_addr.from_json(json_data["udm"]);
// if use FQDN -> update IP addr accordingly
if (support_features.use_fqdn_dns) {
resolve_fqdn(udm_addr.fqdn, udm_addr.ipv4_addr);
}
}
}
if (json_data.find("smf_pool") != json_data.end()) {
smf_pool.clear();
for (auto s : json_data["smf_pool"]) {
smf_inst_t smf_item = {};
struct in_addr ipv4_addr = {};
smf_item.from_json(s);
// if use FQDN -> update IP addr accordingly
if (support_features.use_fqdn_dns) {
resolve_fqdn(smf_item.fqdn, ipv4_addr);
smf_item.ipv4 = inet_ntoa(ipv4_addr);
}
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,19 @@ 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>();
for (auto s : json_data["slice_list"]) {
slice_t sl = {};
sl.from_json(s);
slice_list.push_back(sl);
}
}
} plmn_item_t;
typedef struct {
......@@ -238,14 +305,29 @@ typedef struct {
nlohmann::json json_data = {};
json_data["prefered_integrity_algorithm"] = nlohmann::json::array();
json_data["prefered_ciphering_algorithm"] = nlohmann::json::array();
for (auto s : prefered_integrity_algorithm) {
for (auto s : this->prefered_integrity_algorithm) {
json_data["prefered_integrity_algorithm"].push_back(s);
}
for (auto s : prefered_ciphering_algorithm) {
for (auto s : this->prefered_ciphering_algorithm) {
json_data["prefered_ciphering_algorithm"].push_back(s);
}
return json_data;
}
/*
void from_json(nlohmann::json& json_data) {
uint8_t i = 0;
for (auto s : json_data["prefered_integrity_algorithm"]) {
uint8_t integ_alg = s.get<int>();
prefered_integrity_algorithm[i] = integ_alg;
++i;
}
i = 0;
for (auto s : json_data["prefered_ciphering_algorithm"]) {
uint8_t cipher_alg = s.get<int>();
prefered_ciphering_algorithm[i] = cipher_alg;
++i;
}
}*/
} nas_conf_t;
typedef struct {
......@@ -269,20 +351,44 @@ 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 {
struct in_addr ipv4_addr;
unsigned int port;
std::string api_version;
std::string fqdn;
nlohmann::json to_json() const {
nlohmann::json json_data = {};
json_data["ipv4_addr"] = inet_ntoa(this->ipv4_addr);
json_data["port"] = this->port;
json_data["api_version"] = this->api_version;
json_data["fqdn"] = this->fqdn;
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>();
this->fqdn = json_data["fqdn"].get<std::string>();
}
} nf_addr_t;
class amf_config {
......@@ -305,6 +411,8 @@ class amf_config {
*/
int load_interface(const Setting& if_cfg, interface_cfg_t& cfg);
bool resolve_fqdn(const std::string& fqdn, struct in_addr& ipv4_addr);
/*
* Get the URI of AMF N1N2MessageSubscribe
* @param [const std::string&] ue_cxt_id: UE Context Id
......@@ -362,6 +470,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;
......@@ -371,10 +486,10 @@ class amf_config {
unsigned int sbi_http2_port;
unsigned int statistics_interval;
std::string AMF_Name;
std::string amf_name;
guami_t guami;
std::vector<guami_t> guami_list;
unsigned int relativeAMFCapacity;
unsigned int relative_amf_capacity;
std::vector<plmn_item_t> plmn_list;
std::string is_emergency_support;
auth_conf auth_para;
......@@ -404,6 +519,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;
......
......@@ -420,7 +420,7 @@ void amf_n2::handle_itti_message(itti_ng_setup_request& itti_msg) {
// file and send_msg
uint8_t* buffer = (uint8_t*) calloc(1, BUFFER_SIZE_1024);
NGSetupResponseMsg ngSetupResp;
ngSetupResp.setAMFName(amf_cfg.AMF_Name);
ngSetupResp.setAMFName(amf_cfg.amf_name);
std::vector<struct GuamiItem_s> guami_list;
for (int i = 0; i < amf_cfg.guami_list.size(); i++) {
struct GuamiItem_s tmp;
......@@ -433,7 +433,7 @@ void amf_n2::handle_itti_message(itti_ng_setup_request& itti_msg) {
}
ngSetupResp.setGUAMIList(guami_list);
ngSetupResp.setRelativeAmfCapacity(amf_cfg.relativeAMFCapacity);
ngSetupResp.setRelativeAmfCapacity(amf_cfg.relative_amf_capacity);
std::vector<PlmnSliceSupport_t> plmn_list;
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) {
PlmnSliceSupport_t tmp;
......
......@@ -151,6 +151,7 @@ void nf_profile::get_nf_snssais(std::vector<snssai_t>& s) const {
void nf_profile::add_snssai(const snssai_t& s) {
snssais.push_back(s);
}
//------------------------------------------------------------------------------
void nf_profile::set_nf_ipv4_addresses(const std::vector<struct in_addr>& a) {
ipv4_addresses = a;
......@@ -165,6 +166,10 @@ void nf_profile::get_nf_ipv4_addresses(std::vector<struct in_addr>& a) const {
a = ipv4_addresses;
}
//------------------------------------------------------------------------------
void nf_profile::delete_nf_ipv4_addresses() {
ipv4_addresses.clear();
}
//------------------------------------------------------------------------------
void nf_profile::display() const {
Logger::amf_app().debug("NF instance info");
......@@ -296,6 +301,11 @@ void amf_profile::get_nf_services(std::vector<nf_service_t>& n) const {
n = nf_services;
}
//------------------------------------------------------------------------------
void amf_profile::delete_nf_services() {
nf_services.clear();
}
//------------------------------------------------------------------------------
void amf_profile::set_custom_info(const nlohmann::json& c) {
custom_info = c;
......
......@@ -267,6 +267,12 @@ class nf_profile : public std::enable_shared_from_this<nf_profile> {
*/
void get_nf_ipv4_addresses(std::vector<struct in_addr>& a) const;
/*
* Remove all NF instance ipv4_addresses
* @param void
* @return void:
*/
void delete_nf_ipv4_addresses();
/*
* Print related-information for NF profile
* @param void
......@@ -349,6 +355,12 @@ class amf_profile : public nf_profile {
*/
void get_nf_services(std::vector<nf_service_t>& n) const;
/*
* Delete all NF services
* @param void
* @return void:
*/
void delete_nf_services();
/*
* Set custom info
* @param [const nlohmann::json &] c: custom info to be set
......
......@@ -163,3 +163,9 @@ void statistics::update_gnb(const uint32_t& gnb_id, const gnb_infos& gnb) {
gnbs[gnb_id] = gnb;
}
}
//------------------------------------------------------------------------------
uint32_t statistics::get_number_connected_gnbs() const {
std::shared_lock lock(m_gnbs);
return gnbs.size();
}
......@@ -124,6 +124,13 @@ class statistics {
*/
void update_gnb(const uint32_t& gnb_id, const gnb_infos& gnb);
/*
* Get number of connected gNBs
* @param void
* @return number of connected gNBs
*/
uint32_t get_number_connected_gnbs() const;
public:
uint32_t gNB_connected;
uint32_t UE_connected;
......
......@@ -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_ */
......@@ -29,6 +29,9 @@
#ifndef _3GPP_TS_24501_H_
#define _3GPP_TS_24501_H_
#include <string>
#include <vector>
/********** epd type **************/
#define EPD_5GS_MM_MSG 0b01111110
......@@ -129,6 +132,10 @@
#define EA1_128_5G 0b001
#define EA2_128_5G 0b010
static const std::vector<std::string> nas_itegrity_algorithm_list_e2str = {
"NIA0", "NIA1", "NIA2"};
static const std::vector<std::string> nas_ciphering_algorithm_list_e2str = {
"NEA0", "NEA1", "NEA2"};
/************************** cause value for 5g mobility management(Annex A)
* ********************************/
#define _5GMM_CAUSE_ILLEGAL_UE 3
......
......@@ -45,6 +45,10 @@ void AMFConfigurationApi::setupRoutes() {
*router, base + amf_cfg.sbi_api_version + "/configuration/",
Routes::bind(&AMFConfigurationApi::read_configuration_handler, this));
Routes::Put(
*router, base + amf_cfg.sbi_api_version + "/configuration/",
Routes::bind(&AMFConfigurationApi::update_configuration_handler, this));
// Default handler, called when a route is not found
router->addCustomHandler(Routes::bind(
&AMFConfigurationApi::configuration_api_default_handler, this));
......@@ -69,6 +73,26 @@ 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::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,9 @@ 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 configuration_api_default_handler(
const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response);
......@@ -50,6 +55,9 @@ 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;
};
} // namespace oai::amf::api
......
......@@ -102,4 +102,75 @@ 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());
}
}
}
} // namespace oai::amf::api
......@@ -41,6 +41,9 @@ 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);
};
} // 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