Commit 31c75155 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'nrf-selection' into 'develop'

NRF Selection

See merge request oai/cn5g/oai-cn5g-amf!64
parents c0f30330 7b0cdfb1
...@@ -85,6 +85,10 @@ services: ...@@ -85,6 +85,10 @@ services:
- AUSF_PORT=80 - AUSF_PORT=80
- AUSF_API_VERSION=v1 - AUSF_API_VERSION=v1
- AUSF_FQDN=localhost - AUSF_FQDN=localhost
- NSSF_IPV4_ADDRESS=0.0.0.0
- NSSF_PORT=80
- NSSF_API_VERSION=v1
- NSSF_FQDN=localhost
depends_on: depends_on:
- cicd_mysql - cicd_mysql
networks: networks:
......
...@@ -96,13 +96,21 @@ AMF = ...@@ -96,13 +96,21 @@ AMF =
API_VERSION = "@AUSF_API_VERSION@"; # YOUR AUSF API VERSION FOR SBI CONFIG HERE API_VERSION = "@AUSF_API_VERSION@"; # YOUR AUSF API VERSION FOR SBI CONFIG HERE
FQDN = "@AUSF_FQDN@" # YOUR AUSF FQDN CONFIG HERE FQDN = "@AUSF_FQDN@" # YOUR AUSF FQDN CONFIG HERE
}; };
NSSF :
{
IPV4_ADDRESS = "@NSSF_IPV4_ADDRESS@"; # YOUR NSSF CONFIG HERE
PORT = @NSSF_PORT@; # YOUR NSSF CONFIG HERE (default: 80)
API_VERSION = "@NSSF_API_VERSION@"; # YOUR NSSF API VERSION FOR SBI CONFIG HERE
FQDN = "@NSSF_FQDN@" # YOUR NSSF FQDN CONFIG HERE
};
}; };
SUPPORT_FEATURES: SUPPORT_FEATURES:
{ {
# STRING, {"yes", "no"}, # STRING, {"yes", "no"},
NF_REGISTRATION = "@NF_REGISTRATION@"; # Set to yes if AMF resgisters to an NRF NF_REGISTRATION = "@NF_REGISTRATION@"; # Set to yes if AMF resgisters to an NRF
NRF_SELECTION = "@NRF_SELECTION@"; # Set to yes to enable NRF discovery and selection
SMF_SELECTION = "@SMF_SELECTION@"; # Set to yes to enable SMF discovery and selection SMF_SELECTION = "@SMF_SELECTION@"; # Set to yes to enable SMF discovery and selection
EXTERNAL_AUSF = "@EXTERNAL_AUSF@"; # Set to yes if AMF works with an external AUSF EXTERNAL_AUSF = "@EXTERNAL_AUSF@"; # Set to yes if AMF works with an external AUSF
EXTERNAL_UDM = "@EXTERNAL_UDM@"; # Set to yes if AMF works with an external UDM EXTERNAL_UDM = "@EXTERNAL_UDM@"; # Set to yes if AMF works with an external UDM
......
...@@ -7,7 +7,14 @@ CONFIG_DIR="/openair-amf/etc" ...@@ -7,7 +7,14 @@ CONFIG_DIR="/openair-amf/etc"
# Default values # Default values
EXTERNAL_AUSF=${EXTERNAL_AUSF:-no} EXTERNAL_AUSF=${EXTERNAL_AUSF:-no}
EXTERNAL_UDM=${EXTERNAL_UDM:-no} EXTERNAL_UDM=${EXTERNAL_UDM:-no}
NRF_SELECTION=${NRF_SELECTION:-no}
NSSF_IPV4_ADDRESS=${NSSF_IPV4_ADDRESS:-0.0.0.0}
NSSF_PORT=${NSSF_PORT:-80}
NSSF_API_VERSION=${NSSF_API_VERSION:-v2}
NSSF_FQDN=${NSSF_FQDN:-oai-nssf}
if [[ ${USE_FQDN_DNS} == "yes" ]];then if [[ ${USE_FQDN_DNS} == "yes" ]];then
NSSF_IPV4_ADDR=${NSSF_IPV4_ADDR_0:-0.0.0.0}
SMF_IPV4_ADDR_0=${SMF_IPV4_ADDR_0:-0.0.0.0} SMF_IPV4_ADDR_0=${SMF_IPV4_ADDR_0:-0.0.0.0}
SMF_IPV4_ADDR_1=${SMF_IPV4_ADDR_1:-0.0.0.0} SMF_IPV4_ADDR_1=${SMF_IPV4_ADDR_1:-0.0.0.0}
NRF_IPV4_ADDRESS=${NRF_IPV4_ADDRESS:-0.0.0.0} NRF_IPV4_ADDRESS=${NRF_IPV4_ADDRESS:-0.0.0.0}
......
...@@ -78,6 +78,7 @@ amf_config::amf_config() { ...@@ -78,6 +78,7 @@ amf_config::amf_config() {
nas_cfg = {}; nas_cfg = {};
smf_pool = {}; smf_pool = {};
support_features.enable_nf_registration = false; support_features.enable_nf_registration = false;
support_features.enable_nrf_selection = false;
support_features.enable_smf_selection = false; support_features.enable_smf_selection = false;
support_features.enable_external_ausf = false; support_features.enable_external_ausf = false;
support_features.enable_external_udm = false; support_features.enable_external_udm = false;
...@@ -237,6 +238,14 @@ int amf_config::load(const std::string& config_file) { ...@@ -237,6 +238,14 @@ int amf_config::load(const std::string& config_file) {
support_features.enable_nf_registration = false; support_features.enable_nf_registration = false;
} }
support_features_cfg.lookupValue(
AMF_CONFIG_STRING_SUPPORT_FEATURES_NRF_SELECTION, opt);
if (boost::iequals(opt, "yes")) {
support_features.enable_nrf_selection = true;
} else {
support_features.enable_nrf_selection = false;
}
support_features_cfg.lookupValue( support_features_cfg.lookupValue(
AMF_CONFIG_STRING_SUPPORT_FEATURES_SMF_SELECTION, opt); AMF_CONFIG_STRING_SUPPORT_FEATURES_SMF_SELECTION, opt);
if (boost::iequals(opt, "yes")) { if (boost::iequals(opt, "yes")) {
...@@ -456,6 +465,48 @@ int amf_config::load(const std::string& config_file) { ...@@ -456,6 +465,48 @@ int amf_config::load(const std::string& config_file) {
} }
} }
// NSSF
if (support_features.enable_nrf_selection) {
const Setting& nssf_cfg = new_if_cfg[AMF_CONFIG_STRING_NSSF];
struct in_addr nssf_ipv4_addr = {};
unsigned int nssf_port = {};
std::string nssf_api_version = {};
if (!support_features.use_fqdn_dns) {
nssf_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nssf_ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR NSSF !");
nssf_addr.ipv4_addr = nssf_ipv4_addr;
if (!(nssf_cfg.lookupValue(AMF_CONFIG_STRING_PORT, nssf_port))) {
Logger::amf_app().error(AMF_CONFIG_STRING_PORT "failed");
throw(AMF_CONFIG_STRING_PORT "failed");
}
nssf_addr.port = nssf_port;
if (!(nssf_cfg.lookupValue(
AMF_CONFIG_STRING_API_VERSION, nssf_api_version))) {
Logger::amf_app().error(AMF_CONFIG_STRING_API_VERSION "failed");
throw(AMF_CONFIG_STRING_API_VERSION "failed");
}
nssf_addr.api_version = nssf_api_version;
} else {
std::string nssf_fqdn = {};
nssf_cfg.lookupValue(AMF_CONFIG_STRING_FQDN_DNS, nssf_fqdn);
uint8_t addr_type = {};
fqdn::resolve(nssf_fqdn, address, nssf_port, addr_type);
if (addr_type != 0) { // IPv6: TODO
throw("DO NOT SUPPORT IPV6 ADDR FOR NSSF!");
} else { // IPv4
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nssf_ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR NSSF !");
nssf_addr.ipv4_addr = nssf_ipv4_addr;
nssf_addr.port = nssf_port;
nssf_addr.api_version = "v1"; // TODO: get API version
}
}
}
} catch (const SettingNotFoundException& nfex) { } catch (const SettingNotFoundException& nfex) {
Logger::amf_app().error( Logger::amf_app().error(
"%s : %s, using defaults", nfex.what(), nfex.getPath()); "%s : %s, using defaults", nfex.what(), nfex.getPath());
...@@ -607,6 +658,15 @@ void amf_config::display() { ...@@ -607,6 +658,15 @@ void amf_config::display() {
" API version ...........: %s", nrf_addr.api_version.c_str()); " API version ...........: %s", nrf_addr.api_version.c_str());
} }
if (support_features.enable_nrf_selection) {
Logger::config().info("- NSSF:");
Logger::config().info(
" IP Addr ...............: %s", inet_ntoa(nssf_addr.ipv4_addr));
Logger::config().info(" Port ..................: %d", nssf_addr.port);
Logger::config().info(
" API version ...........: %s", nssf_addr.api_version.c_str());
}
if (support_features.enable_external_ausf) { if (support_features.enable_external_ausf) {
Logger::config().info("- AUSF:"); Logger::config().info("- AUSF:");
Logger::config().info( Logger::config().info(
...@@ -634,6 +694,9 @@ void amf_config::display() { ...@@ -634,6 +694,9 @@ void amf_config::display() {
Logger::config().info( Logger::config().info(
" NF Registration .......: %s", " NF Registration .......: %s",
support_features.enable_nf_registration ? "Yes" : "No"); support_features.enable_nf_registration ? "Yes" : "No");
Logger::config().info(
" NRF Selection .........: %s",
support_features.enable_nrf_selection ? "Yes" : "No");
Logger::config().info( Logger::config().info(
" SMF Selection .........: %s", " SMF Selection .........: %s",
support_features.enable_smf_selection ? "Yes" : "No"); support_features.enable_smf_selection ? "Yes" : "No");
......
...@@ -67,6 +67,8 @@ ...@@ -67,6 +67,8 @@
#define AMF_CONFIG_STRING_AUSF "AUSF" #define AMF_CONFIG_STRING_AUSF "AUSF"
#define AMF_CONFIG_STRING_NSSF "NSSF"
#define AMF_CONFIG_STRING_SCHED_PARAMS "SCHED_PARAMS" #define AMF_CONFIG_STRING_SCHED_PARAMS "SCHED_PARAMS"
#define AMF_CONFIG_STRING_THREAD_RD_CPU_ID "CPU_ID" #define AMF_CONFIG_STRING_THREAD_RD_CPU_ID "CPU_ID"
#define AMF_CONFIG_STRING_THREAD_RD_SCHED_POLICY "SCHED_POLICY" #define AMF_CONFIG_STRING_THREAD_RD_SCHED_POLICY "SCHED_POLICY"
...@@ -102,6 +104,7 @@ ...@@ -102,6 +104,7 @@
"ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST" "ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES "SUPPORT_FEATURES" #define AMF_CONFIG_STRING_SUPPORT_FEATURES "SUPPORT_FEATURES"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES_NF_REGISTRATION "NF_REGISTRATION" #define AMF_CONFIG_STRING_SUPPORT_FEATURES_NF_REGISTRATION "NF_REGISTRATION"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES_NRF_SELECTION "NRF_SELECTION"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES_SMF_SELECTION "SMF_SELECTION" #define AMF_CONFIG_STRING_SUPPORT_FEATURES_SMF_SELECTION "SMF_SELECTION"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES_EXTERNAL_AUSF "EXTERNAL_AUSF" #define AMF_CONFIG_STRING_SUPPORT_FEATURES_EXTERNAL_AUSF "EXTERNAL_AUSF"
#define AMF_CONFIG_STRING_SUPPORT_FEATURES_EXTERNAL_UDM "EXTERNAL_UDM" #define AMF_CONFIG_STRING_SUPPORT_FEATURES_EXTERNAL_UDM "EXTERNAL_UDM"
...@@ -204,6 +207,7 @@ class amf_config { ...@@ -204,6 +207,7 @@ class amf_config {
struct { struct {
bool enable_nf_registration; bool enable_nf_registration;
bool enable_nrf_selection;
bool enable_smf_selection; bool enable_smf_selection;
bool enable_external_ausf; bool enable_external_ausf;
bool enable_external_udm; bool enable_external_udm;
...@@ -222,6 +226,12 @@ class amf_config { ...@@ -222,6 +226,12 @@ class amf_config {
unsigned int port; unsigned int port;
std::string api_version; std::string api_version;
} ausf_addr; } ausf_addr;
struct {
struct in_addr ipv4_addr;
unsigned int port;
std::string api_version;
} nssf_addr;
}; };
} // namespace config } // namespace config
......
...@@ -330,7 +330,14 @@ void amf_n11::handle_itti_message(itti_nsmf_pdusession_create_sm_context& smf) { ...@@ -330,7 +330,14 @@ void amf_n11::handle_itti_message(itti_nsmf_pdusession_create_sm_context& smf) {
std::string smf_addr = {}; std::string smf_addr = {};
std::string smf_api_version = {}; std::string smf_api_version = {};
if (!psc.get()->smf_available) { if (!psc.get()->smf_available) {
if (amf_cfg.support_features.enable_smf_selection) { if (amf_cfg.support_features.enable_nrf_selection) {
if (!discover_smf_from_nsi_info(
smf_addr, smf_api_version, psc.get()->snssai, psc.get()->plmn,
psc.get()->dnn)) {
Logger::amf_n11().error("NRF Selection, no NRF candidate is available");
return;
}
} else if (amf_cfg.support_features.enable_smf_selection) {
// use NRF to find suitable SMF based on snssai, plmn and dnn // use NRF to find suitable SMF based on snssai, plmn and dnn
if (!discover_smf( if (!discover_smf(
smf_addr, smf_api_version, psc.get()->snssai, psc.get()->plmn, smf_addr, smf_api_version, psc.get()->snssai, psc.get()->plmn,
...@@ -892,11 +899,134 @@ void amf_n11::curl_http_client( ...@@ -892,11 +899,134 @@ void amf_n11::curl_http_client(
curl_global_cleanup(); curl_global_cleanup();
free_wrapper((void**) &body_data); free_wrapper((void**) &body_data);
} }
//-----------------------------------------------------------------------------------------------------
bool amf_n11::discover_smf_from_nsi_info(
std::string& smf_addr, std::string& smf_api_version, const snssai_t snssai,
const plmn_t plmn, const std::string dnn) {
Logger::amf_n11().debug(
"Send NS Selection to NSSF to discover the appropriate NRF");
bool result = true;
std::string nrf_addr = {};
std::string nrf_port = {};
std::string nrf_api_version = {};
uint8_t http_version = 1;
if (amf_cfg.support_features.use_http2) http_version = 2;
// Get NSI information from NSSF
nlohmann::json slice_info = {};
nlohmann::json snssai_info = {};
snssai_info["sst"] = snssai.sST;
if (!snssai.sD.empty()) snssai_info["sd"] = snssai.sD;
slice_info["sNssai"] = snssai_info;
slice_info["roamingIndication"] = "NON_ROAMING";
// ToDo Add TAI
std::string url = std::string(inet_ntoa(
*((struct in_addr*) &amf_cfg.nssf_addr.ipv4_addr))) +
":" + std::to_string(amf_cfg.nssf_addr.port) +
"/nnssf-nsselection/" + amf_cfg.nssf_addr.api_version +
"/network-slice-information?nf-type=AMF&nf-id=abc&slice-"
"info-request-for-pdu-session=" +
slice_info.dump();
curl_global_init(CURL_GLOBAL_ALL);
CURL* curl = curl = curl_easy_init();
if (curl) {
CURLcode res = {};
struct curl_slist* headers = nullptr;
// headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(headers, "content-type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, amf_cfg.n11.if_name.c_str());
if (http_version == 2) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// we use a self-signed test server, skip verification during debugging
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(
curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
}
// Response information
long httpCode = {0};
std::unique_ptr<std::string> httpData(new std::string());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
// curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::amf_n11().debug(
"NS Selection, response from NSSF, HTTP Code: %d", httpCode);
if (httpCode == 200) {
Logger::amf_n11().debug(
"NS Selection, got successful response from NSSF");
nlohmann::json response_data = {};
try {
response_data = nlohmann::json::parse(*httpData.get());
} catch (nlohmann::json::exception& e) {
Logger::amf_n11().warn(
"NS Selection, could not parse json from the NRF "
"response");
}
Logger::amf_n11().debug(
"NS Selection, response from NSSF, json data: \n %s",
response_data.dump().c_str());
// Process data to obtain NRF info
if (response_data.find("nsiInformation") != response_data.end()) {
std::string nrf_id = response_data["nsiInformation"]["nrfId"];
std::string nsi_id = response_data["nsiInformation"]["nsiId"];
std::vector<std::string> split_result;
boost::split(split_result, nrf_id, boost::is_any_of("/"));
nrf_api_version = split_result[split_result.size() - 2].c_str();
std::string nrf_endpoint =
split_result[split_result.size() - 4].c_str();
std::vector<std::string> split_nrf_endpoint;
boost::split(split_nrf_endpoint, nrf_endpoint, boost::is_any_of(":"));
nrf_port = split_nrf_endpoint[split_nrf_endpoint.size() - 1].c_str();
nrf_addr = split_nrf_endpoint[split_nrf_endpoint.size() - 2].c_str();
}
} else {
Logger::amf_n11().warn("NS Selection, could not get response from NSSF");
result = false;
}
Logger::amf_n11().debug(
"NS Selection, NRF Addr: %s, NRF Port: %s, NRF Api Version: %s",
nrf_addr.c_str(), nrf_port.c_str(), nrf_api_version.c_str());
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
if (!result) return result;
Logger::amf_n11().debug("NSI Inforation is successfully retrieved from NSSF");
if (!discover_smf(
smf_addr, smf_api_version, snssai, plmn, dnn, nrf_addr, nrf_port,
nrf_api_version))
return false;
return true;
}
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
bool amf_n11::discover_smf( bool amf_n11::discover_smf(
std::string& smf_addr, std::string& smf_api_version, const snssai_t snssai, std::string& smf_addr, std::string& smf_api_version, const snssai_t snssai,
const plmn_t plmn, const std::string dnn) { const plmn_t plmn, const std::string dnn, const std::string& nrf_addr,
const std::string& nrf_port, const std::string& nrf_api_version) {
Logger::amf_n11().debug( Logger::amf_n11().debug(
"Send NFDiscovery to NRF to discover the available SMFs"); "Send NFDiscovery to NRF to discover the available SMFs");
bool result = true; bool result = true;
...@@ -905,12 +1035,17 @@ bool amf_n11::discover_smf( ...@@ -905,12 +1035,17 @@ bool amf_n11::discover_smf(
if (amf_cfg.support_features.use_http2) http_version = 2; if (amf_cfg.support_features.use_http2) http_version = 2;
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string url = {};
// TODO: remove hardcoded values // TODO: remove hardcoded values
std::string url = if (!nrf_addr.empty() & !nrf_port.empty() & !nrf_api_version.empty()) {
std::string(inet_ntoa(*((struct in_addr*) &amf_cfg.nrf_addr.ipv4_addr))) + url = nrf_addr + ":" + nrf_port + "/nnrf-disc/" + nrf_api_version +
":" + std::to_string(amf_cfg.nrf_addr.port) + "/nnrf-disc/" + "/nf-instances?target-nf-type=SMF&requester-nf-type=AMF";
amf_cfg.nrf_addr.api_version + } else
"/nf-instances?target-nf-type=SMF&requester-nf-type=AMF"; url = std::string(
inet_ntoa(*((struct in_addr*) &amf_cfg.nrf_addr.ipv4_addr))) +
":" + std::to_string(amf_cfg.nrf_addr.port) + "/nnrf-disc/" +
amf_cfg.nrf_addr.api_version +
"/nf-instances?target-nf-type=SMF&requester-nf-type=AMF";
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
CURL* curl = curl = curl_easy_init(); CURL* curl = curl = curl_easy_init();
......
...@@ -39,6 +39,10 @@ ...@@ -39,6 +39,10 @@
#include "itti_msg_sbi.hpp" #include "itti_msg_sbi.hpp"
#include "pdu_session_context.hpp" #include "pdu_session_context.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
namespace amf_application { namespace amf_application {
class amf_n11 { class amf_n11 {
...@@ -76,11 +80,19 @@ class amf_n11 { ...@@ -76,11 +80,19 @@ class amf_n11 {
std::string remoteUri, std::string Method, std::string msgBody, std::string remoteUri, std::string Method, std::string msgBody,
std::string& response, uint8_t http_version = 1); std::string& response, uint8_t http_version = 1);
bool discover_smf( bool discover_smf_from_nsi_info(
std::string& smf_addr, std::string& smf_api_version, std::string& smf_addr, std::string& smf_api_version,
const snssai_t snssai, const plmn_t plmn, const std::string dnn); const snssai_t snssai, const plmn_t plmn, const std::string dnn);
bool discover_smf(
std::string& smf_addr, std::string& smf_api_version,
const snssai_t snssai, const plmn_t plmn, const std::string dnn,
const std::string& nrf_addr = {}, const std::string& nrf_port = {},
const std::string& nrf_api_version = {});
void register_nf_instance( void register_nf_instance(
std::shared_ptr<itti_n11_register_nf_instance_request> msg); std::shared_ptr<itti_n11_register_nf_instance_request> msg);
bool send_ue_authentication_request( bool send_ue_authentication_request(
oai::amf::model::AuthenticationInfo& auth_info, oai::amf::model::AuthenticationInfo& auth_info,
oai::amf::model::UEAuthenticationCtx& ue_auth_ctx, uint8_t http_version); oai::amf::model::UEAuthenticationCtx& ue_auth_ctx, uint8_t http_version);
......
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