Commit 0396b32b authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'fix_develop_ue_rel16' into 'develop'

Fix issue to work with COTS UE

See merge request oai/cn5g/oai-cn5g-smf!161
parents 9f73f011 3c4cfaac
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "NFStatusNotifyApi.h" #include "NFStatusNotifyApi.h"
#include "Helpers.h" #include "Helpers.h"
#include "logger.hpp"
#include "smf_config.hpp" #include "smf_config.hpp"
extern smf::smf_config smf_cfg; extern smf::smf_config smf_cfg;
...@@ -56,6 +57,9 @@ void NFStatusNotifyApi::setupRoutes() { ...@@ -56,6 +57,9 @@ void NFStatusNotifyApi::setupRoutes() {
void NFStatusNotifyApi::notify_nf_status_handler( void NFStatusNotifyApi::notify_nf_status_handler(
const Pistache::Rest::Request& request, const Pistache::Rest::Request& request,
Pistache::Http::ResponseWriter response) { Pistache::Http::ResponseWriter response) {
Logger::smf_api_server().info("Received a NFStatusNotify message");
Logger::smf_api_server().debug("Message body: %s", request.body().c_str());
// Getting the body param // Getting the body param
NotificationData notificationData; NotificationData notificationData;
......
...@@ -65,15 +65,13 @@ void IndividualSMContextApiImpl::release_sm_context( ...@@ -65,15 +65,13 @@ void IndividualSMContextApiImpl::release_sm_context(
xgpp_conv::sm_context_release_from_openapi( xgpp_conv::sm_context_release_from_openapi(
smContextReleaseMessage, sm_context_req_msg); smContextReleaseMessage, sm_context_req_msg);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_release_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_release_sm_context_response> >();
boost::shared_future<smf::pdu_session_release_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -88,19 +86,21 @@ void IndividualSMContextApiImpl::release_sm_context( ...@@ -88,19 +86,21 @@ void IndividualSMContextApiImpl::release_sm_context(
boost::future_status status; boost::future_status status;
// wait for timeout or ready // wait for timeout or ready
status = f.wait_for(boost::chrono::milliseconds(FUTURE_STATUS_TIMEOUT_MS)); status = f.wait_for(boost::chrono::milliseconds(FUTURE_STATUS_TIMEOUT_MS));
int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
if (status == boost::future_status::ready) { if (status == boost::future_status::ready) {
assert(f.is_ready()); assert(f.is_ready());
assert(f.has_value()); assert(f.has_value());
assert(!f.has_exception()); assert(!f.has_exception());
// Wait for the result from APP and send reply to NF consumer (e.g., AMF) // Wait for the result from APP and send reply to NF consumer (e.g., AMF)
smf::pdu_session_release_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
// TODO: Process the response // TODO: Process the response
response.send(Pistache::Http::Code(sm_context_response.get_http_code()));
} else {
response.send(Pistache::Http::Code::Request_Timeout);
} }
response.send(Pistache::Http::Code(http_code));
} }
void IndividualSMContextApiImpl::retrieve_sm_context( void IndividualSMContextApiImpl::retrieve_sm_context(
...@@ -128,15 +128,13 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -128,15 +128,13 @@ void IndividualSMContextApiImpl::update_sm_context(
xgpp_conv::sm_context_update_from_openapi( xgpp_conv::sm_context_update_from_openapi(
smContextUpdateMessage, sm_context_req_msg); smContextUpdateMessage, sm_context_req_msg);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_update_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_update_sm_context_response> >();
boost::shared_future<smf::pdu_session_update_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -156,40 +154,65 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -156,40 +154,65 @@ void IndividualSMContextApiImpl::update_sm_context(
assert(f.has_value()); assert(f.has_value());
assert(!f.has_exception()); assert(!f.has_exception());
// Wait for the result from APP and send reply to NF consumer (e.g., AMF) // Wait for the result from APP and send reply to NF consumer (e.g., AMF)
smf::pdu_session_update_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body = {}; std::string body = {};
std::string json_format; std::string json_format;
bool n1_sm_msg_is_set = false;
bool n2_sm_info_is_set = false;
sm_context_response.get_json_format(json_format); int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
sm_context_response.get_json_data(json_data); if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
if (sm_context_response.find("json_format") != sm_context_response.end()) {
json_format = sm_context_response["json_format"].get<std::string>();
}
if (sm_context_response.find("json_data") != sm_context_response.end()) {
json_data = sm_context_response["json_data"];
}
if (sm_context_response.find("n1_sm_message") !=
sm_context_response.end()) {
// json_data = sm_context_response["n1_sm_message"].get<std::string>();
n1_sm_msg_is_set = true;
}
if (sm_context_response.find("n2_sm_information") !=
sm_context_response.end()) {
n2_sm_info_is_set = true;
}
// sm_context_response.get_json_format(json_format);
// sm_context_response.get_json_data(json_data);
Logger::smf_api_server().debug("Json data %s", json_data.dump().c_str()); Logger::smf_api_server().debug("Json data %s", json_data.dump().c_str());
if (sm_context_response.n1_sm_msg_is_set() and if (n1_sm_msg_is_set and n2_sm_info_is_set) {
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_n1_sm_message(), sm_context_response["n1_sm_message"].get<std::string>(),
sm_context_response.get_n2_sm_information(), json_format); sm_context_response["n2_sm_information"].get<std::string>(),
json_format);
response.headers().add<Pistache::Http::Header::ContentType>( response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + "multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY))); std::string(CURL_MIME_BOUNDARY)));
} else if (sm_context_response.n1_sm_msg_is_set()) { } else if (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["n1_sm_message"].get<std::string>(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
response.headers().add<Pistache::Http::Header::ContentType>( response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + "multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY))); std::string(CURL_MIME_BOUNDARY)));
} else if (sm_context_response.n2_sm_info_is_set()) { } else if (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["n2_sm_information"].get<std::string>(),
multipart_related_content_part_e::NGAP, json_format); multipart_related_content_part_e::NGAP, json_format);
response.headers().add<Pistache::Http::Header::ContentType>( response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
...@@ -200,12 +223,10 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -200,12 +223,10 @@ void IndividualSMContextApiImpl::update_sm_context(
Pistache::Http::Mime::MediaType(json_format)); Pistache::Http::Mime::MediaType(json_format));
body = json_data.dump().c_str(); body = json_data.dump().c_str();
} else { } else {
response.send(Pistache::Http::Code(sm_context_response.get_http_code())); response.send(Pistache::Http::Code(http_code));
return; return;
} }
response.send(Pistache::Http::Code(http_code), body);
response.send(
Pistache::Http::Code(sm_context_response.get_http_code()), body);
} else { } else {
response.send(Pistache::Http::Code::Request_Timeout); response.send(Pistache::Http::Code::Request_Timeout);
} }
......
...@@ -94,9 +94,6 @@ class IndividualSMContextApiImpl ...@@ -94,9 +94,6 @@ class IndividualSMContextApiImpl
std::string m_address; std::string m_address;
protected: protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
}; };
} // namespace api } // namespace api
......
...@@ -84,15 +84,13 @@ void SMContextsCollectionApiImpl::post_sm_contexts( ...@@ -84,15 +84,13 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
m_address + base + smf_cfg.sbi_api_version + m_address + base + smf_cfg.sbi_api_version +
NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL); NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_create_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_create_sm_context_response> >();
boost::shared_future<smf::pdu_session_create_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -112,40 +110,60 @@ void SMContextsCollectionApiImpl::post_sm_contexts( ...@@ -112,40 +110,60 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
assert(f.has_value()); assert(f.has_value());
assert(!f.has_exception()); assert(!f.has_exception());
// Wait for the result from APP and send reply to AMF // Wait for the result from APP and send reply to AMF
smf::pdu_session_create_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string json_format = {}; std::string json_format = {};
std::string body = {}; std::string body = {};
bool n1_sm_msg_is_set = false;
sm_context_response.get_json_data(json_data); int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
sm_context_response.get_json_format(json_format); if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
if (sm_context_response.n1_sm_msg_is_set()) { // add N1 container if if (sm_context_response.find("json_format") != sm_context_response.end()) {
// available json_format = sm_context_response["json_format"].get<std::string>();
}
if (sm_context_response.find("json_data") != sm_context_response.end()) {
json_data = sm_context_response["json_data"];
}
if (sm_context_response.find("n1_sm_message") !=
sm_context_response.end()) {
// json_data = sm_context_response["n1_sm_message"].get<std::string>();
n1_sm_msg_is_set = true;
}
if (http_code == http_status_code_e::HTTP_STATUS_CODE_201_CREATED) {
if (sm_context_response.find("smf_context_uri") !=
sm_context_response.end()) {
response.headers().add<Pistache::Http::Header::Location>(
sm_context_response["smf_context_uri"]
.get<std::string>()); // Location header
}
}
if (n1_sm_msg_is_set) { // add N1 container if available
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["n1_sm_message"].get<std::string>(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
response.headers().add<Pistache::Http::Header::ContentType>( response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + "multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY))); std::string(CURL_MIME_BOUNDARY)));
} else if (!json_data.empty()) { // if not, include json data if available } else if (!json_data.empty()) { // if not, include json data if available
response.headers().add<Pistache::Http::Header::Location>(
sm_context_response.get_smf_context_uri()); // Location header
response.headers().add<Pistache::Http::Header::ContentType>( response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(json_format)); Pistache::Http::Mime::MediaType(json_format));
body = json_data.dump().c_str(); body = json_data.dump().c_str();
} else { // otherwise, send reply without content } else { // otherwise, send reply without content
response.send(Pistache::Http::Code(sm_context_response.get_http_code())); response.send(Pistache::Http::Code(http_code));
return; return;
} }
response.send( response.send(Pistache::Http::Code(http_code), body);
Pistache::Http::Code(sm_context_response.get_http_code()), body);
} else { } else {
response.send(Pistache::Http::Code::Request_Timeout); response.send(Pistache::Http::Code::Request_Timeout);
} }
......
...@@ -79,9 +79,6 @@ class SMContextsCollectionApiImpl ...@@ -79,9 +79,6 @@ class SMContextsCollectionApiImpl
std::string m_address; std::string m_address;
protected: protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
}; };
} // namespace api } // namespace api
......
...@@ -77,9 +77,6 @@ class SubscriptionsCollectionApiImpl ...@@ -77,9 +77,6 @@ class SubscriptionsCollectionApiImpl
std::string m_address; std::string m_address;
protected: protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
}; };
} // namespace api } // namespace api
......
...@@ -373,15 +373,13 @@ void smf_http2_server::create_sm_contexts_handler( ...@@ -373,15 +373,13 @@ void smf_http2_server::create_sm_contexts_handler(
NSMF_PDU_SESSION_BASE + smf_cfg.sbi_api_version + NSMF_PDU_SESSION_BASE + smf_cfg.sbi_api_version +
NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL); NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_create_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_create_sm_context_response> >();
boost::shared_future<smf::pdu_session_create_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -394,27 +392,46 @@ void smf_http2_server::create_sm_contexts_handler( ...@@ -394,27 +392,46 @@ void smf_http2_server::create_sm_contexts_handler(
m_smf_app->handle_pdu_session_create_sm_context_request(itti_msg); m_smf_app->handle_pdu_session_create_sm_context_request(itti_msg);
// Wait for the result from APP and send reply to AMF // Wait for the result from APP and send reply to AMF
smf::pdu_session_create_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
sm_context_response.get_json_data(json_data); std::string json_format = {};
std::string json_format; bool n1_sm_msg_is_set = false;
sm_context_response.get_json_format(json_format); int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
if (sm_context_response.find("json_format") != sm_context_response.end()) {
json_format = sm_context_response["json_format"].get<std::string>();
}
if (sm_context_response.find("json_data") != sm_context_response.end()) {
json_data = sm_context_response["json_data"];
}
if (sm_context_response.find("n1_sm_message") != sm_context_response.end()) {
// json_data = sm_context_response["n1_sm_message"].get<std::string>();
n1_sm_msg_is_set = true;
}
// Add header // Add header
header_map h; header_map h;
// Location header // Location header
if (sm_context_response.get_smf_context_uri().size() > 0) { if (sm_context_response.find("smf_context_uri") !=
sm_context_response.end()) {
Logger::smf_api_server().debug( Logger::smf_api_server().debug(
"Add location header %s", "Add location header %s",
sm_context_response.get_smf_context_uri().c_str()); sm_context_response["smf_context_uri"].get<std::string>().c_str());
h.emplace( h.emplace(
"location", "location",
header_value{sm_context_response.get_smf_context_uri().c_str()}); header_value{
sm_context_response["smf_context_uri"].get<std::string>().c_str()});
} }
// content-type header // content-type header
h.emplace("content-type", header_value{json_format}); h.emplace("content-type", header_value{json_format});
response.write_head(sm_context_response.get_http_code(), h); response.write_head(http_code, h);
response.end(json_data.dump().c_str()); response.end(json_data.dump().c_str());
} }
...@@ -438,15 +455,13 @@ void smf_http2_server::update_sm_context_handler( ...@@ -438,15 +455,13 @@ void smf_http2_server::update_sm_context_handler(
xgpp_conv::sm_context_update_from_openapi( xgpp_conv::sm_context_update_from_openapi(
smContextUpdateMessage, sm_context_req_msg); smContextUpdateMessage, sm_context_req_msg);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_update_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_update_sm_context_response> >();
boost::shared_future<smf::pdu_session_update_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -459,39 +474,61 @@ void smf_http2_server::update_sm_context_handler( ...@@ -459,39 +474,61 @@ void smf_http2_server::update_sm_context_handler(
m_smf_app->handle_pdu_session_update_sm_context_request(itti_msg); m_smf_app->handle_pdu_session_update_sm_context_request(itti_msg);
// Wait for the result from APP and send reply to AMF // Wait for the result from APP and send reply to AMF
smf::pdu_session_update_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body = {}; std::string body = {};
header_map h = {}; header_map h = {};
std::string json_format = {}; std::string json_format = {};
bool n1_sm_msg_is_set = false;
bool n2_sm_info_is_set = false;
int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
if (sm_context_response.find("json_format") != sm_context_response.end()) {
json_format = sm_context_response["json_format"].get<std::string>();
}
if (sm_context_response.find("json_data") != sm_context_response.end()) {
json_data = sm_context_response["json_data"];
}
if (sm_context_response.find("n1_sm_message") != sm_context_response.end()) {
// json_data = sm_context_response["n1_sm_message"].get<std::string>();
n1_sm_msg_is_set = true;
}
if (sm_context_response.find("n2_sm_information") !=
sm_context_response.end()) {
n2_sm_info_is_set = true;
}
sm_context_response.get_json_format(json_format);
sm_context_response.get_json_data(json_data);
Logger::smf_api_server().debug("Json data %s", json_data.dump().c_str()); Logger::smf_api_server().debug("Json data %s", json_data.dump().c_str());
if (sm_context_response.n1_sm_msg_is_set() and if (n1_sm_msg_is_set and n2_sm_info_is_set) {
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_n1_sm_message(), sm_context_response["n1_sm_message"].get<std::string>(),
sm_context_response.get_n2_sm_information(), json_format); sm_context_response["n2_sm_information"].get<std::string>(),
json_format);
h.emplace( h.emplace(
"content-type", header_value{"multipart/related; boundary=" + "content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)}); std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n1_sm_msg_is_set()) { } else if (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["n1_sm_message"].get<std::string>(),
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", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)}); std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n2_sm_info_is_set()) { } else if (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["n2_sm_information"].get<std::string>(),
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", header_value{"multipart/related; boundary=" +
...@@ -501,7 +538,7 @@ void smf_http2_server::update_sm_context_handler( ...@@ -501,7 +538,7 @@ void smf_http2_server::update_sm_context_handler(
body = json_data.dump().c_str(); body = json_data.dump().c_str();
} }
response.write_head(sm_context_response.get_http_code(), h); response.write_head(http_code, h);
response.end(body); response.end(body);
} }
...@@ -519,15 +556,13 @@ void smf_http2_server::release_sm_context_handler( ...@@ -519,15 +556,13 @@ void smf_http2_server::release_sm_context_handler(
xgpp_conv::sm_context_release_from_openapi( xgpp_conv::sm_context_release_from_openapi(
smContextReleaseMessage, sm_context_req_msg); smContextReleaseMessage, sm_context_req_msg);
boost::shared_ptr< boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::promise<smf::pdu_session_release_sm_context_response> > boost::make_shared<boost::promise<nlohmann::json> >();
p = boost::make_shared< boost::shared_future<nlohmann::json> f;
boost::promise<smf::pdu_session_release_sm_context_response> >();
boost::shared_future<smf::pdu_session_release_sm_context_response> f;
f = p->get_future(); f = p->get_future();
// Generate ID for this promise (to be used in SMF-APP) // Generate ID for this promise (to be used in SMF-APP)
uint32_t promise_id = generate_promise_id(); uint32_t promise_id = m_smf_app->generate_promise_id();
Logger::smf_api_server().debug("Promise ID generated %d", promise_id); Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
m_smf_app->add_promise(promise_id, p); m_smf_app->add_promise(promise_id, p);
...@@ -544,10 +579,15 @@ void smf_http2_server::release_sm_context_handler( ...@@ -544,10 +579,15 @@ void smf_http2_server::release_sm_context_handler(
m_smf_app->handle_pdu_session_release_sm_context_request(itti_msg); m_smf_app->handle_pdu_session_release_sm_context_request(itti_msg);
// wait for the result from APP and send reply to AMF // wait for the result from APP and send reply to AMF
smf::pdu_session_release_sm_context_response sm_context_response = f.get(); nlohmann::json sm_context_response = f.get();
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
response.write_head(sm_context_response.get_http_code()); int http_code = http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
response.write_head(http_code);
response.end(); response.end();
} }
......
...@@ -74,9 +74,6 @@ class smf_http2_server { ...@@ -74,9 +74,6 @@ class smf_http2_server {
smf::smf_app* m_smf_app; smf::smf_app* m_smf_app;
protected: protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
}; };
#endif #endif
...@@ -1026,6 +1026,13 @@ struct node_id_s { ...@@ -1026,6 +1026,13 @@ struct node_id_s {
struct in6_addr ipv6_address; struct in6_addr ipv6_address;
} u1; } u1;
std::string fqdn; // should be in union but problem with virtual ~ std::string fqdn; // should be in union but problem with virtual ~
node_id_s() {
node_id_type = node_id_type_value_e::NODE_ID_TYPE_UNKNOWN;
u1.ipv4_address.s_addr = INADDR_ANY;
u1.ipv6_address = in6addr_any;
fqdn = {};
}
bool operator==(const struct node_id_s& i) const { bool operator==(const struct node_id_s& i) const {
if (i.node_id_type != this->node_id_type) return false; if (i.node_id_type != this->node_id_type) return false;
switch (i.node_id_type) { switch (i.node_id_type) {
......
...@@ -22,14 +22,15 @@ ...@@ -22,14 +22,15 @@
#ifndef FILE_SMF_SEEN #ifndef FILE_SMF_SEEN
#define FILE_SMF_SEEN #define FILE_SMF_SEEN
#include "3gpp_29.274.h" #include <boost/algorithm/string.hpp>
#include "3gpp_29.571.h"
#include "3gpp_24.501.h"
#include <nlohmann/json.hpp>
#include <map> #include <map>
#include <vector> #include <nlohmann/json.hpp>
#include <unordered_set> #include <unordered_set>
#include <vector>
#include "3gpp_24.501.h"
#include "3gpp_29.274.h"
#include "3gpp_29.571.h"
typedef uint64_t supi64_t; typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64 #define SUPI_64_FMT "%" SCNu64
...@@ -85,13 +86,21 @@ typedef struct s_nssai // section 28.4, TS23.003 ...@@ -85,13 +86,21 @@ typedef struct s_nssai // section 28.4, TS23.003
uint32_t sd; uint32_t sd;
s_nssai(const uint8_t& m_sst, const uint32_t m_sd) : sst(m_sst), sd(m_sd) {} s_nssai(const uint8_t& m_sst, const uint32_t m_sd) : sst(m_sst), sd(m_sd) {}
s_nssai(const uint8_t& m_sst, const std::string m_sd) : sst(m_sst) { s_nssai(const uint8_t& m_sst, const std::string m_sd) : sst(m_sst) {
sd = 0xFFFFFF; sd = SD_NO_VALUE;
if (m_sd.empty()) return;
uint8_t base = 10;
try { try {
sd = std::stoul(m_sd, nullptr, 10); if (m_sd.size() > 2) {
if (boost::iequals(m_sd.substr(0, 2), "0x")) {
base = 16;
}
}
sd = std::stoul(m_sd, nullptr, base);
} catch (const std::exception& e) { } catch (const std::exception& e) {
Logger::smf_app().warn( Logger::smf_app().error(
"Error when converting from string to int for snssai.SD, error: %s", "Error when converting from string to int for S-NSSAI SD, error: %s",
e.what()); e.what());
sd = SD_NO_VALUE;
} }
} }
s_nssai() : sst(), sd() {} s_nssai() : sst(), sd() {}
...@@ -277,7 +286,8 @@ constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800; ...@@ -277,7 +286,8 @@ constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800;
// 8.22 Fully Qualified TEID (F-TEID) - 3GPP TS 29.274 V16.0.0 // 8.22 Fully Qualified TEID (F-TEID) - 3GPP TS 29.274 V16.0.0
#define TEID_GRE_KEY_LENGTH 4 #define TEID_GRE_KEY_LENGTH 4
#define DEFAULT_QFI 6 #define DEFAULT_QFI 1
#define DEFAULT_5QI 9 // TODO: from conf file
typedef struct dnn_smf_info_item_s { typedef struct dnn_smf_info_item_s {
std::string dnn; std::string dnn;
...@@ -345,7 +355,7 @@ typedef struct nf_service_s { ...@@ -345,7 +355,7 @@ typedef struct nf_service_s {
s.append(service_instance_id); s.append(service_instance_id);
s.append(", Service name: "); s.append(", Service name: ");
s.append(service_name); s.append(service_name);
for (auto v : versions) { for (const auto& v : versions) {
s.append(v.to_string()); s.append(v.to_string());
} }
s.append(", Scheme: "); s.append(", Scheme: ");
...@@ -380,11 +390,42 @@ typedef struct dnn_upf_info_item_s { ...@@ -380,11 +390,42 @@ typedef struct dnn_upf_info_item_s {
return std::hash<std::string>()(dnn); return std::hash<std::string>()(dnn);
} }
} dnn_upf_info_item_t; std::string to_string() const {
std::string s = {};
s.append("DNN = ").append(dnn).append(", ");
if (dnai_list.size() > 0) {
s.append("DNAI list: {");
for (const auto& dnai : dnai_list) {
s.append("DNAI = ").append(dnai).append(", ");
}
s.append("}, ");
}
if (dnai_nw_instance_list.size() > 0) {
s.append("DNAI NW Instance list: {");
for (const auto& dnai_nw : dnai_nw_instance_list) {
s.append("(")
.append(dnai_nw.first)
.append(", ")
.append(dnai_nw.second)
.append("),");
}
s.append("}, ");
}
return s;
}
}
dnn_upf_info_item_t;
typedef struct snssai_upf_info_item_s { typedef struct snssai_upf_info_item_s {
snssai_t snssai; mutable snssai_t snssai;
std::unordered_set<dnn_upf_info_item_t, dnn_upf_info_item_t> mutable std::unordered_set<dnn_upf_info_item_t, dnn_upf_info_item_t>
dnn_upf_info_list; dnn_upf_info_list;
snssai_upf_info_item_s& operator=(const snssai_upf_info_item_s& s) { snssai_upf_info_item_s& operator=(const snssai_upf_info_item_s& s) {
...@@ -394,13 +435,29 @@ typedef struct snssai_upf_info_item_s { ...@@ -394,13 +435,29 @@ typedef struct snssai_upf_info_item_s {
} }
bool operator==(const snssai_upf_info_item_s& s) const { bool operator==(const snssai_upf_info_item_s& s) const {
return snssai == s.snssai; return (snssai == s.snssai) and (dnn_upf_info_list == s.dnn_upf_info_list);
} }
size_t operator()(const snssai_upf_info_item_s&) const { size_t operator()(const snssai_upf_info_item_s&) const {
return snssai.operator()(snssai); return snssai.operator()(snssai);
} }
std::string to_string() const {
std::string s = {};
s.append("{" + snssai.toString() + ", ");
if (dnn_upf_info_list.size() > 0) {
s.append("{");
for (auto dnn_upf : dnn_upf_info_list) {
s.append(dnn_upf.to_string());
}
s.append("}, ");
}
return s;
}
} snssai_upf_info_item_t; } snssai_upf_info_item_t;
typedef struct interface_upf_info_item_s { typedef struct interface_upf_info_item_s {
...@@ -436,11 +493,11 @@ typedef struct upf_info_s { ...@@ -436,11 +493,11 @@ typedef struct upf_info_s {
std::string s = {}; std::string s = {};
// TODO: Interface UPF Info List // TODO: Interface UPF Info List
if (!snssai_upf_info_list.empty()) { if (!snssai_upf_info_list.empty()) {
s.append("SNSSAI UPF Info: "); s.append("S-NSSAI UPF Info: ");
for (auto sn : snssai_upf_info_list) { for (auto sn : snssai_upf_info_list) {
s.append("{" + sn.snssai.toString() + ", "); s.append("{" + sn.snssai.toString() + ", ");
for (auto d : sn.dnn_upf_info_list) { for (auto d : sn.dnn_upf_info_list) {
s.append("{DNN = " + d.dnn + "}, "); s.append("{DNN = " + d.dnn + "} ");
} }
s.append("};"); s.append("};");
} }
......
...@@ -181,10 +181,14 @@ void conv::plmnToMccMnc( ...@@ -181,10 +181,14 @@ void conv::plmnToMccMnc(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
struct in_addr conv::fromString(const std::string addr4) { struct in_addr conv::fromString(const std::string addr4) {
unsigned char buf[sizeof(struct in6_addr)] = {}; unsigned char buf[sizeof(struct in6_addr)] = {};
int s = inet_pton(AF_INET, addr4.c_str(), buf); struct in_addr ipv4_addr;
struct in_addr* ia = (struct in_addr*) buf; ipv4_addr.s_addr = INADDR_ANY;
return *ia; if (inet_pton(AF_INET, addr4.c_str(), buf) == 1) {
memcpy(&ipv4_addr, buf, sizeof(struct in_addr));
}
return ipv4_addr;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::string conv::toString(const struct in_addr& inaddr) { std::string conv::toString(const struct in_addr& inaddr) {
std::string s = {}; std::string s = {};
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "fqdn.hpp" #include "fqdn.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "string.hpp"
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
...@@ -33,11 +34,11 @@ bool fqdn::resolve( ...@@ -33,11 +34,11 @@ bool fqdn::resolve(
const std::string& host_name, std::string& address, uint32_t& port, const std::string& host_name, std::string& address, uint32_t& port,
uint8_t& addr_type, const std::string& protocol) { uint8_t& addr_type, const std::string& protocol) {
int tries = 0; int tries = 0;
Logger::smf_app().debug("Resolving a DNS (name %s)", host_name.c_str()); // Logger::smf_app().debug("Resolving a DNS (name %s)", host_name.c_str());
while (tries < MAX_NB_RESOLVE_TRIES) { while (tries < MAX_NB_RESOLVE_TRIES) {
try { try {
boost::asio::io_context io_context = {}; boost::asio::io_context io_context = {};
Logger::smf_app().debug("Resolving DNS Try #%u", tries); // Logger::smf_app().debug("Resolving DNS Try #%u", tries + 1);
boost::asio::ip::tcp::resolver resolver{io_context}; boost::asio::ip::tcp::resolver resolver{io_context};
boost::asio::ip::tcp::resolver::results_type endpoints = boost::asio::ip::tcp::resolver::results_type endpoints =
...@@ -73,6 +74,77 @@ bool fqdn::resolve( ...@@ -73,6 +74,77 @@ bool fqdn::resolve(
return false; return false;
} }
bool fqdn::resolve(pfcp::node_id_t& node_id) {
Logger::smf_app().debug("Resolving an FQDN/IP Addr for an UPF node");
// Resolve IP addr from FQDN
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_FQDN) {
// Don't need to do if IP addr already available
if (node_id.u1.ipv4_address.s_addr != INADDR_ANY) return true;
// Resolve if FQDN available
if (!node_id.fqdn.empty()) {
Logger::smf_app().debug("FQDN %s", node_id.fqdn.c_str());
std::string ip_addr_str = {};
uint32_t port = {0};
uint8_t addr_type = {0};
struct in_addr ipv4_addr = {};
if (!fqdn::resolve(node_id.fqdn, ip_addr_str, port, addr_type)) {
Logger::smf_app().warn(
"Resolve FQDN %s: cannot resolve the hostname!",
node_id.fqdn.c_str());
return false;
}
switch (addr_type) {
case 0: {
node_id.u1.ipv4_address.s_addr = conv::fromString(ip_addr_str).s_addr;
Logger::smf_app().debug(
"Resolve FQDN %s, IP Addr %s", node_id.fqdn.c_str(),
ip_addr_str.c_str());
} break;
case 1: {
// TODO
Logger::smf_app().warn(
"Resolve FQDN: %s. IPv6 Addr, this mode has not been "
"supported yet!",
node_id.fqdn.c_str());
return false;
} break;
default:
Logger::smf_app().warn("Unknown Address type");
return false;
}
} else {
return false; // No FQDN available
}
// Resolve hostname from an IP Addr
} else if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
// Don't need to do reserve_resolve if FQDN is already available
if (!node_id.fqdn.empty()) {
return true;
} else {
std::string hostname = {};
std::string ip_str = conv::toString(node_id.u1.ipv4_address);
if (!fqdn::reverse_resolve(ip_str, hostname)) {
Logger::smf_app().warn(
"Could not resolve hostname for IP address %s", ip_str.c_str());
return false;
} else {
node_id.fqdn = hostname;
Logger::smf_app().debug(
"Resolve IP Addr %s, FQDN %s", ip_str.c_str(),
node_id.fqdn.c_str());
}
return true;
}
} else {
// Don't support IPv6 for the moment
return false;
}
return true;
}
bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) { bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) {
Logger::smf_app().debug("Resolving an IP address (name %s)", ip_addr.c_str()); Logger::smf_app().debug("Resolving an IP address (name %s)", ip_addr.c_str());
int tries = 0; int tries = 0;
...@@ -107,4 +179,4 @@ bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) { ...@@ -107,4 +179,4 @@ bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) {
} }
} }
return false; return false;
} }
\ No newline at end of file
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#ifndef FILE_FQDN_HPP_SEEN #ifndef FILE_FQDN_HPP_SEEN
#define FILE_FQDN_HPP_SEEN #define FILE_FQDN_HPP_SEEN
#include <string> #include <string>
#include "3gpp_29.244.h"
class fqdn { class fqdn {
public: public:
/* /*
...@@ -41,6 +42,7 @@ class fqdn { ...@@ -41,6 +42,7 @@ class fqdn {
const std::string& host_name, std::string& address, uint32_t& port, const std::string& host_name, std::string& address, uint32_t& port,
uint8_t& addr_type, const std::string& protocol = "http"); uint8_t& addr_type, const std::string& protocol = "http");
static bool resolve(pfcp::node_id_t& node_id);
/** /**
* @brief Resolves an IP address to get the hostname * @brief Resolves an IP address to get the hostname
* @param ip_address to resolve * @param ip_address to resolve
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "common_types.h"
#include "TLVEncoder.h" #include "TLVEncoder.h"
#include "TLVDecoder.h" #include "TLVDecoder.h"
#include "ProcedureTransactionIdentity.h" #include "ProcedureTransactionIdentity.h"
...@@ -30,54 +31,17 @@ ...@@ -30,54 +31,17 @@
int encode_procedure_transaction_identity( int encode_procedure_transaction_identity(
ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei, ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei,
uint8_t* buffer, uint32_t len) { uint8_t* buffer, uint32_t len) {
uint32_t encoded = 0; uint8_t encoded = 0;
int encode_result;
CHECK_PDU_POINTER_AND_LENGTH_ENCODER( CHECK_PDU_POINTER_AND_LENGTH_ENCODER(
buffer, PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH, len); buffer, PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH, len);
ENCODE_U8(buffer + encoded, (uint8_t) proceduretransactionidentity, encoded);
if ((encode_result = encode_bstring(
proceduretransactionidentity, buffer + encoded, len - encoded)) < 0)
return encode_result;
else
encoded += encode_result;
return encoded; return encoded;
/*
uint32_t encoded = 0;
uint8_t bitStream = 0x0;
CHECK_PDU_POINTER_AND_LENGTH_ENCODER (buffer,
PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH, len);
if(iei > 0){
bitStream = 0x00 | (iei & 0xf0) | (proceduretransactionidentity & 0x0f);
}
ENCODE_U8(buffer + encoded, bitStream, encoded);
return encoded;
*/
} }
int decode_procedure_transaction_identity( int decode_procedure_transaction_identity(
ProcedureTransactionIdentity* proceduretransactionidentity, uint8_t iei, ProcedureTransactionIdentity* proceduretransactionidentity, uint8_t iei,
uint8_t* buffer, uint32_t len) { uint8_t* buffer, uint32_t len) {
int decoded = 0; int decoded = 0;
uint8_t ielen = 0; DECODE_U8(buffer + decoded, proceduretransactionidentity, decoded);
int decode_result;
if ((decode_result = decode_bstring(
proceduretransactionidentity, ielen, buffer + decoded,
len - decoded)) < 0)
return decode_result;
else
decoded += decode_result;
return decoded; return decoded;
/*
int decoded = 0;
uint8_t bitStream = 0x0;
DECODE_U8(buffer + decoded, bitStream, decoded);
if(iei != (bitStream & 0xf0))
return -1;
*proceduretransactionidentity = bitStream & 0x0f;
return decoded;
*/
} }
...@@ -20,12 +20,11 @@ ...@@ -20,12 +20,11 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "bstrlib.h"
#define PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH 1 #define PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH 1
#define PROCEDURE_TRANSACTION_IDENTITY_MAXIMUM_LENGTH 1 #define PROCEDURE_TRANSACTION_IDENTITY_MAXIMUM_LENGTH 1
typedef bstring ProcedureTransactionIdentity; typedef uint8_t ProcedureTransactionIdentity;
int encode_procedure_transaction_identity( int encode_procedure_transaction_identity(
ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei, ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei,
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <cstring> #include <cstring>
#include <endian.h> #include <endian.h>
#include <exception> #include <exception>
//#include <fmt/format.h> conflicts with spdlog // #include <fmt/format.h> conflicts with spdlog
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
...@@ -735,29 +735,26 @@ class pfcp_fteid_ie : public pfcp_ie { ...@@ -735,29 +735,26 @@ class pfcp_fteid_ie : public pfcp_ie {
//-------- //--------
explicit pfcp_fteid_ie(const pfcp::fteid_t& b) : pfcp_ie(PFCP_IE_F_TEID) { explicit pfcp_fteid_ie(const pfcp::fteid_t& b) : pfcp_ie(PFCP_IE_F_TEID) {
tlv.set_length(1); tlv.set_length(1);
u1.b = 0; u1.b = 0;
u1.bf.ch = b.ch; u1.bf.ch = b.ch;
u1.bf.chid = b.chid; u1.bf.chid = b.chid;
teid = b.teid; teid = b.teid;
ipv4_address = b.ipv4_address;
ipv6_address = b.ipv6_address;
if (!u1.bf.ch) { if (!u1.bf.ch) {
tlv.add_length(4); // teid tlv.add_length(4); // teid
u1.bf.v4 = b.v4; u1.bf.v4 = b.v4;
u1.bf.v6 = b.v6; u1.bf.v6 = b.v6;
if (u1.bf.v4) { if (u1.bf.v4) {
tlv.add_length(4); tlv.add_length(4);
ipv4_address = b.ipv4_address;
} }
if (u1.bf.v6) { if (u1.bf.v6) {
tlv.add_length(16); tlv.add_length(16);
ipv6_address = b.ipv6_address;
} }
}
if (u1.bf.ch & b.v4) {
u1.bf.v4 = b.v4;
} else { } else {
ipv4_address.s_addr = INADDR_ANY; if (u1.bf.ch & b.v4) {
ipv6_address = in6addr_any; u1.bf.v4 = b.v4;
// else should clear v4 v6 bits }
if (u1.bf.chid) { if (u1.bf.chid) {
choose_id = b.choose_id; choose_id = b.choose_id;
tlv.add_length(1); tlv.add_length(1);
...@@ -948,7 +945,7 @@ class pfcp_sdf_filter_ie : public pfcp_ie { ...@@ -948,7 +945,7 @@ class pfcp_sdf_filter_ie : public pfcp_ie {
u1.bf.fl = b.fl; u1.bf.fl = b.fl;
u1.bf.bid = b.bid; u1.bf.bid = b.bid;
if (u1.bf.fd) { if (u1.bf.fd) {
length_of_flow_description = b.length_of_flow_description; length_of_flow_description = b.flow_description.length();
flow_description = b.flow_description; flow_description = b.flow_description;
tlv.add_length( tlv.add_length(
sizeof(length_of_flow_description) + flow_description.size()); sizeof(length_of_flow_description) + flow_description.size());
......
This diff is collapsed.
...@@ -114,22 +114,10 @@ class smf_app { ...@@ -114,22 +114,10 @@ class smf_app {
mutable std::shared_mutex m_scid2smf_context; mutable std::shared_mutex m_scid2smf_context;
mutable std::shared_mutex m_smf_event_subscriptions; mutable std::shared_mutex m_smf_event_subscriptions;
// Store promise IDs for Create/Update session // Store promise IDs for Create/Update session
mutable std::shared_mutex m_sm_context_create_promises; mutable std::shared_mutex m_sbi_server_promises;
mutable std::shared_mutex m_sm_context_update_promises;
mutable std::shared_mutex m_sm_context_release_promises;
std::map< std::map<uint32_t, boost::shared_ptr<boost::promise<nlohmann::json>>>
uint32_t, sbi_server_promises;
boost::shared_ptr<boost::promise<pdu_session_create_sm_context_response>>>
sm_context_create_promises;
std::map<
uint32_t,
boost::shared_ptr<boost::promise<pdu_session_update_sm_context_response>>>
sm_context_update_promises;
std::map<
uint32_t, boost::shared_ptr<
boost::promise<pdu_session_release_sm_context_response>>>
sm_context_release_promises;
smf_profile nf_instance_profile; // SMF profile smf_profile nf_instance_profile; // SMF profile
std::string smf_instance_id; // SMF instance id std::string smf_instance_id; // SMF instance id
...@@ -726,32 +714,25 @@ class smf_app { ...@@ -726,32 +714,25 @@ class smf_app {
p); p);
/* /*
* To store a promise of a PDU Session Update SM Contex Response to be * To store a promise of a SBI Server response message to be
* triggered when the result is ready * triggered when the result is ready
* @param [uint32_t] id: promise id * @param [uint32_t] id: promise id
* @param [boost::shared_ptr< * @param [boost::shared_ptr<
* boost::promise<pdu_session_update_sm_context_response> >&] p: pointer to * boost::promise<nlohmann::json> >&] p: pointer to
* the promise * the promise
* @return void * @return void
*/ */
void add_promise( void add_promise(
uint32_t id, uint32_t id, boost::shared_ptr<boost::promise<nlohmann::json>>& p);
boost::shared_ptr<boost::promise<pdu_session_update_sm_context_response>>&
p);
/* /*
* To store a promise of a PDU Session Release SM Context Response to be * To generate promise ID across SMF components
* triggered when the result is ready * @param void
* @param [uint32_t] id: promise id * @return generated ID
* @param [boost::shared_ptr<
* boost::promise<pdu_session_release_sm_context_response> >&] p: pointer to
* the promise
* @return void
*/ */
void add_promise( static uint64_t generate_promise_id() {
uint32_t id, return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
boost::shared_ptr< }
boost::promise<pdu_session_release_sm_context_response>>& p);
/* /*
* To trigger the response to the HTTP server by set the value of the * To trigger the response to the HTTP server by set the value of the
...@@ -790,6 +771,17 @@ class smf_app { ...@@ -790,6 +771,17 @@ class smf_app {
const uint32_t& http_code, const uint8_t& cause, const uint32_t& http_code, const uint8_t& cause,
const std::string& n1_sm_msg, uint32_t& promise_id); const std::string& n1_sm_msg, uint32_t& promise_id);
/*
* To trigger the response to the HTTP server by set the value of the
* corresponding promise to ready
* @param [const nlohmann::json&] response_message_json: response message in
* JSON format
* @param [uint32_t &] promise_id: Promise Id
* @return void
*/
void trigger_http_response(
const nlohmann::json& response_message_json, uint32_t& pid);
/* /*
* To trigger the response to the HTTP server by set the value of the * To trigger the response to the HTTP server by set the value of the
* corresponding promise to ready * corresponding promise to ready
...@@ -825,18 +817,6 @@ class smf_app { ...@@ -825,18 +817,6 @@ class smf_app {
pdu_session_update_sm_context_response& sm_context_response, pdu_session_update_sm_context_response& sm_context_response,
uint32_t& pid); uint32_t& pid);
/*
* To trigger the session release sm context response by set the value of the
* corresponding promise to ready
* @param [pdu_session_release_sm_context_response&] sm_context_response:
* response message
* @param [uint32_t &] promise_id: Promise Id
* @return void
*/
void trigger_session_release_sm_context_response(
pdu_session_release_sm_context_response& sm_context_response,
uint32_t& pid);
/* /*
* Add an Event Subscription to the list * Add an Event Subscription to the list
* @param [const evsub_id_t&] sub_id: Subscription ID * @param [const evsub_id_t&] sub_id: Subscription ID
...@@ -924,6 +904,13 @@ class smf_app { ...@@ -924,6 +904,13 @@ class smf_app {
* @return void * @return void
*/ */
void trigger_upf_status_notification_subscribe(); void trigger_upf_status_notification_subscribe();
/*
* Get the SMF instance ID
* @param [void]
* @return SMF instance ID
*/
std::string get_smf_instance_id() const;
}; };
} // namespace smf } // namespace smf
#include "smf_config.hpp" #include "smf_config.hpp"
......
...@@ -1044,10 +1044,12 @@ void smf_config::display() { ...@@ -1044,10 +1044,12 @@ void smf_config::display() {
Logger::smf_app().info(" Secondary DNS v6 ....: %s", str_addr6); Logger::smf_app().info(" Secondary DNS v6 ....: %s", str_addr6);
} }
Logger::smf_app().info("- CSCF:");
Logger::smf_app().info( Logger::smf_app().info(
" CSCF .........: %s", inet_ntoa(*((struct in_addr*) &default_cscfv4))); " CSCF IPv4 ...........: %s",
inet_ntoa(*((struct in_addr*) &default_cscfv4)));
if (inet_ntop(AF_INET6, &default_cscfv6, str_addr6, sizeof(str_addr6))) { if (inet_ntop(AF_INET6, &default_cscfv6, str_addr6, sizeof(str_addr6))) {
Logger::smf_app().info(" CSCF v6 ......: %s", str_addr6); Logger::smf_app().info(" CSCF IPv6 ...........: %s", str_addr6);
} }
Logger::smf_app().info("- Default UE MTU: %d", ue_mtu); Logger::smf_app().info("- Default UE MTU: %d", ue_mtu);
......
This diff is collapsed.
...@@ -614,7 +614,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -614,7 +614,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
// Subscribe to PDU Session Release (event exposure) // Subscribe to PDU Session Release (event exposure)
ee_pdu_session_release_connection = ee_pdu_session_release_connection =
event_sub.subscribe_ee_pdu_session_release(boost::bind( event_sub.subscribe_ee_pdu_session_release(boost::bind(
&smf_context::handle_ee_pdu_session_release, this, _1, _2, _3)); &smf_context::handle_ee_pdu_session_release, this, _1, _2));
// Subscribe to UE IP Change Event // Subscribe to UE IP Change Event
ee_ue_ip_change_connection = event_sub.subscribe_ee_ue_ip_change( ee_ue_ip_change_connection = event_sub.subscribe_ee_ue_ip_change(
...@@ -885,7 +885,8 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -885,7 +885,8 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
*/ */
bool handle_pdu_session_resource_release_response_transfer( bool handle_pdu_session_resource_release_response_transfer(
std::string& n2_sm_information, std::string& n2_sm_information,
std::shared_ptr<itti_n11_update_sm_context_request>& sm_context_request); std::shared_ptr<itti_n11_update_sm_context_request>& sm_context_request,
std::shared_ptr<smf_pdu_session>& sp);
/* /*
* Handle Xn Handover Patch Switch Request * Handle Xn Handover Patch Switch Request
...@@ -1172,6 +1173,31 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -1172,6 +1173,31 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void get_pdu_sessions( void get_pdu_sessions(
std::map<pdu_session_id_t, std::shared_ptr<smf_pdu_session>>& sessions); std::map<pdu_session_id_t, std::shared_ptr<smf_pdu_session>>& sessions);
/*
* Get PDU related information
* @param [const scid_t&] scid: SMF Context ID
* @param [supi64_t&] supi: SUPI
* @param [pdu_session_id_t&] pdu_session_id: PDU Session ID
* @return true if this Context ID exist and can get related info, otherwise,
* return false
*/
bool get_pdu_session_info(
const scid_t& scid, supi64_t& supi,
pdu_session_id_t& pdu_session_id) const;
/*
* Get PDU related information
* @param [const scid_t&] scid: SMF Context ID
* @param [supi64_t&] supi: SUPI
* @param [std::shared_ptr<smf_pdu_session>&] sp: Pointer to the PDU Session
* Info
* @return true if this Context ID exist and can get related info, otherwise,
* return false
*/
bool get_pdu_session_info(
const scid_t& scid, supi64_t& supi,
std::shared_ptr<smf_pdu_session>& sp) const;
/* /*
* Handle SM Context Status Change (Send notification AMF) * Handle SM Context Status Change (Send notification AMF)
* @param [scid_t] scid: SMF Context ID * @param [scid_t] scid: SMF Context ID
...@@ -1180,39 +1206,50 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -1180,39 +1206,50 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
* @return void * @return void
*/ */
void handle_sm_context_status_change( void handle_sm_context_status_change(
scid_t scid, const std::string& status, uint8_t http_version); const scid_t& scid, const std::string& status,
const uint8_t& http_version) const;
/* /*
* Handle SM Context Status Change (Send notification AMF) * Trigger PDU Session Release Notification (Send notification AMF)
* @param [scid_t] scid: SMF Context ID * @param [scid_t] scid: SMF Context ID
* @param [uint32_t] status: Updated status
* @param [uint8_t] http_version: HTTP version * @param [uint8_t] http_version: HTTP version
* @return void * @return void
*/ */
void trigger_pdu_session_release(
const scid_t& scid, const uint8_t& http_version) const;
void handle_ee_pdu_session_release( void handle_ee_pdu_session_release(
supi64_t supi, pdu_session_id_t pdu_session_id, uint8_t http_version); const scid_t& scid, const uint8_t& http_version) const;
void trigger_ue_ip_change(scid_t scid, uint8_t http_version); void trigger_ue_ip_change(
void handle_ue_ip_change(scid_t scid, uint8_t http_version); const scid_t& scid, const uint8_t& http_version) const;
void handle_ue_ip_change(
const scid_t& scid, const uint8_t& http_version) const;
void trigger_plmn_change(scid_t scid, uint8_t http_version); void trigger_plmn_change(
void handle_plmn_change(scid_t scid, uint8_t http_version); const scid_t& scid, const uint8_t& http_version) const;
void handle_plmn_change(
const scid_t& scid, const uint8_t& http_version) const;
void trigger_ddds(scid_t scid, uint8_t http_version); void trigger_ddds(const scid_t& scid, const uint8_t& http_version) const;
void handle_ddds(scid_t scid, uint8_t http_version); void handle_ddds(const scid_t& scid, const uint8_t& http_version) const;
void trigger_pdusesest(scid_t scid, uint8_t http_version); void trigger_pdusesest(const scid_t& scid, const uint8_t& http_version) const;
void handle_pdusesest(scid_t scid, uint8_t http_version); void handle_pdusesest(const scid_t& scid, const uint8_t& http_version) const;
void trigger_qos_monitoring( void trigger_qos_monitoring(
seid_t seid, oai::smf_server::model::EventNotification ev_notif_model, const seid_t& seid,
uint8_t http_version); const oai::smf_server::model::EventNotification& ev_notif_model,
const uint8_t& http_version) const;
void handle_qos_monitoring( void handle_qos_monitoring(
seid_t seid, oai::smf_server::model::EventNotification ev_notif_model, const seid_t& seid,
uint8_t http_version); const oai::smf_server::model::EventNotification& ev_notif_model,
const uint8_t& http_version) const;
void trigger_flexcn_event(
const scid_t& scid, const uint8_t& http_version) const;
void handle_flexcn_event(
const scid_t& scid, const uint8_t& http_version) const;
void trigger_flexcn_event(scid_t scid, uint8_t http_version);
void handle_flexcn_event(scid_t scid, uint8_t http_version);
/* /*
* Update QoS information in the Response message according to the content of * Update QoS information in the Response message according to the content of
* decoded NAS msg * decoded NAS msg
...@@ -1315,6 +1352,34 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -1315,6 +1352,34 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
const ng_ran_target_id_t& ran_target_id, const ng_ran_target_id_t& ran_target_id,
const pdu_session_id_t& pdu_session_id) const; const pdu_session_id_t& pdu_session_id) const;
/**
* Send a PDU session Create Response, based on the content of resp.
* @param resp
*/
void send_pdu_session_create_response(
const std::shared_ptr<itti_n11_create_sm_context_response>& resp);
/**
* Create a PDU session UPDATE response, based on the content of resp
* @param resp
* @pram session_procedure_type The session procedure type of this reply
*/
void send_pdu_session_update_response(
const std::shared_ptr<itti_n11_update_sm_context_request>& req,
const std::shared_ptr<itti_n11_update_sm_context_response>& resp,
const session_management_procedures_type_e& session_procedure_type,
const std::shared_ptr<smf_pdu_session>& sps);
/**
* Create a PDU session Release response, based on the content of resp
* @param resp
*/
void send_pdu_session_release_response(
const std::shared_ptr<itti_n11_release_sm_context_request>& req,
const std::shared_ptr<itti_n11_release_sm_context_response>& resp,
const session_management_procedures_type_e& session_procedure_type,
const std::shared_ptr<smf_pdu_session>& sps);
private: private:
std::vector<std::shared_ptr<smf_procedure>> pending_procedures; std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
// snssai <-> session management subscription // snssai <-> session management subscription
......
...@@ -46,10 +46,9 @@ typedef bs2::signal_type< ...@@ -46,10 +46,9 @@ typedef bs2::signal_type<
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type sm_context_status_sig_t; bs2::keywords::mutex_type<bs2::dummy_mutex>>::type sm_context_status_sig_t;
// Signal for Event exposure // Signal for Event exposure
// PDU session Release, SUPI, PDU SessionID, HTTP version // PDU session Release, SCID, HTTP version
typedef bs2::signal_type< typedef bs2::signal_type<
void(supi64_t, pdu_session_id_t, uint8_t), void(scid_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_pdu_session_release_sig_t; ee_pdu_session_release_sig_t;
// TODO: ee_ue_ip_address_change_sig_t; //UI IP Address, UE ID // TODO: ee_ue_ip_address_change_sig_t; //UI IP Address, UE ID
......
...@@ -218,6 +218,85 @@ bool pdu_session_msg::n2_sm_info_type_is_set() const { ...@@ -218,6 +218,85 @@ bool pdu_session_msg::n2_sm_info_type_is_set() const {
return m_n2_sm_info_type_is_set; return m_n2_sm_info_type_is_set;
} }
//-----------------------------------------------------------------------------
void pdu_session_msg::to_json(nlohmann::json& data) const {
data["msg_type"] = m_msg_type;
data["api_root"] = m_api_root;
std::string supi_str = smf_supi_to_string(m_supi);
data["supi"] = supi_str;
data["supi_prefix"] = m_supi_prefix;
data["pdu_session_id"] = m_pdu_session_id;
data["dnn"] = m_dnn;
data["snssai"]["sst"] = m_snssai.sst;
data["snssai"]["sd"] = m_snssai.sd;
data["pdu_session_type"] = m_pdu_session_type;
data["procedure_transaction_id"] = m_pti.procedure_transaction_id;
if (m_n1_sm_msg_is_set) data["n1_sm_message"] = m_n1_sm_message;
if (m_n2_sm_info_is_set) data["n2_sm_information"] = m_n2_sm_information;
if (m_n2_sm_info_type_is_set) data["n2_sm_info_type"] = m_n2_sm_info_type;
}
//-----------------------------------------------------------------------------
void pdu_session_msg::from_json(const nlohmann::json& data) {
if (data.find("msg_type") != data.end()) {
m_msg_type =
static_cast<pdu_session_msg_type_t>(data["msg_type"].get<int>());
}
if (data.find("api_root") != data.end()) {
m_api_root = data["api_root"].get<std::string>();
}
if (data.find("supi") != data.end()) {
smf_string_to_supi(&m_supi, data["supi"].get<std::string>().c_str());
}
if (data.find("supi_prefix") != data.end()) {
m_supi_prefix = data["supi_prefix"].get<std::string>();
}
if (data.find("pdu_session_id") != data.end()) {
m_pdu_session_id = data["pdu_session_id"].get<int>();
}
if (data.find("dnn") != data.end()) {
m_dnn = data["dnn"].get<std::string>();
}
if (data.find("snssai") != data.end()) {
if (data["snssai"].find("sst") != data["snssai"].end()) {
m_snssai.sst = data["snssai"]["sst"].get<int>();
}
}
if (data.find("snssai") != data.end()) {
if (data["snssai"].find("sd") != data["snssai"].end()) {
m_snssai.sd = data["snssai"]["sd"].get<int>();
}
}
if (data.find("pdu_session_type") != data.end()) {
m_pdu_session_type = data["pdu_session_type"].get<int>();
}
if (data.find("procedure_transaction_id") != data.end()) {
m_pti.procedure_transaction_id =
data["procedure_transaction_id"].get<int>();
}
if (data.find("n1_sm_message") != data.end()) {
m_n1_sm_message = data["n1_sm_message"].get<std::string>();
m_n1_sm_msg_is_set = true;
}
if (data.find("n2_sm_information") != data.end()) {
m_n2_sm_information = data["n2_sm_information"].get<std::string>();
m_n2_sm_info_is_set = true;
}
if (data.find("n2_sm_info_type") != data.end()) {
m_n2_sm_info_type = data["n2_sm_info_type"].get<std::string>();
m_n2_sm_info_type_is_set = true;
}
}
/* /*
* class: PDU Session SM Context Request * class: PDU Session SM Context Request
*/ */
...@@ -291,6 +370,35 @@ void pdu_session_sm_context_response::get_json_format( ...@@ -291,6 +370,35 @@ void pdu_session_sm_context_response::get_json_format(
format = m_json_format; format = m_json_format;
} }
//-----------------------------------------------------------------------------
void pdu_session_sm_context_response::to_json(nlohmann::json& data) const {
pdu_session_msg::to_json(data);
data["cause"] = m_cause;
data["json_data"] = m_json_data;
data["json_format"] = m_json_format;
data["http_code"] = m_http_code;
}
//-----------------------------------------------------------------------------
void pdu_session_sm_context_response::from_json(const nlohmann::json& data) {
pdu_session_msg::from_json(data);
if (data.find("cause") != data.end()) {
m_cause = data["cause"].get<int>();
}
if (data.find("json_data") != data.end()) {
m_json_data = data["json_data"];
}
if (data.find("json_format") != data.end()) {
m_json_format = data["json_format"];
}
if (data.find("http_code") != data.end()) {
m_http_code = data["http_code"].get<int>();
}
}
/* /*
* class: PDU Session Create SM Context Request * class: PDU Session Create SM Context Request
*/ */
...@@ -449,6 +557,31 @@ void pdu_session_create_sm_context_response::get_epco( ...@@ -449,6 +557,31 @@ void pdu_session_create_sm_context_response::get_epco(
p = m_epco; p = m_epco;
} }
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_response::to_json(
nlohmann::json& data) const {
pdu_session_sm_context_response::to_json(data);
// TODO: paa_t m_paa
// TODO: qos_flow_context_updated m_qos_flow_context
// TODO: protocol_configuration_options_t m_epco
data["amf_url"] = m_amf_url;
data["smf_context_uri"] = m_smf_context_uri;
}
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_response::from_json(
const nlohmann::json& data) {
// TODO: paa_t m_paa
// TODO: qos_flow_context_updated m_qos_flow_context
// TODO: protocol_configuration_options_t m_epco
if (data.find("amf_url") != data.end()) {
m_amf_url = data["amf_url"].get<std::string>();
}
if (data.find("smf_context_uri") != data.end()) {
m_smf_context_uri = data["smf_context_uri"].get<std::string>();
}
}
/* /*
* class: PDU Session Update SM Context Request * class: PDU Session Update SM Context Request
*/ */
...@@ -689,29 +822,37 @@ std::string pdu_session_update_sm_context_response::get_smf_context_uri() ...@@ -689,29 +822,37 @@ std::string pdu_session_update_sm_context_response::get_smf_context_uri()
return m_smf_context_uri; return m_smf_context_uri;
} }
/*
* class: PDU Session Release SM Context Response
*/
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::set_cause(uint8_t cause) { void pdu_session_update_sm_context_response::to_json(
m_cause = cause; nlohmann::json& data) const {
pdu_session_sm_context_response::to_json(data);
// TODO: qos_flow_context_updateds
data["smf_context_uri"] = m_smf_context_uri;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uint8_t pdu_session_release_sm_context_response::get_cause() { void pdu_session_update_sm_context_response::from_json(
return m_cause; const nlohmann::json& data) {
pdu_session_sm_context_response::from_json(data);
// TODO: qos_flow_context_updateds
if (data.find("smf_context_uri") != data.end()) {
m_smf_context_uri = data["smf_context_uri"].get<std::string>();
}
} }
/*
* class: PDU Session Release SM Context Response
*/
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::set_http_code( void pdu_session_release_sm_context_response::to_json(
const uint32_t code) { nlohmann::json& data) const {
m_http_code = code; pdu_session_sm_context_response::to_json(data);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uint32_t pdu_session_release_sm_context_response::get_http_code() const { void pdu_session_release_sm_context_response::from_json(
return m_http_code; const nlohmann::json& data) {
pdu_session_sm_context_response::from_json(data);
} }
/* /*
......
...@@ -161,6 +161,9 @@ class pdu_session_msg { ...@@ -161,6 +161,9 @@ class pdu_session_msg {
void set_n2_sm_info_type(const std::string& value); void set_n2_sm_info_type(const std::string& value);
bool n2_sm_info_type_is_set() const; bool n2_sm_info_type_is_set() const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private: private:
pdu_session_msg_type_t m_msg_type; pdu_session_msg_type_t m_msg_type;
std::string m_api_root; std::string m_api_root;
...@@ -236,6 +239,9 @@ class pdu_session_sm_context_response : public pdu_session_msg { ...@@ -236,6 +239,9 @@ class pdu_session_sm_context_response : public pdu_session_msg {
void set_json_format(const std::string& format); void set_json_format(const std::string& format);
void get_json_format(std::string& format) const; void get_json_format(std::string& format) const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private: private:
uint8_t m_cause; uint8_t m_cause;
nlohmann::json m_json_data; nlohmann::json m_json_data;
...@@ -323,6 +329,9 @@ class pdu_session_create_sm_context_response ...@@ -323,6 +329,9 @@ class pdu_session_create_sm_context_response
void set_epco(const protocol_configuration_options_t& p); void set_epco(const protocol_configuration_options_t& p);
void get_epco(protocol_configuration_options_t& p) const; void get_epco(protocol_configuration_options_t& p) const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private: private:
paa_t m_paa; paa_t m_paa;
qos_flow_context_updated m_qos_flow_context; qos_flow_context_updated m_qos_flow_context;
...@@ -440,6 +449,9 @@ class pdu_session_update_sm_context_response ...@@ -440,6 +449,9 @@ class pdu_session_update_sm_context_response
void set_smf_context_uri(const std::string& value); void set_smf_context_uri(const std::string& value);
std::string get_smf_context_uri() const; std::string get_smf_context_uri() const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private: private:
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds; std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds;
std::string m_smf_context_uri; std::string m_smf_context_uri;
...@@ -464,21 +476,17 @@ class pdu_session_release_sm_context_request : public pdu_session_msg { ...@@ -464,21 +476,17 @@ class pdu_session_release_sm_context_request : public pdu_session_msg {
}; };
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
class pdu_session_release_sm_context_response : public pdu_session_msg { class pdu_session_release_sm_context_response
: public pdu_session_sm_context_response {
public: public:
pdu_session_release_sm_context_response() pdu_session_release_sm_context_response()
: pdu_session_msg(PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE) { : pdu_session_sm_context_response(
m_cause = 0; PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE){};
m_http_code = 0;
}; void to_json(nlohmann::json& data) const;
void set_cause(uint8_t cause); void from_json(const nlohmann::json& data);
uint8_t get_cause();
void set_http_code(const uint32_t code);
uint32_t get_http_code() const;
private: private:
uint8_t m_cause;
uint32_t m_http_code;
}; };
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
......
...@@ -717,6 +717,75 @@ bool smf_n1::create_n1_pdu_session_release_reject( ...@@ -717,6 +717,75 @@ bool smf_n1::create_n1_pdu_session_release_reject(
} }
} }
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_command(
const std::shared_ptr<pdu_session_msg>& msg, std::string& nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_n1().info("Create N1 SM Container, PDU Session Release Command");
int bytes = {0};
unsigned char data[BUF_LEN] = {'\0'};
nas_message_t nas_msg = {};
nas_msg.header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
SM_msg* sm_msg = &nas_msg.plain.sm;
// Fill the content of SM header
sm_msg->header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
sm_msg->header.pdu_session_identity = msg->get_pdu_session_id();
Logger::smf_n1().info("PDU_SESSION_RELEASE_COMMAND, encode starting...");
// Fill the content of PDU Session Release Command
sm_msg->header.pdu_session_identity = msg->get_pdu_session_id();
sm_msg->header.procedure_transaction_identity =
msg->get_pti()
.procedure_transaction_id; // TODO: if PDU session release procedure
// is not triggered by a UE-requested PDU
// session release set the PTI IE of the
// PDU SESSION RELEASE COMMAND message
// to "No procedure transaction identity
// assigned"
sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
sm_msg->pdu_session_release_command._5gsmcause =
static_cast<uint8_t>(sm_cause);
// TODO: to be updated when adding the following IEs
sm_msg->pdu_session_release_command.presence = 0x00;
// GPRSTimer3
// EAPMessage
//_5GSMCongestionReattemptIndicator
// ExtendedProtocolConfigurationOptions
Logger::smf_n1().debug(
"SM message, PDU Session ID %d, PTI %d, Message Type %0x%x, 5GSM Cause: "
"0x%x",
sm_msg->header.pdu_session_identity,
sm_msg->header.procedure_transaction_identity,
sm_msg->header.message_type,
sm_msg->pdu_session_release_command._5gsmcause);
// Encode NAS message
bytes = nas_message_encode(
data, &nas_msg, sizeof(data) /*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_n1().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++) printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0) {
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
return true;
} else {
return false;
}
}
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_command( bool smf_n1::create_n1_pdu_session_release_command(
pdu_session_update_sm_context_response& sm_context_res, pdu_session_update_sm_context_response& sm_context_res,
...@@ -744,7 +813,13 @@ bool smf_n1::create_n1_pdu_session_release_command( ...@@ -744,7 +813,13 @@ bool smf_n1::create_n1_pdu_session_release_command(
// Fill the content of PDU Session Release Command // Fill the content of PDU Session Release Command
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id(); sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
sm_msg->header.procedure_transaction_identity = sm_msg->header.procedure_transaction_identity =
sm_context_res.get_pti().procedure_transaction_id; sm_context_res.get_pti()
.procedure_transaction_id; // TODO: if PDU session release procedure
// is not triggered by a UE-requested PDU
// session release set the PTI IE of the
// PDU SESSION RELEASE COMMAND message
// to "No procedure transaction identity
// assigned"
sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND; sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
sm_msg->pdu_session_release_command._5gsmcause = sm_msg->pdu_session_release_command._5gsmcause =
static_cast<uint8_t>(sm_cause); static_cast<uint8_t>(sm_cause);
......
...@@ -135,6 +135,9 @@ class smf_n1 { ...@@ -135,6 +135,9 @@ class smf_n1 {
pdu_session_update_sm_context_request& sm_context_res, pdu_session_update_sm_context_request& sm_context_res,
std::string& nas_msg_str, cause_value_5gsm_e sm_cause); std::string& nas_msg_str, cause_value_5gsm_e sm_cause);
bool create_n1_pdu_session_release_command(
const std::shared_ptr<pdu_session_msg>& msg, std::string& nas_msg_str,
cause_value_5gsm_e sm_cause);
/* /*
* Create N1 SM Container: PDU Session Release Command * Create N1 SM Container: PDU Session Release Command
* Included in PDU Session Update SM Context Response (PDU Session Release * Included in PDU Session Update SM Context Response (PDU Session Release
......
...@@ -231,7 +231,7 @@ bool smf_n2::create_n2_pdu_session_resource_setup_request_transfer( ...@@ -231,7 +231,7 @@ bool smf_n2::create_n2_pdu_session_resource_setup_request_transfer(
.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc( .choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t))); 1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi; .choice.nonDynamic5QI->fiveQI = (uint8_t) DEFAULT_5QI;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.priorityLevelARP = .allocationAndRetentionPriority.priorityLevelARP =
qos_flow.qos_profile.arp.priority_level; qos_flow.qos_profile.arp.priority_level;
...@@ -845,6 +845,55 @@ bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer( ...@@ -845,6 +845,55 @@ bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer(
return result; return result;
} }
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_release_command_transfer(
const std::shared_ptr<pdu_session_msg>& msg,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str) {
Logger::smf_n2().debug(
"Create N2 SM Information: NGAP PDU Session Resource Release Command "
"Transfer IE");
bool result = false;
Ngap_PDUSessionResourceReleaseCommandTransfer_t*
ngap_resource_release_command_transfer = nullptr;
ngap_resource_release_command_transfer =
(Ngap_PDUSessionResourceReleaseCommandTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceReleaseCommandTransfer_t));
// TODO: To be completed, here's an example
ngap_resource_release_command_transfer->cause.present =
Ngap_Cause_PR_radioNetwork;
ngap_resource_release_command_transfer->cause.choice.radioNetwork = 1;
// encode
size_t buffer_size = BUF_LEN;
char* buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceReleaseCommandTransfer, nullptr,
ngap_resource_release_command_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Release Command encode failed (encoded size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++) printf("%02x ", (char) buffer[i]);
Logger::smf_n2().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
// free memory
free_wrapper((void**) &ngap_resource_release_command_transfer);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_release_command_transfer( bool smf_n2::create_n2_pdu_session_resource_release_command_transfer(
pdu_session_update_sm_context_response& sm_context_res, pdu_session_update_sm_context_response& sm_context_res,
......
...@@ -162,6 +162,10 @@ class smf_n2 { ...@@ -162,6 +162,10 @@ class smf_n2 {
pdu_session_update_sm_context_response& sm_context_res, pdu_session_update_sm_context_response& sm_context_res,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str); n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str);
bool create_n2_pdu_session_resource_release_command_transfer(
const std::shared_ptr<pdu_session_msg>& msg,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str);
/* /*
* Create N2 SM Information: PDU Session Resource Release Command Transfer IE * Create N2 SM Information: PDU Session Resource Release Command Transfer IE
* This IE is included in the following messages: * This IE is included in the following messages:
......
...@@ -197,51 +197,51 @@ int smf_app::process_pco_request_ipcp( ...@@ -197,51 +197,51 @@ int smf_app::process_pco_request_ipcp(
* returning the IP address of a valid DNS server. * returning the IP address of a valid DNS server.
* By default, no secondary DNS address is provided. * By default, no secondary DNS address is provided.
*/ */
Logger::smf_app().debug( /* Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option " "PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS length %u", "SECONDARY_DNS_SERVER_IP_ADDRESS length %u",
ipcp_req_option_length); ipcp_req_option_length);
if (ipcp_req_option_length >= 6) { if (ipcp_req_option_length >= 6) {
ipcp_dns_sec_ipv4_addr = htonl( ipcp_dns_sec_ipv4_addr = htonl(
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 2)) (((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 2))
<< 24) | << 24) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 3)) (((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 3))
<< 16) | << 16) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 4)) (((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 4))
<< 8) | << 8) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 5)))); (((uint32_t) poc_id->protocol_id_contents.at(pco_in_index +
Logger::smf_app().debug( 5)))); Logger::smf_app().debug( "PCO: Protocol identifier IPCP option "
"PCO: Protocol identifier IPCP option " "SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_sec_ipv4_addr 0x%x",
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_sec_ipv4_addr 0x%x", ipcp_dns_sec_ipv4_addr);
ipcp_dns_sec_ipv4_addr);
if (ipcp_dns_sec_ipv4_addr == INADDR_ANY) {
if (ipcp_dns_sec_ipv4_addr == INADDR_ANY) { ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr; ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK; } else if (
} else if ( smf_cfg.default_dns_secv4.s_addr != ipcp_dns_sec_ipv4_addr) {
smf_cfg.default_dns_secv4.s_addr != ipcp_dns_sec_ipv4_addr) { ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK; ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr; } else {
} else { ipcp_out_dns_sec_ipv4_addr = ipcp_dns_sec_ipv4_addr;
ipcp_out_dns_sec_ipv4_addr = ipcp_dns_sec_ipv4_addr; }
}
Logger::smf_app().debug(
Logger::smf_app().debug( "PCO: Protocol identifier IPCP option "
"PCO: Protocol identifier IPCP option " "SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_sec_ipv4_addr
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_sec_ipv4_addr 0x%x", 0x%x", ipcp_out_dns_sec_ipv4_addr);
ipcp_out_dns_sec_ipv4_addr); }
} uint8_t ids[6] = {0};
uint8_t ids[6] = {0}; ids[0] = IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS;
ids[0] = IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS; ids[1] = 6;
ids[1] = 6; ids[2] = (uint8_t)(ipcp_out_dns_sec_ipv4_addr & 0x000000FF);
ids[2] = (uint8_t)(ipcp_out_dns_sec_ipv4_addr & 0x000000FF); ids[3] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 8) & 0x000000FF);
ids[3] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 8) & 0x000000FF); ids[4] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 16) & 0x000000FF);
ids[4] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 16) & 0x000000FF); ids[5] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 24) & 0x000000FF);
ids[5] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 24) & 0x000000FF); ipcp_out_length += 6;
ipcp_out_length += 6; std::string tmp_s((const char*) &ids[0], 6);
std::string tmp_s((const char*) &ids[0], 6); poc_id_resp.protocol_id_contents.append(tmp_s);
poc_id_resp.protocol_id_contents.append(tmp_s); */
} break; } break;
default: default:
......
This diff is collapsed.
...@@ -92,6 +92,7 @@ class pfcp_association { ...@@ -92,6 +92,7 @@ class pfcp_association {
timer_association = ITTI_INVALID_TIMER_ID; timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID; timer_graceful_release = ITTI_INVALID_TIMER_ID;
} }
pfcp_association( pfcp_association(
const pfcp::node_id_t& node_id, const pfcp::node_id_t& node_id,
pfcp::recovery_time_stamp_t& recovery_time_stamp) pfcp::recovery_time_stamp_t& recovery_time_stamp)
...@@ -129,6 +130,7 @@ class pfcp_association { ...@@ -129,6 +130,7 @@ class pfcp_association {
timer_association = ITTI_INVALID_TIMER_ID; timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID; timer_graceful_release = ITTI_INVALID_TIMER_ID;
} }
pfcp_association(pfcp_association const& p) pfcp_association(pfcp_association const& p)
: node_id(p.node_id), : node_id(p.node_id),
hash_node_id(p.hash_node_id), hash_node_id(p.hash_node_id),
...@@ -190,8 +192,21 @@ class pfcp_association { ...@@ -190,8 +192,21 @@ class pfcp_association {
bool find_upf_edge( bool find_upf_edge(
const std::shared_ptr<pfcp_association>& other_upf, edge& out_edge); const std::shared_ptr<pfcp_association>& other_upf, edge& out_edge);
/**
* @brief Get the readble name of the UPF associated with this association
* @param void
* @return string representing the name of the UPF associated with this
* association
*/
std::string get_printable_name(); std::string get_printable_name();
/*
* Print related-information for this association
* @param void
* @return void:
*/
void display();
private: private:
bool find_interface_edge( bool find_interface_edge(
const iface_type& type_match, std::vector<edge>& edges); const iface_type& type_match, std::vector<edge>& edges);
...@@ -220,6 +235,7 @@ class smf_qos_flow { ...@@ -220,6 +235,7 @@ class smf_qos_flow {
precedence = {}; precedence = {};
far_id_ul = {}; far_id_ul = {};
far_id_dl = {}; far_id_dl = {};
urr_id = {};
released = false; released = false;
qos_profile = {}; qos_profile = {};
cause_value = 0; cause_value = 0;
...@@ -246,18 +262,21 @@ class smf_qos_flow { ...@@ -246,18 +262,21 @@ class smf_qos_flow {
*/ */
std::string toString() const; std::string toString() const;
[[nodiscard]] std::string toString(const std::string& indent) const;
pfcp::qfi_t qfi; // QoS Flow Identifier pfcp::qfi_t qfi; // QoS Flow Identifier
pfcp::fteid_t ul_fteid; // fteid of UPF pfcp::fteid_t ul_fteid{}; // fteid of UPF
pfcp::fteid_t dl_fteid; // fteid of AN pfcp::fteid_t dl_fteid{}; // fteid of AN
pfcp::pdr_id_t pdr_id_ul; // Packet Detection Rule ID, UL pfcp::pdr_id_t pdr_id_ul; // Packet Detection Rule ID, UL
pfcp::pdr_id_t pdr_id_dl; // Packet Detection Rule ID, DL pfcp::pdr_id_t pdr_id_dl; // Packet Detection Rule ID, DL
pfcp::precedence_t precedence; pfcp::urr_id_t urr_id{}; // Usage reporting Rule, use same for UL and DL
pfcp::precedence_t precedence{};
std::pair<bool, pfcp::far_id_t> far_id_ul; // FAR ID, UL std::pair<bool, pfcp::far_id_t> far_id_ul; // FAR ID, UL
std::pair<bool, pfcp::far_id_t> far_id_dl; // FAR ID, DL std::pair<bool, pfcp::far_id_t> far_id_dl; // FAR ID, DL
bool released; // finally seems necessary, TODO try to find heuristic ? bool released{}; // finally seems necessary, TODO try to find heuristic ?
pdu_session_id_t pdu_session_id; pdu_session_id_t pdu_session_id{};
qos_profile_t qos_profile; // QoS profile qos_profile_t qos_profile; // QoS profile
uint8_t cause_value; // cause uint8_t cause_value{}; // cause
}; };
const std::string DEFAULT_FLOW_DESCRIPTION = const std::string DEFAULT_FLOW_DESCRIPTION =
...@@ -272,7 +291,7 @@ struct edge { ...@@ -272,7 +291,7 @@ struct edge {
std::string nw_instance; std::string nw_instance;
iface_type type; iface_type type;
bool uplink = false; bool uplink = false;
std::vector<smf_qos_flow> qos_flows; std::vector<std::shared_ptr<smf_qos_flow>> qos_flows;
bool n4_sent = false; bool n4_sent = false;
std::shared_ptr<pfcp_association> association; std::shared_ptr<pfcp_association> association;
// we use parts of the upf_interface here // we use parts of the upf_interface here
...@@ -293,6 +312,12 @@ struct edge { ...@@ -293,6 +312,12 @@ struct edge {
const std::unordered_set<std::string>& dnais, const std::unordered_set<std::string>& dnais,
std::string& found_dnai) const; std::string& found_dnai) const;
std::shared_ptr<smf_qos_flow> get_qos_flow(const pfcp::pdr_id_t& pdr_id);
std::shared_ptr<smf_qos_flow> get_qos_flow(const pfcp::qfi_t& qfi);
std::shared_ptr<smf_qos_flow> get_qos_flow(const pfcp::far_id_t& far_id);
bool operator==(const edge& other) const { bool operator==(const edge& other) const {
return nw_instance == other.nw_instance && type == other.type && return nw_instance == other.nw_instance && type == other.type &&
uplink == other.uplink && association == other.association; uplink == other.uplink && association == other.association;
...@@ -304,7 +329,14 @@ struct edge { ...@@ -304,7 +329,14 @@ struct edge {
// only print name of UPF when nw instance is empty // only print name of UPF when nw instance is empty
// otherwise output is too long and redundant // otherwise output is too long and redundant
if (association && nw_instance.empty()) { if (association && nw_instance.empty()) {
output.append("(").append(association->get_printable_name()).append(")"); output.append("(").append(association->get_printable_name()).append(") ");
}
if (!snssai_dnns.empty()) {
output.append(", S-NSSAI UPF info list: { ");
for (const auto& s : snssai_dnns) {
output.append(" ").append(s.to_string()).append(", ");
}
output.append("}");
} }
return output; return output;
} }
...@@ -416,6 +448,16 @@ class upf_graph { ...@@ -416,6 +448,16 @@ class upf_graph {
*/ */
static std::string get_dnai_list(const std::unordered_set<string>& dnais); static std::string get_dnai_list(const std::unordered_set<string>& dnais);
/**
* Traverse the graph in BFS from start and generate info
* @param start Start node
* @param indent Added in the beginning of each line
* @return
*/
std::string to_string_from_start_node(
const std::string& indent,
const std::shared_ptr<pfcp_association>& start) const;
public: public:
upf_graph() : adjacency_list(), visited_asynch(){}; upf_graph() : adjacency_list(), visited_asynch(){};
...@@ -539,12 +581,10 @@ class upf_graph { ...@@ -539,12 +581,10 @@ class upf_graph {
/** /**
* Update edge information in the graph * Update edge information in the graph
* @param upf UPF for which edge info should be updated * @param upf UPF for which edge info should be updated
* @param nw_instance NW instance of the edge, must be unique for this UPF
* @param info info to update * @param info info to update
*/ */
void update_edge_info( void update_edge_info(
const std::shared_ptr<pfcp_association>& upf, const std::shared_ptr<pfcp_association>& upf, const edge& info);
const std::string& nw_instance, const edge& info);
/** /**
* @brief: Debug-prints the current graph * @brief: Debug-prints the current graph
...@@ -555,6 +595,15 @@ class upf_graph { ...@@ -555,6 +595,15 @@ class upf_graph {
* @return * @return
*/ */
bool full() const; bool full() const;
/**
* Traverses the graph in BFS starting at the N3 interface and returns graph
* information: For each QFI: UL/DL FTEID for each edge
* @param indent Added in the beginning of each line
* @return string representation of this graph
*
*/
[[nodiscard]] std::string to_string(const std::string& indent) const;
}; };
#define PFCP_MAX_ASSOCIATIONS 16 #define PFCP_MAX_ASSOCIATIONS 16
...@@ -610,8 +659,7 @@ class pfcp_associations { ...@@ -610,8 +659,7 @@ class pfcp_associations {
pfcp::node_id_t& node_id, pfcp::node_id_t& node_id,
pfcp::up_function_features_s& function_features); pfcp::up_function_features_s& function_features);
bool get_association( bool get_association(
const pfcp::node_id_t& node_id, const pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa);
std::shared_ptr<pfcp_association>& sa) const;
bool get_association( bool get_association(
const pfcp::fseid_t& cp_fseid, const pfcp::fseid_t& cp_fseid,
std::shared_ptr<pfcp_association>& sa) const; std::shared_ptr<pfcp_association>& sa) const;
......
This diff is collapsed.
...@@ -41,12 +41,15 @@ ...@@ -41,12 +41,15 @@
#include "msg_pfcp.hpp" #include "msg_pfcp.hpp"
#include "smf_msg.hpp" #include "smf_msg.hpp"
#include "uint_generator.hpp" #include "uint_generator.hpp"
#include "smf_pfcp_association.hpp"
namespace smf { namespace smf {
class smf_context; class smf_context;
class smf_pdu_session; class smf_pdu_session;
enum class smf_procedure_code : uint8_t { CONTINUE, ERROR, OK };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class smf_procedure { class smf_procedure {
private: private:
...@@ -62,20 +65,76 @@ class smf_procedure { ...@@ -62,20 +65,76 @@ class smf_procedure {
explicit smf_procedure(uint64_t tx) { trxn_id = tx; } explicit smf_procedure(uint64_t tx) { trxn_id = tx; }
virtual ~smf_procedure() {} virtual ~smf_procedure() {}
virtual itti_msg_type_t get_procedure_type() { return ITTI_MSG_TYPE_NONE; } virtual itti_msg_type_t get_procedure_type() { return ITTI_MSG_TYPE_NONE; }
virtual void handle_itti_msg( virtual smf_procedure_code handle_itti_msg(
itti_n4_session_establishment_response& resp, itti_n4_session_establishment_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
virtual void handle_itti_msg( return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg(
itti_n4_session_modification_response& resp, itti_n4_session_modification_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
virtual void handle_itti_msg( return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg(
itti_n4_session_deletion_response& resp, itti_n4_session_deletion_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
}; };
class smf_qos_flow; class smf_qos_flow;
class smf_pdu_session; class smf_pdu_session;
class smf_session_procedure : public smf_procedure {
public:
explicit smf_session_procedure(std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(), sps(ps) {}
std::shared_ptr<smf_pdu_session> sps;
pfcp::create_far pfcp_create_far(edge& edge, const pfcp::qfi_t& qfi);
pfcp::create_pdr pfcp_create_pdr(edge& edge, const pfcp::qfi_t& qfi);
pfcp::create_urr pfcp_create_urr(edge& edge, const pfcp::qfi_t& qfi);
// TODO eventuell if used more than once
private:
// pfcp::destination_interface_value_e get_interface_value(const edge& edge);
pfcp::ue_ip_address_t pfcp_ue_ip_address(const edge& edge);
static pfcp::fteid_t pfcp_prepare_fteid(const pfcp::fteid_t& fteid);
protected:
void synch_ul_dl_edges(
const vector<edge>& dl_edges, const vector<edge>& ul_edges,
const pfcp::qfi_t& qfi);
/**
* Helper function to get current UPF from graph in a safe way
* @param dl_edges
* @param ul_edges
* @param current_upf
* @return ERROR in case not successful
*/
smf_procedure_code get_current_upf(
std::vector<edge>& dl_edges, std::vector<edge>& ul_edges,
std::shared_ptr<pfcp_association>& current_upf);
/**
* Helper function to get next UPF from graph in a safe way
* @param dl_edges
* @param ul_edges
* @param current_upf
* @return ERROR in case not successful, OK when UPF graph is empty and
* CONTINUE if UPF is not null
*/
smf_procedure_code get_next_upf(
std::vector<edge>& dl_edges, std::vector<edge>& ul_edges,
std::shared_ptr<pfcp_association>& next_upf);
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class n4_session_restore_procedure : public smf_procedure { class n4_session_restore_procedure : public smf_procedure {
public: public:
...@@ -94,12 +153,11 @@ class n4_session_restore_procedure : public smf_procedure { ...@@ -94,12 +153,11 @@ class n4_session_restore_procedure : public smf_procedure {
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class session_create_sm_context_procedure : public smf_procedure { class session_create_sm_context_procedure : public smf_session_procedure {
public: public:
explicit session_create_sm_context_procedure( explicit session_create_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps) std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(), : smf_session_procedure(ps),
sps(ps),
n4_triggered(), n4_triggered(),
n11_triggered_pending(), n11_triggered_pending(),
n11_trigger() {} n11_trigger() {}
...@@ -111,7 +169,7 @@ class session_create_sm_context_procedure : public smf_procedure { ...@@ -111,7 +169,7 @@ class session_create_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context * @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return * @return
*/ */
int run( smf_procedure_code run(
std::shared_ptr<itti_n11_create_sm_context_request> req, std::shared_ptr<itti_n11_create_sm_context_request> req,
std::shared_ptr<itti_n11_create_sm_context_response> resp, std::shared_ptr<itti_n11_create_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc);
...@@ -122,24 +180,31 @@ class session_create_sm_context_procedure : public smf_procedure { ...@@ -122,24 +180,31 @@ class session_create_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context * @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void * @return void
*/ */
void handle_itti_msg( smf_procedure_code handle_itti_msg(
itti_n4_session_establishment_response& resp, itti_n4_session_establishment_response& resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc) override;
std::shared_ptr<itti_n4_session_establishment_request> n4_triggered; std::shared_ptr<itti_n4_session_establishment_request> n4_triggered;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_create_sm_context_request> n11_trigger; std::shared_ptr<itti_n11_create_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_create_sm_context_response> n11_triggered_pending; std::shared_ptr<itti_n11_create_sm_context_response> n11_triggered_pending;
private:
smf_qos_flow current_flow{};
/**
* Sends a session establishment request, based on current UPF graph
* @return
*/
smf_procedure_code send_n4_session_establishment_request();
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class session_update_sm_context_procedure : public smf_procedure { class session_update_sm_context_procedure : public smf_session_procedure {
public: public:
explicit session_update_sm_context_procedure( explicit session_update_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps) std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(), : smf_session_procedure(ps),
sps(ps),
n4_triggered(), n4_triggered(),
n11_triggered_pending(), n11_triggered_pending(),
n11_trigger(), n11_trigger(),
...@@ -152,7 +217,7 @@ class session_update_sm_context_procedure : public smf_procedure { ...@@ -152,7 +217,7 @@ class session_update_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context * @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return * @return
*/ */
int run( smf_procedure_code run(
std::shared_ptr<itti_n11_update_sm_context_request> req, std::shared_ptr<itti_n11_update_sm_context_request> req,
std::shared_ptr<itti_n11_update_sm_context_response> resp, std::shared_ptr<itti_n11_update_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc);
...@@ -163,28 +228,37 @@ class session_update_sm_context_procedure : public smf_procedure { ...@@ -163,28 +228,37 @@ class session_update_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context * @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void * @return void
*/ */
void handle_itti_msg( smf_procedure_code handle_itti_msg(
itti_n4_session_modification_response& resp, itti_n4_session_modification_response& resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc) override;
std::shared_ptr<itti_n4_session_modification_request> n4_triggered; std::shared_ptr<itti_n4_session_modification_request> n4_triggered;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_update_sm_context_request> n11_trigger; std::shared_ptr<itti_n11_update_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_update_sm_context_response> n11_triggered_pending; std::shared_ptr<itti_n11_update_sm_context_response> n11_triggered_pending;
session_management_procedures_type_e session_procedure_type; session_management_procedures_type_e session_procedure_type;
private:
// TODO currently support only one flow
smf_qos_flow current_flow{};
/**
* Sends a session modification request, based on the graph
* Does only consider normal DL procedures
* @return OK when successful, ERROR otherwise
*/
smf_procedure_code send_n4_session_modification_request();
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class session_release_sm_context_procedure : public smf_procedure { class session_release_sm_context_procedure : public smf_session_procedure {
public: public:
explicit session_release_sm_context_procedure( explicit session_release_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps) std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(), : smf_session_procedure(ps),
sps(ps),
n4_triggered(), n4_triggered(),
n11_triggered_pending(), n11_triggered_pending(),
n11_trigger() {} n11_trigger(),
session_procedure_type() {}
/* /*
* Execute N11 Release SM Context Request procedure * Execute N11 Release SM Context Request procedure
...@@ -193,7 +267,7 @@ class session_release_sm_context_procedure : public smf_procedure { ...@@ -193,7 +267,7 @@ class session_release_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context * @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return * @return
*/ */
int run( smf_procedure_code run(
std::shared_ptr<itti_n11_release_sm_context_request> req, std::shared_ptr<itti_n11_release_sm_context_request> req,
std::shared_ptr<itti_n11_release_sm_context_response> resp, std::shared_ptr<itti_n11_release_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc);
...@@ -204,15 +278,18 @@ class session_release_sm_context_procedure : public smf_procedure { ...@@ -204,15 +278,18 @@ class session_release_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context * @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void * @return void
*/ */
void handle_itti_msg( smf_procedure_code handle_itti_msg(
itti_n4_session_deletion_response& resp, itti_n4_session_deletion_response& resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc) override;
std::shared_ptr<itti_n4_session_deletion_request> n4_triggered; std::shared_ptr<itti_n4_session_deletion_request> n4_triggered;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger; std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_release_sm_context_response> n11_triggered_pending; std::shared_ptr<itti_n11_release_sm_context_response> n11_triggered_pending;
session_management_procedures_type_e session_procedure_type;
private:
smf_procedure_code send_n4_session_deletion_request();
}; };
} // namespace smf } // namespace smf
......
This diff is collapsed.
...@@ -796,12 +796,10 @@ void smf_sbi::subscribe_upf_status_notify( ...@@ -796,12 +796,10 @@ void smf_sbi::subscribe_upf_status_notify(
"available (HTTP version %d)", "available (HTTP version %d)",
msg->http_version); msg->http_version);
Logger::smf_sbi().debug( Logger::smf_sbi().debug("NRF's URL: %s", msg->url.c_str());
"Send NFStatusNotify to NRF, NRF URL %s", msg->url.c_str());
std::string body = msg->json_data.dump(); std::string body = msg->json_data.dump();
Logger::smf_sbi().debug( Logger::smf_sbi().debug("Message body: %s", body.c_str());
"Send NFStatusNotify to NRF, msg body: %s", body.c_str());
std::string response_data = {}; std::string response_data = {};
// Generate a promise and associate this promise to the curl handle // Generate a promise and associate this promise to the curl handle
...@@ -927,7 +925,7 @@ bool smf_sbi::get_sm_data( ...@@ -927,7 +925,7 @@ bool smf_sbi::get_sm_data(
} }
if (jsonData["singleNssai"].find("sd") != jsonData["singleNssai"].end()) { if (jsonData["singleNssai"].find("sd") != jsonData["singleNssai"].end()) {
std::string sd_str = jsonData["singleNssai"]["sd"]; std::string sd_str = jsonData["singleNssai"]["sd"];
uint32_t sd = 0xFFFFFF; uint32_t sd = SD_NO_VALUE;
xgpp_conv::sd_string_to_int( xgpp_conv::sd_string_to_int(
jsonData["singleNssai"]["sd"].get<std::string>(), sd); jsonData["singleNssai"]["sd"].get<std::string>(), sd);
if (sd != snssai.sd) { if (sd != snssai.sd) {
...@@ -1392,7 +1390,7 @@ uint32_t smf_sbi::get_available_response(boost::shared_future<uint32_t>& f) { ...@@ -1392,7 +1390,7 @@ uint32_t smf_sbi::get_available_response(boost::shared_future<uint32_t>& f) {
uint32_t response_code = f.get(); uint32_t response_code = f.get();
return response_code; return response_code;
} else { } else {
return 408; // timeout, TODO: remove hardcoded value return http_status_code_e::HTTP_STATUS_CODE_408_REQUEST_TIMEOUT;
} }
} }
......
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