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 @@
#include "NFStatusNotifyApi.h"
#include "Helpers.h"
#include "logger.hpp"
#include "smf_config.hpp"
extern smf::smf_config smf_cfg;
......@@ -56,6 +57,9 @@ void NFStatusNotifyApi::setupRoutes() {
void NFStatusNotifyApi::notify_nf_status_handler(
const Pistache::Rest::Request& request,
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
NotificationData notificationData;
......
......@@ -65,15 +65,13 @@ void IndividualSMContextApiImpl::release_sm_context(
xgpp_conv::sm_context_release_from_openapi(
smContextReleaseMessage, sm_context_req_msg);
boost::shared_ptr<
boost::promise<smf::pdu_session_release_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_release_sm_context_response> >();
boost::shared_future<smf::pdu_session_release_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -88,19 +86,21 @@ void IndividualSMContextApiImpl::release_sm_context(
boost::future_status status;
// wait for timeout or ready
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) {
assert(f.is_ready());
assert(f.has_value());
assert(!f.has_exception());
// 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);
if (sm_context_response.find("http_code") != sm_context_response.end()) {
http_code = sm_context_response["http_code"].get<int>();
}
// 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(
......@@ -128,15 +128,13 @@ void IndividualSMContextApiImpl::update_sm_context(
xgpp_conv::sm_context_update_from_openapi(
smContextUpdateMessage, sm_context_req_msg);
boost::shared_ptr<
boost::promise<smf::pdu_session_update_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_update_sm_context_response> >();
boost::shared_future<smf::pdu_session_update_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -156,40 +154,65 @@ void IndividualSMContextApiImpl::update_sm_context(
assert(f.has_value());
assert(!f.has_exception());
// 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);
nlohmann::json json_data = {};
std::string body = {};
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);
sm_context_response.get_json_data(json_data);
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());
if (sm_context_response.n1_sm_msg_is_set() and
sm_context_response.n2_sm_info_is_set()) {
if (n1_sm_msg_is_set and n2_sm_info_is_set) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format);
sm_context_response["n1_sm_message"].get<std::string>(),
sm_context_response["n2_sm_information"].get<std::string>(),
json_format);
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; 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(
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);
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; 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(
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);
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
......@@ -200,12 +223,10 @@ void IndividualSMContextApiImpl::update_sm_context(
Pistache::Http::Mime::MediaType(json_format));
body = json_data.dump().c_str();
} else {
response.send(Pistache::Http::Code(sm_context_response.get_http_code()));
response.send(Pistache::Http::Code(http_code));
return;
}
response.send(
Pistache::Http::Code(sm_context_response.get_http_code()), body);
response.send(Pistache::Http::Code(http_code), body);
} else {
response.send(Pistache::Http::Code::Request_Timeout);
}
......
......@@ -94,9 +94,6 @@ class IndividualSMContextApiImpl
std::string m_address;
protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
};
} // namespace api
......
......@@ -84,15 +84,13 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
m_address + base + smf_cfg.sbi_api_version +
NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL);
boost::shared_ptr<
boost::promise<smf::pdu_session_create_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_create_sm_context_response> >();
boost::shared_future<smf::pdu_session_create_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -112,40 +110,60 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
assert(f.has_value());
assert(!f.has_exception());
// 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);
nlohmann::json json_data = {};
std::string json_format = {};
std::string body = {};
bool n1_sm_msg_is_set = false;
sm_context_response.get_json_data(json_data);
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.n1_sm_msg_is_set()) { // add N1 container if
// available
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 (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(
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);
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)));
} 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>(
Pistache::Http::Mime::MediaType(json_format));
body = json_data.dump().c_str();
} 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;
}
response.send(
Pistache::Http::Code(sm_context_response.get_http_code()), body);
response.send(Pistache::Http::Code(http_code), body);
} else {
response.send(Pistache::Http::Code::Request_Timeout);
}
......
......@@ -79,9 +79,6 @@ class SMContextsCollectionApiImpl
std::string m_address;
protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
};
} // namespace api
......
......@@ -77,9 +77,6 @@ class SubscriptionsCollectionApiImpl
std::string m_address;
protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
};
} // namespace api
......
......@@ -373,15 +373,13 @@ void smf_http2_server::create_sm_contexts_handler(
NSMF_PDU_SESSION_BASE + smf_cfg.sbi_api_version +
NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL);
boost::shared_ptr<
boost::promise<smf::pdu_session_create_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_create_sm_context_response> >();
boost::shared_future<smf::pdu_session_create_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -394,27 +392,46 @@ void smf_http2_server::create_sm_contexts_handler(
m_smf_app->handle_pdu_session_create_sm_context_request(itti_msg);
// 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);
nlohmann::json json_data = {};
sm_context_response.get_json_data(json_data);
std::string json_format;
sm_context_response.get_json_format(json_format);
std::string json_format = {};
bool n1_sm_msg_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;
}
// Add header
header_map h;
// 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(
"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(
"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
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());
}
......@@ -438,15 +455,13 @@ void smf_http2_server::update_sm_context_handler(
xgpp_conv::sm_context_update_from_openapi(
smContextUpdateMessage, sm_context_req_msg);
boost::shared_ptr<
boost::promise<smf::pdu_session_update_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_update_sm_context_response> >();
boost::shared_future<smf::pdu_session_update_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -459,39 +474,61 @@ void smf_http2_server::update_sm_context_handler(
m_smf_app->handle_pdu_session_update_sm_context_request(itti_msg);
// 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);
nlohmann::json json_data = {};
std::string body = {};
header_map h = {};
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());
if (sm_context_response.n1_sm_msg_is_set() and
sm_context_response.n2_sm_info_is_set()) {
if (n1_sm_msg_is_set and n2_sm_info_is_set) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format);
sm_context_response["n1_sm_message"].get<std::string>(),
sm_context_response["n2_sm_information"].get<std::string>(),
json_format);
h.emplace(
"content-type", header_value{"multipart/related; 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(
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);
h.emplace(
"content-type", header_value{"multipart/related; 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(
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);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
......@@ -501,7 +538,7 @@ void smf_http2_server::update_sm_context_handler(
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);
}
......@@ -519,15 +556,13 @@ void smf_http2_server::release_sm_context_handler(
xgpp_conv::sm_context_release_from_openapi(
smContextReleaseMessage, sm_context_req_msg);
boost::shared_ptr<
boost::promise<smf::pdu_session_release_sm_context_response> >
p = boost::make_shared<
boost::promise<smf::pdu_session_release_sm_context_response> >();
boost::shared_future<smf::pdu_session_release_sm_context_response> f;
boost::shared_ptr<boost::promise<nlohmann::json> > p =
boost::make_shared<boost::promise<nlohmann::json> >();
boost::shared_future<nlohmann::json> f;
f = p->get_future();
// 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);
m_smf_app->add_promise(promise_id, p);
......@@ -544,10 +579,15 @@ void smf_http2_server::release_sm_context_handler(
m_smf_app->handle_pdu_session_release_sm_context_request(itti_msg);
// 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);
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();
}
......
......@@ -74,9 +74,6 @@ class smf_http2_server {
smf::smf_app* m_smf_app;
protected:
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
};
#endif
......@@ -1026,6 +1026,13 @@ struct node_id_s {
struct in6_addr ipv6_address;
} u1;
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 {
if (i.node_id_type != this->node_id_type) return false;
switch (i.node_id_type) {
......
......@@ -22,14 +22,15 @@
#ifndef FILE_SMF_SEEN
#define FILE_SMF_SEEN
#include "3gpp_29.274.h"
#include "3gpp_29.571.h"
#include "3gpp_24.501.h"
#include <nlohmann/json.hpp>
#include <boost/algorithm/string.hpp>
#include <map>
#include <vector>
#include <nlohmann/json.hpp>
#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;
#define SUPI_64_FMT "%" SCNu64
......@@ -85,13 +86,21 @@ typedef struct s_nssai // section 28.4, TS23.003
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 std::string m_sd) : sst(m_sst) {
sd = 0xFFFFFF;
sd = SD_NO_VALUE;
if (m_sd.empty()) return;
uint8_t base = 10;
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) {
Logger::smf_app().warn(
"Error when converting from string to int for snssai.SD, error: %s",
Logger::smf_app().error(
"Error when converting from string to int for S-NSSAI SD, error: %s",
e.what());
sd = SD_NO_VALUE;
}
}
s_nssai() : sst(), sd() {}
......@@ -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
#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 {
std::string dnn;
......@@ -345,7 +355,7 @@ typedef struct nf_service_s {
s.append(service_instance_id);
s.append(", Service name: ");
s.append(service_name);
for (auto v : versions) {
for (const auto& v : versions) {
s.append(v.to_string());
}
s.append(", Scheme: ");
......@@ -380,11 +390,42 @@ typedef struct dnn_upf_info_item_s {
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 {
snssai_t snssai;
std::unordered_set<dnn_upf_info_item_t, dnn_upf_info_item_t>
mutable snssai_t snssai;
mutable std::unordered_set<dnn_upf_info_item_t, dnn_upf_info_item_t>
dnn_upf_info_list;
snssai_upf_info_item_s& operator=(const snssai_upf_info_item_s& s) {
......@@ -394,13 +435,29 @@ typedef struct snssai_upf_info_item_s {
}
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 {
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;
typedef struct interface_upf_info_item_s {
......@@ -436,11 +493,11 @@ typedef struct upf_info_s {
std::string s = {};
// TODO: Interface UPF Info List
if (!snssai_upf_info_list.empty()) {
s.append("SNSSAI UPF Info: ");
s.append("S-NSSAI UPF Info: ");
for (auto sn : snssai_upf_info_list) {
s.append("{" + sn.snssai.toString() + ", ");
for (auto d : sn.dnn_upf_info_list) {
s.append("{DNN = " + d.dnn + "}, ");
s.append("{DNN = " + d.dnn + "} ");
}
s.append("};");
}
......
......@@ -181,10 +181,14 @@ void conv::plmnToMccMnc(
//------------------------------------------------------------------------------
struct in_addr conv::fromString(const std::string addr4) {
unsigned char buf[sizeof(struct in6_addr)] = {};
int s = inet_pton(AF_INET, addr4.c_str(), buf);
struct in_addr* ia = (struct in_addr*) buf;
return *ia;
struct in_addr ipv4_addr;
ipv4_addr.s_addr = INADDR_ANY;
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 s = {};
......
......@@ -21,6 +21,7 @@
#include "fqdn.hpp"
#include "logger.hpp"
#include "string.hpp"
#include <boost/asio.hpp>
#include <iostream>
#include <chrono>
......@@ -33,11 +34,11 @@ bool fqdn::resolve(
const std::string& host_name, std::string& address, uint32_t& port,
uint8_t& addr_type, const std::string& protocol) {
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) {
try {
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::results_type endpoints =
......@@ -73,6 +74,77 @@ bool fqdn::resolve(
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) {
Logger::smf_app().debug("Resolving an IP address (name %s)", ip_addr.c_str());
int tries = 0;
......@@ -107,4 +179,4 @@ bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) {
}
}
return false;
}
\ No newline at end of file
}
......@@ -28,6 +28,7 @@
#ifndef FILE_FQDN_HPP_SEEN
#define FILE_FQDN_HPP_SEEN
#include <string>
#include "3gpp_29.244.h"
class fqdn {
public:
/*
......@@ -41,6 +42,7 @@ class fqdn {
const std::string& host_name, std::string& address, uint32_t& port,
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
* @param ip_address to resolve
......
......@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdint.h>
#include "common_types.h"
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "ProcedureTransactionIdentity.h"
......@@ -30,54 +31,17 @@
int encode_procedure_transaction_identity(
ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei,
uint8_t* buffer, uint32_t len) {
uint32_t encoded = 0;
int encode_result;
uint8_t encoded = 0;
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(
buffer, PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH, len);
if ((encode_result = encode_bstring(
proceduretransactionidentity, buffer + encoded, len - encoded)) < 0)
return encode_result;
else
encoded += encode_result;
ENCODE_U8(buffer + encoded, (uint8_t) proceduretransactionidentity, 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(
ProcedureTransactionIdentity* proceduretransactionidentity, uint8_t iei,
uint8_t* buffer, uint32_t len) {
int decoded = 0;
uint8_t ielen = 0;
int decode_result;
if ((decode_result = decode_bstring(
proceduretransactionidentity, ielen, buffer + decoded,
len - decoded)) < 0)
return decode_result;
else
decoded += decode_result;
int decoded = 0;
DECODE_U8(buffer + decoded, proceduretransactionidentity, 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 @@
*/
#include <stdint.h>
#include "bstrlib.h"
#define PROCEDURE_TRANSACTION_IDENTITY_MINIMUM_LENGTH 1
#define PROCEDURE_TRANSACTION_IDENTITY_MAXIMUM_LENGTH 1
typedef bstring ProcedureTransactionIdentity;
typedef uint8_t ProcedureTransactionIdentity;
int encode_procedure_transaction_identity(
ProcedureTransactionIdentity proceduretransactionidentity, uint8_t iei,
......
......@@ -39,7 +39,7 @@
#include <cstring>
#include <endian.h>
#include <exception>
//#include <fmt/format.h> conflicts with spdlog
// #include <fmt/format.h> conflicts with spdlog
#include <iostream>
#include <memory>
#include <sstream>
......@@ -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) {
tlv.set_length(1);
u1.b = 0;
u1.bf.ch = b.ch;
u1.bf.chid = b.chid;
teid = b.teid;
ipv4_address = b.ipv4_address;
ipv6_address = b.ipv6_address;
u1.b = 0;
u1.bf.ch = b.ch;
u1.bf.chid = b.chid;
teid = b.teid;
if (!u1.bf.ch) {
tlv.add_length(4); // teid
u1.bf.v4 = b.v4;
u1.bf.v6 = b.v6;
if (u1.bf.v4) {
tlv.add_length(4);
ipv4_address = b.ipv4_address;
}
if (u1.bf.v6) {
tlv.add_length(16);
ipv6_address = b.ipv6_address;
}
}
if (u1.bf.ch & b.v4) {
u1.bf.v4 = b.v4;
} else {
ipv4_address.s_addr = INADDR_ANY;
ipv6_address = in6addr_any;
// else should clear v4 v6 bits
if (u1.bf.ch & b.v4) {
u1.bf.v4 = b.v4;
}
if (u1.bf.chid) {
choose_id = b.choose_id;
tlv.add_length(1);
......@@ -948,7 +945,7 @@ class pfcp_sdf_filter_ie : public pfcp_ie {
u1.bf.fl = b.fl;
u1.bf.bid = b.bid;
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;
tlv.add_length(
sizeof(length_of_flow_description) + flow_description.size());
......
This diff is collapsed.
......@@ -114,22 +114,10 @@ class smf_app {
mutable std::shared_mutex m_scid2smf_context;
mutable std::shared_mutex m_smf_event_subscriptions;
// Store promise IDs for Create/Update session
mutable std::shared_mutex m_sm_context_create_promises;
mutable std::shared_mutex m_sm_context_update_promises;
mutable std::shared_mutex m_sm_context_release_promises;
mutable std::shared_mutex m_sbi_server_promises;
std::map<
uint32_t,
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;
std::map<uint32_t, boost::shared_ptr<boost::promise<nlohmann::json>>>
sbi_server_promises;
smf_profile nf_instance_profile; // SMF profile
std::string smf_instance_id; // SMF instance id
......@@ -726,32 +714,25 @@ class smf_app {
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
* @param [uint32_t] id: promise id
* @param [boost::shared_ptr<
* boost::promise<pdu_session_update_sm_context_response> >&] p: pointer to
* boost::promise<nlohmann::json> >&] p: pointer to
* the promise
* @return void
*/
void add_promise(
uint32_t id,
boost::shared_ptr<boost::promise<pdu_session_update_sm_context_response>>&
p);
uint32_t id, boost::shared_ptr<boost::promise<nlohmann::json>>& p);
/*
* To store a promise of a PDU Session Release SM Context Response to be
* triggered when the result is ready
* @param [uint32_t] id: promise id
* @param [boost::shared_ptr<
* boost::promise<pdu_session_release_sm_context_response> >&] p: pointer to
* the promise
* @return void
* To generate promise ID across SMF components
* @param void
* @return generated ID
*/
void add_promise(
uint32_t id,
boost::shared_ptr<
boost::promise<pdu_session_release_sm_context_response>>& p);
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
/*
* To trigger the response to the HTTP server by set the value of the
......@@ -790,6 +771,17 @@ class smf_app {
const uint32_t& http_code, const uint8_t& cause,
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
* corresponding promise to ready
......@@ -825,18 +817,6 @@ class smf_app {
pdu_session_update_sm_context_response& sm_context_response,
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
* @param [const evsub_id_t&] sub_id: Subscription ID
......@@ -924,6 +904,13 @@ class smf_app {
* @return void
*/
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
#include "smf_config.hpp"
......
......@@ -1044,10 +1044,12 @@ void smf_config::display() {
Logger::smf_app().info(" Secondary DNS v6 ....: %s", str_addr6);
}
Logger::smf_app().info("- CSCF:");
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))) {
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);
......
This diff is collapsed.
......@@ -614,7 +614,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
// Subscribe to PDU Session Release (event exposure)
ee_pdu_session_release_connection =
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
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> {
*/
bool handle_pdu_session_resource_release_response_transfer(
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
......@@ -1172,6 +1173,31 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void get_pdu_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)
* @param [scid_t] scid: SMF Context ID
......@@ -1180,39 +1206,50 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
* @return void
*/
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 [uint32_t] status: Updated status
* @param [uint8_t] http_version: HTTP version
* @return void
*/
void trigger_pdu_session_release(
const scid_t& scid, const uint8_t& http_version) const;
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 handle_ue_ip_change(scid_t scid, uint8_t http_version);
void trigger_ue_ip_change(
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 handle_plmn_change(scid_t scid, uint8_t http_version);
void trigger_plmn_change(
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 handle_ddds(scid_t scid, uint8_t http_version);
void trigger_ddds(const scid_t& scid, const uint8_t& http_version) const;
void handle_ddds(const scid_t& scid, const uint8_t& http_version) const;
void trigger_pdusesest(scid_t scid, uint8_t http_version);
void handle_pdusesest(scid_t scid, uint8_t http_version);
void trigger_pdusesest(const scid_t& scid, const uint8_t& http_version) const;
void handle_pdusesest(const scid_t& scid, const uint8_t& http_version) const;
void trigger_qos_monitoring(
seid_t seid, oai::smf_server::model::EventNotification ev_notif_model,
uint8_t http_version);
const seid_t& seid,
const oai::smf_server::model::EventNotification& ev_notif_model,
const uint8_t& http_version) const;
void handle_qos_monitoring(
seid_t seid, oai::smf_server::model::EventNotification ev_notif_model,
uint8_t http_version);
const seid_t& seid,
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
* decoded NAS msg
......@@ -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 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:
std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
// snssai <-> session management subscription
......
......@@ -46,10 +46,9 @@ typedef bs2::signal_type<
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type sm_context_status_sig_t;
// Signal for Event exposure
// PDU session Release, SUPI, PDU SessionID, HTTP version
// PDU session Release, SCID, HTTP version
typedef bs2::signal_type<
void(supi64_t, pdu_session_id_t, uint8_t),
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
void(scid_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_pdu_session_release_sig_t;
// 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 {
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
*/
......@@ -291,6 +370,35 @@ void pdu_session_sm_context_response::get_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
*/
......@@ -449,6 +557,31 @@ void pdu_session_create_sm_context_response::get_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
*/
......@@ -689,29 +822,37 @@ std::string pdu_session_update_sm_context_response::get_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) {
m_cause = cause;
void pdu_session_update_sm_context_response::to_json(
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() {
return m_cause;
void pdu_session_update_sm_context_response::from_json(
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(
const uint32_t code) {
m_http_code = code;
void pdu_session_release_sm_context_response::to_json(
nlohmann::json& data) const {
pdu_session_sm_context_response::to_json(data);
}
//-----------------------------------------------------------------------------
uint32_t pdu_session_release_sm_context_response::get_http_code() const {
return m_http_code;
void pdu_session_release_sm_context_response::from_json(
const nlohmann::json& data) {
pdu_session_sm_context_response::from_json(data);
}
/*
......
......@@ -161,6 +161,9 @@ class pdu_session_msg {
void set_n2_sm_info_type(const std::string& value);
bool n2_sm_info_type_is_set() const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
pdu_session_msg_type_t m_msg_type;
std::string m_api_root;
......@@ -236,6 +239,9 @@ class pdu_session_sm_context_response : public pdu_session_msg {
void set_json_format(const std::string& format);
void get_json_format(std::string& format) const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
uint8_t m_cause;
nlohmann::json m_json_data;
......@@ -323,6 +329,9 @@ class pdu_session_create_sm_context_response
void set_epco(const protocol_configuration_options_t& p);
void get_epco(protocol_configuration_options_t& p) const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
paa_t m_paa;
qos_flow_context_updated m_qos_flow_context;
......@@ -440,6 +449,9 @@ class pdu_session_update_sm_context_response
void set_smf_context_uri(const std::string& value);
std::string get_smf_context_uri() const;
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds;
std::string m_smf_context_uri;
......@@ -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:
pdu_session_release_sm_context_response()
: pdu_session_msg(PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE) {
m_cause = 0;
m_http_code = 0;
};
void set_cause(uint8_t cause);
uint8_t get_cause();
void set_http_code(const uint32_t code);
uint32_t get_http_code() const;
: pdu_session_sm_context_response(
PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE){};
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
uint8_t m_cause;
uint32_t m_http_code;
};
//---------------------------------------------------------------------------------------
......
......@@ -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(
pdu_session_update_sm_context_response& sm_context_res,
......@@ -744,7 +813,13 @@ bool smf_n1::create_n1_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.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->pdu_session_release_command._5gsmcause =
static_cast<uint8_t>(sm_cause);
......
......@@ -135,6 +135,9 @@ class smf_n1 {
pdu_session_update_sm_context_request& sm_context_res,
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
* 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(
.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi;
.choice.nonDynamic5QI->fiveQI = (uint8_t) DEFAULT_5QI;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.priorityLevelARP =
qos_flow.qos_profile.arp.priority_level;
......@@ -845,6 +845,55 @@ bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer(
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(
pdu_session_update_sm_context_response& sm_context_res,
......
......@@ -162,6 +162,10 @@ class smf_n2 {
pdu_session_update_sm_context_response& sm_context_res,
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
* This IE is included in the following messages:
......
......@@ -197,51 +197,51 @@ int smf_app::process_pco_request_ipcp(
* returning the IP address of a valid DNS server.
* By default, no secondary DNS address is provided.
*/
Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS length %u",
ipcp_req_option_length);
if (ipcp_req_option_length >= 6) {
ipcp_dns_sec_ipv4_addr = htonl(
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 2))
<< 24) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 3))
<< 16) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 4))
<< 8) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 5))));
Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_sec_ipv4_addr 0x%x",
ipcp_dns_sec_ipv4_addr);
if (ipcp_dns_sec_ipv4_addr == INADDR_ANY) {
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
} else if (
smf_cfg.default_dns_secv4.s_addr != ipcp_dns_sec_ipv4_addr) {
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
} else {
ipcp_out_dns_sec_ipv4_addr = ipcp_dns_sec_ipv4_addr;
}
Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_sec_ipv4_addr 0x%x",
ipcp_out_dns_sec_ipv4_addr);
}
uint8_t ids[6] = {0};
ids[0] = IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS;
ids[1] = 6;
ids[2] = (uint8_t)(ipcp_out_dns_sec_ipv4_addr & 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[5] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 24) & 0x000000FF);
ipcp_out_length += 6;
std::string tmp_s((const char*) &ids[0], 6);
poc_id_resp.protocol_id_contents.append(tmp_s);
/* Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS length %u",
ipcp_req_option_length);
if (ipcp_req_option_length >= 6) {
ipcp_dns_sec_ipv4_addr = htonl(
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 2))
<< 24) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 3))
<< 16) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index + 4))
<< 8) |
(((uint32_t) poc_id->protocol_id_contents.at(pco_in_index +
5)))); Logger::smf_app().debug( "PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_sec_ipv4_addr 0x%x",
ipcp_dns_sec_ipv4_addr);
if (ipcp_dns_sec_ipv4_addr == INADDR_ANY) {
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
} else if (
smf_cfg.default_dns_secv4.s_addr != ipcp_dns_sec_ipv4_addr) {
ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;
ipcp_out_dns_sec_ipv4_addr = smf_cfg.default_dns_secv4.s_addr;
} else {
ipcp_out_dns_sec_ipv4_addr = ipcp_dns_sec_ipv4_addr;
}
Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option "
"SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_sec_ipv4_addr
0x%x", ipcp_out_dns_sec_ipv4_addr);
}
uint8_t ids[6] = {0};
ids[0] = IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS;
ids[1] = 6;
ids[2] = (uint8_t)(ipcp_out_dns_sec_ipv4_addr & 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[5] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 24) & 0x000000FF);
ipcp_out_length += 6;
std::string tmp_s((const char*) &ids[0], 6);
poc_id_resp.protocol_id_contents.append(tmp_s);
*/
} break;
default:
......
This diff is collapsed.
......@@ -92,6 +92,7 @@ class pfcp_association {
timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID;
}
pfcp_association(
const pfcp::node_id_t& node_id,
pfcp::recovery_time_stamp_t& recovery_time_stamp)
......@@ -129,6 +130,7 @@ class pfcp_association {
timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID;
}
pfcp_association(pfcp_association const& p)
: node_id(p.node_id),
hash_node_id(p.hash_node_id),
......@@ -190,8 +192,21 @@ class pfcp_association {
bool find_upf_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();
/*
* Print related-information for this association
* @param void
* @return void:
*/
void display();
private:
bool find_interface_edge(
const iface_type& type_match, std::vector<edge>& edges);
......@@ -220,6 +235,7 @@ class smf_qos_flow {
precedence = {};
far_id_ul = {};
far_id_dl = {};
urr_id = {};
released = false;
qos_profile = {};
cause_value = 0;
......@@ -246,18 +262,21 @@ class smf_qos_flow {
*/
std::string toString() const;
[[nodiscard]] std::string toString(const std::string& indent) const;
pfcp::qfi_t qfi; // QoS Flow Identifier
pfcp::fteid_t ul_fteid; // fteid of UPF
pfcp::fteid_t dl_fteid; // fteid of AN
pfcp::fteid_t ul_fteid{}; // fteid of UPF
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_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_dl; // FAR ID, DL
bool released; // finally seems necessary, TODO try to find heuristic ?
pdu_session_id_t pdu_session_id;
bool released{}; // finally seems necessary, TODO try to find heuristic ?
pdu_session_id_t pdu_session_id{};
qos_profile_t qos_profile; // QoS profile
uint8_t cause_value; // cause
uint8_t cause_value{}; // cause
};
const std::string DEFAULT_FLOW_DESCRIPTION =
......@@ -272,7 +291,7 @@ struct edge {
std::string nw_instance;
iface_type type;
bool uplink = false;
std::vector<smf_qos_flow> qos_flows;
std::vector<std::shared_ptr<smf_qos_flow>> qos_flows;
bool n4_sent = false;
std::shared_ptr<pfcp_association> association;
// we use parts of the upf_interface here
......@@ -293,6 +312,12 @@ struct edge {
const std::unordered_set<std::string>& dnais,
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 {
return nw_instance == other.nw_instance && type == other.type &&
uplink == other.uplink && association == other.association;
......@@ -304,7 +329,14 @@ struct edge {
// only print name of UPF when nw instance is empty
// otherwise output is too long and redundant
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;
}
......@@ -416,6 +448,16 @@ class upf_graph {
*/
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:
upf_graph() : adjacency_list(), visited_asynch(){};
......@@ -539,12 +581,10 @@ class upf_graph {
/**
* Update edge information in the graph
* @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
*/
void update_edge_info(
const std::shared_ptr<pfcp_association>& upf,
const std::string& nw_instance, const edge& info);
const std::shared_ptr<pfcp_association>& upf, const edge& info);
/**
* @brief: Debug-prints the current graph
......@@ -555,6 +595,15 @@ class upf_graph {
* @return
*/
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
......@@ -610,8 +659,7 @@ class pfcp_associations {
pfcp::node_id_t& node_id,
pfcp::up_function_features_s& function_features);
bool get_association(
const pfcp::node_id_t& node_id,
std::shared_ptr<pfcp_association>& sa) const;
const pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa);
bool get_association(
const pfcp::fseid_t& cp_fseid,
std::shared_ptr<pfcp_association>& sa) const;
......
This diff is collapsed.
......@@ -41,12 +41,15 @@
#include "msg_pfcp.hpp"
#include "smf_msg.hpp"
#include "uint_generator.hpp"
#include "smf_pfcp_association.hpp"
namespace smf {
class smf_context;
class smf_pdu_session;
enum class smf_procedure_code : uint8_t { CONTINUE, ERROR, OK };
//------------------------------------------------------------------------------
class smf_procedure {
private:
......@@ -62,20 +65,76 @@ class smf_procedure {
explicit smf_procedure(uint64_t tx) { trxn_id = tx; }
virtual ~smf_procedure() {}
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,
std::shared_ptr<smf::smf_context> pc) {}
virtual void handle_itti_msg(
std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg(
itti_n4_session_modification_response& resp,
std::shared_ptr<smf::smf_context> pc) {}
virtual void handle_itti_msg(
std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg(
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_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 {
public:
......@@ -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:
explicit session_create_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(),
sps(ps),
: smf_session_procedure(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger() {}
......@@ -111,7 +169,7 @@ class session_create_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @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_response> resp,
std::shared_ptr<smf::smf_context> sc);
......@@ -122,24 +180,31 @@ class session_create_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
*/
void handle_itti_msg(
smf_procedure_code handle_itti_msg(
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<smf_pdu_session> sps;
std::shared_ptr<itti_n11_create_sm_context_request> n11_trigger;
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:
explicit session_update_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(),
sps(ps),
: smf_session_procedure(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger(),
......@@ -152,7 +217,7 @@ class session_update_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @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_response> resp,
std::shared_ptr<smf::smf_context> sc);
......@@ -163,28 +228,37 @@ class session_update_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
*/
void handle_itti_msg(
smf_procedure_code handle_itti_msg(
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<smf_pdu_session> sps;
std::shared_ptr<itti_n11_update_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_update_sm_context_response> n11_triggered_pending;
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:
explicit session_release_sm_context_procedure(
std::shared_ptr<smf_pdu_session>& ps)
: smf_procedure(),
sps(ps),
: smf_session_procedure(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger() {}
n11_trigger(),
session_procedure_type() {}
/*
* Execute N11 Release SM Context Request procedure
......@@ -193,7 +267,7 @@ class session_release_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @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_response> resp,
std::shared_ptr<smf::smf_context> sc);
......@@ -204,15 +278,18 @@ class session_release_sm_context_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
*/
void handle_itti_msg(
smf_procedure_code handle_itti_msg(
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<smf_pdu_session> sps;
std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger;
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
......
This diff is collapsed.
......@@ -796,12 +796,10 @@ void smf_sbi::subscribe_upf_status_notify(
"available (HTTP version %d)",
msg->http_version);
Logger::smf_sbi().debug(
"Send NFStatusNotify to NRF, NRF URL %s", msg->url.c_str());
Logger::smf_sbi().debug("NRF's URL: %s", msg->url.c_str());
std::string body = msg->json_data.dump();
Logger::smf_sbi().debug(
"Send NFStatusNotify to NRF, msg body: %s", body.c_str());
Logger::smf_sbi().debug("Message body: %s", body.c_str());
std::string response_data = {};
// Generate a promise and associate this promise to the curl handle
......@@ -927,7 +925,7 @@ bool smf_sbi::get_sm_data(
}
if (jsonData["singleNssai"].find("sd") != jsonData["singleNssai"].end()) {
std::string sd_str = jsonData["singleNssai"]["sd"];
uint32_t sd = 0xFFFFFF;
uint32_t sd = SD_NO_VALUE;
xgpp_conv::sd_string_to_int(
jsonData["singleNssai"]["sd"].get<std::string>(), sd);
if (sd != snssai.sd) {
......@@ -1392,7 +1390,7 @@ uint32_t smf_sbi::get_available_response(boost::shared_future<uint32_t>& f) {
uint32_t response_code = f.get();
return response_code;
} 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