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 =
# 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_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
}
......
......@@ -16,6 +16,7 @@ if [[ ${USE_FQDN_DNS} == "yes" ]];then
UPF_IPV4_ADDRESS=${UPF_IPV4_ADDRESS:-0.0.0.0}
UDM_IPV4_ADDRESS=${UDM_IPV4_ADDRESS:-0.0.0.0}
fi
HTTP_VERSION=${HTTP_VERSION:-1}
for c in ${CONFIG_DIR}/*.conf; do
# grep variable names (format: ${VAR}) from template to be rendered
......
......@@ -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))) {
std::cerr << "HTTP Server error: " << ec.message() << std::endl;
}
......@@ -453,24 +478,27 @@ void smf_http2_server::update_sm_context_handler(
sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n1_sm_msg_is_set()) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n2_sm_info_is_set()) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n2_sm_information(),
multipart_related_content_part_e::NGAP, json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else {
h.emplace("content-type", header_value{json_format});
body = json_data.dump().c_str();
......@@ -526,6 +554,39 @@ void smf_http2_server::release_sm_context_handler(
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() {
server.stop();
......
......@@ -35,6 +35,7 @@
#include "SmContextUpdateMessage.h"
#include "SmContextMessage.h"
#include "SmContextReleaseMessage.h"
#include "NFStatusNotifyApiImpl.h"
#include "uint_generator.hpp"
#include "smf.h"
......@@ -59,6 +60,10 @@ class smf_http2_server {
const std::string& smf_ref,
const SmContextReleaseMessage& smContextReleaseMessage,
const response& response);
void nf_status_notify_handler(
const NotificationData& notificationData, const response& response);
void stop();
private:
......
......@@ -204,6 +204,7 @@ typedef struct qos_profile_s {
#define NNRF_NFM_BASE "/nnrf-nfm/"
#define NNRF_NF_REGISTER_URL "/nf-instances/"
#define NNRF_NF_STATUS_SUBSCRIBE_URL "/subscriptions"
#define NNRF_NF_STATUS_NOTIFY_BASE "/nsmf-nfstatus-notify/"
// for CURL
#define NF_CURL_TIMEOUT_MS 100L
......
......@@ -701,8 +701,8 @@ void smf_app::handle_pdu_session_create_sm_context_request(
std::string n1_sm_message, n1_sm_message_hex;
nas_message_t decoded_nas_msg = {};
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_E_IPV4};
pdu_session_type_t pdu_session_type = {
.pdu_session_type = PDU_SESSION_TYPE_E_IPV4};
// Step 1. Decode NAS and get the necessary information
int decoder_rc = smf_n1::get_instance().decode_n1_sm_container(
......@@ -1625,6 +1625,7 @@ void smf_app::timer_nrf_heartbeat_timeout(
patch_item.setValue("REGISTERED");
itti_msg->patch_items.push_back(patch_item);
itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
......@@ -2070,8 +2071,9 @@ void smf_app::trigger_nf_registration_request() {
std::shared_ptr<itti_n11_register_nf_instance_request> itti_msg =
std::make_shared<itti_n11_register_nf_instance_request>(
TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->profile = nf_instance_profile;
int ret = itti_inst->send_msg(itti_msg);
itti_msg->profile = nf_instance_profile;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI",
......@@ -2088,6 +2090,7 @@ void smf_app::trigger_nf_deregistration() {
std::make_shared<itti_n11_deregister_nf_instance>(
TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
......@@ -2107,10 +2110,12 @@ void smf_app::trigger_upf_status_notification_subscribe() {
TASK_SMF_APP, TASK_SMF_SBI);
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
json_data["nfStatusNotificationUri"] =
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";
json_data["subscrCond"]["NfTypeCond"]["nfType"] = "UPF";
......@@ -2124,9 +2129,10 @@ void smf_app::trigger_upf_status_notification_subscribe() {
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_STATUS_SUBSCRIBE_URL;
itti_msg->url = url;
itti_msg->json_data = json_data;
int ret = itti_inst->send_msg(itti_msg);
itti_msg->url = url;
itti_msg->json_data = json_data;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI",
......
......@@ -560,6 +560,7 @@ int smf_config::load(const string& config_file) {
const Setting& support_features =
smf_cfg[SMF_CONFIG_STRING_SUPPORT_FEATURES];
string opt;
unsigned int httpVersion = {0};
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF, opt);
if (boost::iequals(opt, "yes")) {
......@@ -599,6 +600,10 @@ int smf_config::load(const string& config_file) {
use_fqdn_dns = false;
}
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_SBI_HTTP_VERSION, httpVersion);
http_version = httpVersion;
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE, opt);
if (boost::iequals(opt, "yes")) {
......@@ -820,8 +825,17 @@ int smf_config::load(const string& config_file) {
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nrf_ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR NRF !");
nrf_addr.ipv4_addr = nrf_ipv4_addr;
nrf_addr.port = nrf_port;
nrf_addr.ipv4_addr = nrf_ipv4_addr;
// 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.fqdn = astring;
}
......
......@@ -144,6 +144,7 @@
#define SMF_CONFIG_STRING_NAS_FORCE_PUSH_PCO \
"FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS"
#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 \
"USE_NETWORK_INSTANCE"
......@@ -228,6 +229,7 @@ class smf_config {
bool discover_upf;
bool use_local_subscription_info;
bool use_fqdn_dns;
unsigned int http_version;
bool use_nwi;
struct {
......@@ -249,6 +251,7 @@ class smf_config {
struct {
struct in_addr ipv4_addr;
unsigned int port;
unsigned int http_version;
std::string api_version;
std::string fqdn;
} nrf_addr;
......
......@@ -596,7 +596,8 @@ void smf_sbi::register_nf_instance(
add_promise(promise_id, p);
// 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");
remove_promise(promise_id);
return;
......@@ -680,7 +681,8 @@ void smf_sbi::update_nf_instance(
add_promise(promise_id, p);
// 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");
remove_promise(promise_id);
return;
......@@ -747,7 +749,8 @@ void smf_sbi::deregister_nf_instance(
add_promise(promise_id, p);
// 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");
remove_promise(promise_id);
return;
......@@ -799,7 +802,8 @@ void smf_sbi::subscribe_upf_status_notify(
add_promise(promise_id, p);
// 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");
remove_promise(promise_id);
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