Commit 58fce642 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'httpv2_support' into 'develop'

Httpv2 support

See merge request oai/cn5g/oai-cn5g-smf!93
parents 12738682 9feb4d50
...@@ -89,6 +89,7 @@ SMF = ...@@ -89,6 +89,7 @@ SMF =
# but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling # but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling
USE_LOCAL_SUBSCRIPTION_INFO = "yes"; # Set to yes if SMF uses local subscription information instead of from an UDM USE_LOCAL_SUBSCRIPTION_INFO = "yes"; # Set to yes if SMF uses local subscription information instead of from an UDM
USE_FQDN_DNS = "@USE_FQDN_DNS@"; # Set to yes if AMF/UDM/NRF/UPF will relying on a DNS to resolve FQDN USE_FQDN_DNS = "@USE_FQDN_DNS@"; # Set to yes if AMF/UDM/NRF/UPF will relying on a DNS to resolve FQDN
HTTP_VERSION = @HTTP_VERSION@; # YOUR NRF CONFIG HERE (default: 1)
USE_NETWORK_INSTANCE = "@USE_NETWORK_INSTANCE@" # Set yes if network instance is to be used for given UPF USE_NETWORK_INSTANCE = "@USE_NETWORK_INSTANCE@" # Set yes if network instance is to be used for given UPF
} }
......
...@@ -16,6 +16,7 @@ if [[ ${USE_FQDN_DNS} == "yes" ]];then ...@@ -16,6 +16,7 @@ if [[ ${USE_FQDN_DNS} == "yes" ]];then
UPF_IPV4_ADDRESS=${UPF_IPV4_ADDRESS:-0.0.0.0} UPF_IPV4_ADDRESS=${UPF_IPV4_ADDRESS:-0.0.0.0}
UDM_IPV4_ADDRESS=${UDM_IPV4_ADDRESS:-0.0.0.0} UDM_IPV4_ADDRESS=${UDM_IPV4_ADDRESS:-0.0.0.0}
fi fi
HTTP_VERSION=${HTTP_VERSION:-1}
for c in ${CONFIG_DIR}/*.conf; do for c in ${CONFIG_DIR}/*.conf; do
# grep variable names (format: ${VAR}) from template to be rendered # grep variable names (format: ${VAR}) from template to be rendered
......
...@@ -316,6 +316,31 @@ void smf_http2_server::start() { ...@@ -316,6 +316,31 @@ void smf_http2_server::start() {
}); });
}); });
// NFStatusNotify
server.handle(
NNRF_NF_STATUS_NOTIFY_BASE + smf_cfg.sbi_api_version +
NNRF_NF_STATUS_SUBSCRIBE_URL,
[&](const request& request, const response& response) {
request.on_data([&](const uint8_t* data, std::size_t len) {
std::string msg((char*) data, len);
try {
if (request.method().compare("POST") == 0 && len > 0) {
smf::data_notification_msg notification_msg = {};
NotificationData notificationData = {};
nlohmann::json::parse(msg.c_str()).get_to(notificationData);
this->nf_status_notify_handler(notificationData, response);
}
} catch (nlohmann::detail::exception& e) {
Logger::smf_sbi().warn(
"Can not parse the json data (error: %s)!", e.what());
response.write_head(
http_status_code_e::HTTP_STATUS_CODE_400_BAD_REQUEST);
response.end();
return;
}
});
});
if (server.listen_and_serve(ec, m_address, std::to_string(m_port))) { if (server.listen_and_serve(ec, m_address, std::to_string(m_port))) {
std::cerr << "HTTP Server error: " << ec.message() << std::endl; std::cerr << "HTTP Server error: " << ec.message() << std::endl;
} }
...@@ -453,24 +478,27 @@ void smf_http2_server::update_sm_context_handler( ...@@ -453,24 +478,27 @@ void smf_http2_server::update_sm_context_handler(
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format); sm_context_response.get_n2_sm_information(), json_format);
h.emplace( h.emplace(
"content-type", header_value{"multipart/related; boundary=" + "content-type",
std::string(CURL_MIME_BOUNDARY)}); header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n1_sm_msg_is_set()) { } else if (sm_context_response.n1_sm_msg_is_set()) {
mime_parser::create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
h.emplace( h.emplace(
"content-type", header_value{"multipart/related; boundary=" + "content-type",
std::string(CURL_MIME_BOUNDARY)}); header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n2_sm_info_is_set()) { } else if (sm_context_response.n2_sm_info_is_set()) {
mime_parser::create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n2_sm_information(), sm_context_response.get_n2_sm_information(),
multipart_related_content_part_e::NGAP, json_format); multipart_related_content_part_e::NGAP, json_format);
h.emplace( h.emplace(
"content-type", header_value{"multipart/related; boundary=" + "content-type",
std::string(CURL_MIME_BOUNDARY)}); header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else { } else {
h.emplace("content-type", header_value{json_format}); h.emplace("content-type", header_value{json_format});
body = json_data.dump().c_str(); body = json_data.dump().c_str();
...@@ -526,6 +554,39 @@ void smf_http2_server::release_sm_context_handler( ...@@ -526,6 +554,39 @@ void smf_http2_server::release_sm_context_handler(
response.end(); response.end();
} }
void smf_http2_server::nf_status_notify_handler(
const NotificationData& notificationData, const response& response) {
Logger::smf_api_server().info(
"NFStatusNotifyApiImpl, received a NF status notification...");
smf::data_notification_msg notification_msg = {};
nlohmann::json json_data = {};
std::string content_type = "application/problem+json";
// convert from NotificationData to data_notification_msg
xgpp_conv::data_notification_from_openapi(notificationData, notification_msg);
// Handle the message in smf_app
std::shared_ptr<itti_sbi_notification_data> itti_msg =
std::make_shared<itti_sbi_notification_data>(TASK_SMF_SBI, TASK_SMF_APP);
itti_msg->notification_msg = notification_msg;
itti_msg->http_version = 2;
ProblemDetails problem_details = {};
uint8_t http_code = 0;
header_map h;
if (m_smf_app->handle_nf_status_notification(
itti_msg, problem_details, http_code)) {
http_code = 204;
response.write_head(http_code, h);
response.end();
} else {
to_json(json_data, problem_details);
h.emplace("content-type", header_value{content_type});
response.end(json_data.dump().c_str());
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_http2_server::stop() { void smf_http2_server::stop() {
server.stop(); server.stop();
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "SmContextUpdateMessage.h" #include "SmContextUpdateMessage.h"
#include "SmContextMessage.h" #include "SmContextMessage.h"
#include "SmContextReleaseMessage.h" #include "SmContextReleaseMessage.h"
#include "NFStatusNotifyApiImpl.h"
#include "uint_generator.hpp" #include "uint_generator.hpp"
#include "smf.h" #include "smf.h"
...@@ -59,6 +60,10 @@ class smf_http2_server { ...@@ -59,6 +60,10 @@ class smf_http2_server {
const std::string& smf_ref, const std::string& smf_ref,
const SmContextReleaseMessage& smContextReleaseMessage, const SmContextReleaseMessage& smContextReleaseMessage,
const response& response); const response& response);
void nf_status_notify_handler(
const NotificationData& notificationData, const response& response);
void stop(); void stop();
private: private:
......
...@@ -204,6 +204,7 @@ typedef struct qos_profile_s { ...@@ -204,6 +204,7 @@ typedef struct qos_profile_s {
#define NNRF_NFM_BASE "/nnrf-nfm/" #define NNRF_NFM_BASE "/nnrf-nfm/"
#define NNRF_NF_REGISTER_URL "/nf-instances/" #define NNRF_NF_REGISTER_URL "/nf-instances/"
#define NNRF_NF_STATUS_SUBSCRIBE_URL "/subscriptions" #define NNRF_NF_STATUS_SUBSCRIBE_URL "/subscriptions"
#define NNRF_NF_STATUS_NOTIFY_BASE "/nsmf-nfstatus-notify/"
// for CURL // for CURL
#define NF_CURL_TIMEOUT_MS 100L #define NF_CURL_TIMEOUT_MS 100L
......
...@@ -701,8 +701,8 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -701,8 +701,8 @@ void smf_app::handle_pdu_session_create_sm_context_request(
std::string n1_sm_message, n1_sm_message_hex; std::string n1_sm_message, n1_sm_message_hex;
nas_message_t decoded_nas_msg = {}; nas_message_t decoded_nas_msg = {};
cause_value_5gsm_e cause_n1 = {cause_value_5gsm_e::CAUSE_0_UNKNOWN}; cause_value_5gsm_e cause_n1 = {cause_value_5gsm_e::CAUSE_0_UNKNOWN};
pdu_session_type_t pdu_session_type = {.pdu_session_type = pdu_session_type_t pdu_session_type = {
PDU_SESSION_TYPE_E_IPV4}; .pdu_session_type = PDU_SESSION_TYPE_E_IPV4};
// Step 1. Decode NAS and get the necessary information // Step 1. Decode NAS and get the necessary information
int decoder_rc = smf_n1::get_instance().decode_n1_sm_container( int decoder_rc = smf_n1::get_instance().decode_n1_sm_container(
...@@ -1625,6 +1625,7 @@ void smf_app::timer_nrf_heartbeat_timeout( ...@@ -1625,6 +1625,7 @@ void smf_app::timer_nrf_heartbeat_timeout(
patch_item.setValue("REGISTERED"); patch_item.setValue("REGISTERED");
itti_msg->patch_items.push_back(patch_item); itti_msg->patch_items.push_back(patch_item);
itti_msg->smf_instance_id = smf_instance_id; itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg); int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) { if (RETURNok != ret) {
...@@ -2070,8 +2071,9 @@ void smf_app::trigger_nf_registration_request() { ...@@ -2070,8 +2071,9 @@ void smf_app::trigger_nf_registration_request() {
std::shared_ptr<itti_n11_register_nf_instance_request> itti_msg = std::shared_ptr<itti_n11_register_nf_instance_request> itti_msg =
std::make_shared<itti_n11_register_nf_instance_request>( std::make_shared<itti_n11_register_nf_instance_request>(
TASK_SMF_APP, TASK_SMF_SBI); TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->profile = nf_instance_profile; itti_msg->profile = nf_instance_profile;
int ret = itti_inst->send_msg(itti_msg); itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) { if (RETURNok != ret) {
Logger::smf_app().error( Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI", "Could not send ITTI message %s to task TASK_SMF_SBI",
...@@ -2088,6 +2090,7 @@ void smf_app::trigger_nf_deregistration() { ...@@ -2088,6 +2090,7 @@ void smf_app::trigger_nf_deregistration() {
std::make_shared<itti_n11_deregister_nf_instance>( std::make_shared<itti_n11_deregister_nf_instance>(
TASK_SMF_APP, TASK_SMF_SBI); TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->smf_instance_id = smf_instance_id; itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg); int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) { if (RETURNok != ret) {
Logger::smf_app().error( Logger::smf_app().error(
...@@ -2107,10 +2110,12 @@ void smf_app::trigger_upf_status_notification_subscribe() { ...@@ -2107,10 +2110,12 @@ void smf_app::trigger_upf_status_notification_subscribe() {
TASK_SMF_APP, TASK_SMF_SBI); TASK_SMF_APP, TASK_SMF_SBI);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
unsigned int port = smf_cfg.sbi.port;
if (smf_cfg.http_version == 2) port = smf_cfg.sbi_http2_port;
// TODO: remove hardcoded values // TODO: remove hardcoded values
json_data["nfStatusNotificationUri"] = json_data["nfStatusNotificationUri"] =
std::string(inet_ntoa(*((struct in_addr*) &smf_cfg.sbi.addr4))) + ":" + std::string(inet_ntoa(*((struct in_addr*) &smf_cfg.sbi.addr4))) + ":" +
std::to_string(smf_cfg.sbi.port) + "/nsmf-nfstatus-notify/" + std::to_string(port) + "/nsmf-nfstatus-notify/" +
smf_cfg.sbi_api_version + "/subscriptions"; smf_cfg.sbi_api_version + "/subscriptions";
json_data["subscrCond"]["NfTypeCond"]["nfType"] = "UPF"; json_data["subscrCond"]["NfTypeCond"]["nfType"] = "UPF";
...@@ -2124,9 +2129,10 @@ void smf_app::trigger_upf_status_notification_subscribe() { ...@@ -2124,9 +2129,10 @@ void smf_app::trigger_upf_status_notification_subscribe() {
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE + ":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_STATUS_SUBSCRIBE_URL; smf_cfg.nrf_addr.api_version + NNRF_NF_STATUS_SUBSCRIBE_URL;
itti_msg->url = url; itti_msg->url = url;
itti_msg->json_data = json_data; itti_msg->json_data = json_data;
int ret = itti_inst->send_msg(itti_msg); itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) { if (RETURNok != ret) {
Logger::smf_app().error( Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI", "Could not send ITTI message %s to task TASK_SMF_SBI",
......
...@@ -560,6 +560,7 @@ int smf_config::load(const string& config_file) { ...@@ -560,6 +560,7 @@ int smf_config::load(const string& config_file) {
const Setting& support_features = const Setting& support_features =
smf_cfg[SMF_CONFIG_STRING_SUPPORT_FEATURES]; smf_cfg[SMF_CONFIG_STRING_SUPPORT_FEATURES];
string opt; string opt;
unsigned int httpVersion = {0};
support_features.lookupValue( support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF, opt); SMF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF, opt);
if (boost::iequals(opt, "yes")) { if (boost::iequals(opt, "yes")) {
...@@ -599,6 +600,10 @@ int smf_config::load(const string& config_file) { ...@@ -599,6 +600,10 @@ int smf_config::load(const string& config_file) {
use_fqdn_dns = false; use_fqdn_dns = false;
} }
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_SBI_HTTP_VERSION, httpVersion);
http_version = httpVersion;
support_features.lookupValue( support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE, opt); SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE, opt);
if (boost::iequals(opt, "yes")) { if (boost::iequals(opt, "yes")) {
...@@ -820,8 +825,17 @@ int smf_config::load(const string& config_file) { ...@@ -820,8 +825,17 @@ int smf_config::load(const string& config_file) {
IPV4_STR_ADDR_TO_INADDR( IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nrf_ipv4_addr, util::trim(address).c_str(), nrf_ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR NRF !"); "BAD IPv4 ADDRESS FORMAT FOR NRF !");
nrf_addr.ipv4_addr = nrf_ipv4_addr; nrf_addr.ipv4_addr = nrf_ipv4_addr;
nrf_addr.port = nrf_port; // nrf_addr.port = nrf_port;
// We hardcode nrf port from config for the moment
if (!(nrf_cfg.lookupValue(SMF_CONFIG_STRING_NRF_PORT, nrf_port))) {
Logger::smf_app().error(SMF_CONFIG_STRING_NRF_PORT "failed");
throw(SMF_CONFIG_STRING_NRF_PORT "failed");
}
nrf_addr.port = nrf_port;
//
nrf_addr.api_version = "v1"; // TODO: to get API version from DNS nrf_addr.api_version = "v1"; // TODO: to get API version from DNS
nrf_addr.fqdn = astring; nrf_addr.fqdn = astring;
} }
......
...@@ -144,6 +144,7 @@ ...@@ -144,6 +144,7 @@
#define SMF_CONFIG_STRING_NAS_FORCE_PUSH_PCO \ #define SMF_CONFIG_STRING_NAS_FORCE_PUSH_PCO \
"FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS" "FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_FQDN_DNS "USE_FQDN_DNS" #define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_FQDN_DNS "USE_FQDN_DNS"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_SBI_HTTP_VERSION "HTTP_VERSION"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE \ #define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE \
"USE_NETWORK_INSTANCE" "USE_NETWORK_INSTANCE"
...@@ -228,6 +229,7 @@ class smf_config { ...@@ -228,6 +229,7 @@ class smf_config {
bool discover_upf; bool discover_upf;
bool use_local_subscription_info; bool use_local_subscription_info;
bool use_fqdn_dns; bool use_fqdn_dns;
unsigned int http_version;
bool use_nwi; bool use_nwi;
struct { struct {
...@@ -249,6 +251,7 @@ class smf_config { ...@@ -249,6 +251,7 @@ class smf_config {
struct { struct {
struct in_addr ipv4_addr; struct in_addr ipv4_addr;
unsigned int port; unsigned int port;
unsigned int http_version;
std::string api_version; std::string api_version;
std::string fqdn; std::string fqdn;
} nrf_addr; } nrf_addr;
......
...@@ -596,7 +596,8 @@ void smf_sbi::register_nf_instance( ...@@ -596,7 +596,8 @@ void smf_sbi::register_nf_instance(
add_promise(promise_id, p); add_promise(promise_id, p);
// Create a new curl easy handle and add to the multi handle // Create a new curl easy handle and add to the multi handle
if (!curl_create_handle(url, body, response_data, pid_ptr, "PUT")) { if (!curl_create_handle(
url, body, response_data, pid_ptr, "PUT", msg->http_version)) {
Logger::smf_sbi().warn("Could not create a new handle to send message"); Logger::smf_sbi().warn("Could not create a new handle to send message");
remove_promise(promise_id); remove_promise(promise_id);
return; return;
...@@ -680,7 +681,8 @@ void smf_sbi::update_nf_instance( ...@@ -680,7 +681,8 @@ void smf_sbi::update_nf_instance(
add_promise(promise_id, p); add_promise(promise_id, p);
// Create a new curl easy handle and add to the multi handle // Create a new curl easy handle and add to the multi handle
if (!curl_create_handle(url, body, response_data, pid_ptr, "PATCH")) { if (!curl_create_handle(
url, body, response_data, pid_ptr, "PATCH", msg->http_version)) {
Logger::smf_sbi().warn("Could not create a new handle to send message"); Logger::smf_sbi().warn("Could not create a new handle to send message");
remove_promise(promise_id); remove_promise(promise_id);
return; return;
...@@ -747,7 +749,8 @@ void smf_sbi::deregister_nf_instance( ...@@ -747,7 +749,8 @@ void smf_sbi::deregister_nf_instance(
add_promise(promise_id, p); add_promise(promise_id, p);
// Create a new curl easy handle and add to the multi handle // Create a new curl easy handle and add to the multi handle
if (!curl_create_handle(url, response_data, pid_ptr, "DELETE")) { if (!curl_create_handle(
url, response_data, pid_ptr, "DELETE", msg->http_version)) {
Logger::smf_sbi().warn("Could not create a new handle to send message"); Logger::smf_sbi().warn("Could not create a new handle to send message");
remove_promise(promise_id); remove_promise(promise_id);
return; return;
...@@ -799,7 +802,8 @@ void smf_sbi::subscribe_upf_status_notify( ...@@ -799,7 +802,8 @@ void smf_sbi::subscribe_upf_status_notify(
add_promise(promise_id, p); add_promise(promise_id, p);
// Create a new curl easy handle and add to the multi handle // Create a new curl easy handle and add to the multi handle
if (!curl_create_handle(msg->url, body, response_data, pid_ptr, "POST")) { if (!curl_create_handle(
msg->url, body, response_data, pid_ptr, "POST", msg->http_version)) {
Logger::smf_sbi().warn("Could not create a new handle to send message"); Logger::smf_sbi().warn("Could not create a new handle to send message");
remove_promise(promise_id); remove_promise(promise_id);
return; return;
......
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