Commit 06729cf0 authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

Merge branch 'fix_develop_ue_rel16' into ue_triggered_pdu_session_release

parents 3d122038 89235dea
...@@ -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\n", request.body().c_str());
// Getting the body param // Getting the body param
NotificationData notificationData; NotificationData notificationData;
......
...@@ -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() {}
...@@ -212,8 +221,8 @@ enum class sm_context_status_e { ...@@ -212,8 +221,8 @@ enum class sm_context_status_e {
SM_CONTEXT_STATUS_RELEASED = 1 SM_CONTEXT_STATUS_RELEASED = 1
}; };
static const std::vector<std::string> sm_context_status_e2str = { static const std::vector<std::string> sm_context_status_e2str = {"ACTIVE",
"ACTIVE", "RELEASED"}; "RELEASED"};
typedef struct qos_profile_gbr_s { typedef struct qos_profile_gbr_s {
gfbr_t gfbr; // Guaranteed Flow Bit Rate gfbr_t gfbr; // Guaranteed Flow Bit Rate
...@@ -346,7 +355,7 @@ typedef struct nf_service_s { ...@@ -346,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: ");
...@@ -381,11 +390,38 @@ typedef struct dnn_upf_info_item_s { ...@@ -381,11 +390,38 @@ 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) {
...@@ -395,13 +431,29 @@ typedef struct snssai_upf_info_item_s { ...@@ -395,13 +431,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 Info: " + snssai.toString() + ", ");
if (dnn_upf_info_list.size() > 0) {
s.append("DNN UPF Info list: {");
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 {
......
...@@ -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>
...@@ -37,7 +38,7 @@ bool fqdn::resolve( ...@@ -37,7 +38,7 @@ bool fqdn::resolve(
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;
......
...@@ -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
......
...@@ -399,10 +399,13 @@ void smf_app::start_nf_registration_discovery() { ...@@ -399,10 +399,13 @@ void smf_app::start_nf_registration_discovery() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_app::start_upf_association(const pfcp::node_id_t& node_id) { void smf_app::start_upf_association(const pfcp::node_id_t& node_id) {
Logger::smf_app().debug("Start a PFCP Association procedure with an UPF");
std::time_t time_epoch = std::time(nullptr); std::time_t time_epoch = std::time(nullptr);
uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH; uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
pfcp_associations::get_instance().add_peer_candidate_node(node_id); pfcp::node_id_t node_id_tmp = node_id;
fqdn::resolve(node_id_tmp); // Resolve FQDN/IP addr if necessary
pfcp_associations::get_instance().add_peer_candidate_node(node_id_tmp);
std::shared_ptr<itti_n4_association_setup_request> n4_asc = std::shared_ptr<itti_n4_association_setup_request> n4_asc =
std::shared_ptr<itti_n4_association_setup_request>( std::shared_ptr<itti_n4_association_setup_request>(
new itti_n4_association_setup_request(TASK_SMF_APP, TASK_SMF_N4)); new itti_n4_association_setup_request(TASK_SMF_APP, TASK_SMF_N4));
...@@ -438,9 +441,12 @@ void smf_app::start_upf_association(const pfcp::node_id_t& node_id) { ...@@ -438,9 +441,12 @@ void smf_app::start_upf_association(const pfcp::node_id_t& node_id) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_app::start_upf_association( void smf_app::start_upf_association(
const pfcp::node_id_t& node_id, const upf_profile& profile) { const pfcp::node_id_t& node_id, const upf_profile& profile) {
Logger::smf_app().debug("Start a PFCP Association procedure with an UPF");
std::time_t time_epoch = std::time(nullptr); std::time_t time_epoch = std::time(nullptr);
uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH; uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
pfcp::node_id_t node_id_tmp = node_id;
fqdn::resolve(node_id_tmp); // Resolve FQDN/IP addr if necessary
pfcp_associations::get_instance().add_peer_candidate_node(node_id, profile); pfcp_associations::get_instance().add_peer_candidate_node(node_id, profile);
std::shared_ptr<itti_n4_association_setup_request> n4_asc = std::shared_ptr<itti_n4_association_setup_request> n4_asc =
std::shared_ptr<itti_n4_association_setup_request>( std::shared_ptr<itti_n4_association_setup_request>(
...@@ -690,6 +696,11 @@ void smf_app::handle_itti_msg( ...@@ -690,6 +696,11 @@ void smf_app::handle_itti_msg(
graph->start_asynch_dfs_procedure(true, empty_flow); graph->start_asynch_dfs_procedure(true, empty_flow);
graph->dfs_next_upf(dl_edges, ul_edges, current_upf); graph->dfs_next_upf(dl_edges, ul_edges, current_upf);
if (!current_upf) {
Logger::smf_app().warn("Could not select UPF in graph!");
return;
}
up_node_id = current_upf->node_id; up_node_id = current_upf->node_id;
std::shared_ptr<itti_n4_session_failure_indication> std::shared_ptr<itti_n4_session_failure_indication>
...@@ -1450,15 +1461,21 @@ bool smf_app::handle_nf_status_notification( ...@@ -1450,15 +1461,21 @@ bool smf_app::handle_nf_status_notification(
// Add a new UPF node // Add a new UPF node
Logger::smf_app().debug( Logger::smf_app().debug(
"Add a new UPF node, Ipv4 Addr %s", inet_ntoa(ipv4_addrs[0])); "Add a new UPF node, Ipv4 Addr %s", inet_ntoa(ipv4_addrs[0]));
// pfcp::node_id_t n = {};
if (n.node_id_type == pfcp::NODE_ID_TYPE_UNKNOWN) if (n.node_id_type == pfcp::NODE_ID_TYPE_UNKNOWN)
n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS; n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS;
n.u1.ipv4_address.s_addr = ipv4_addrs[0].s_addr; n.u1.ipv4_address.s_addr = ipv4_addrs[0].s_addr;
/*smf_cfg.upfs.push_back(n); // Do reserve_resolve to find FQDN if not available
upf_profile* upf_node_profile = if (n.fqdn.empty()) {
dynamic_cast<upf_profile*>(profile.get()); std::string hostname = {};
start_upf_association(n, std::ref(*upf_node_profile)); std::string ip_str = conv::toString(n.u1.ipv4_address);
*/ if (!fqdn::reverse_resolve(ip_str, hostname)) {
Logger::smf_app().debug(
"Could not resolve hostname for IP address %s",
ip_str.c_str());
} else {
n.fqdn = hostname;
}
}
} else { } else {
Logger::smf_app().debug( Logger::smf_app().debug(
"UPF node already exist (%s)", inet_ntoa(ipv4_addrs[0])); "UPF node already exist (%s)", inet_ntoa(ipv4_addrs[0]));
...@@ -1473,7 +1490,7 @@ bool smf_app::handle_nf_status_notification( ...@@ -1473,7 +1490,7 @@ bool smf_app::handle_nf_status_notification(
// Trigger N4 association request with retry if needed // Trigger N4 association request with retry if needed
std::shared_ptr<itti_n4_association_retry> itti_msg = std::shared_ptr<itti_n4_association_retry> itti_msg =
std::make_shared<itti_n4_association_retry>( std::make_shared<itti_n4_association_retry>(
TASK_SMF_N4, TASK_SMF_APP); TASK_SMF_APP, TASK_SMF_APP);
itti_msg->node_id = n; itti_msg->node_id = n;
itti_msg->profile = std::ref(*upf_node_profile); itti_msg->profile = std::ref(*upf_node_profile);
int ret = itti_inst->send_msg(itti_msg); int ret = itti_inst->send_msg(itti_msg);
...@@ -1483,7 +1500,8 @@ bool smf_app::handle_nf_status_notification( ...@@ -1483,7 +1500,8 @@ bool smf_app::handle_nf_status_notification(
itti_msg->get_msg_name()); itti_msg->get_msg_name());
} }
} else { } else {
Logger::smf_app().debug("No IP Addr/FQDN found"); Logger::smf_app().debug(
"No IP Addr/FQDN found or UPF node already exist");
return false; return false;
} }
} }
......
...@@ -400,6 +400,9 @@ std::string smf_pdu_session::toString() const { ...@@ -400,6 +400,9 @@ std::string smf_pdu_session::toString() const {
if (!is_released) { if (!is_released) {
s.append("\tSEID:\t\t\t").append(std::to_string(seid)).append("\n"); s.append("\tSEID:\t\t\t").append(std::to_string(seid)).append("\n");
} }
/*
// TODO as FTEID is not updated here, it is confusing to have null output
We need a complete QoS handling refactor
if (default_qfi.qfi) { if (default_qfi.qfi) {
s.append("\tDefault "); s.append("\tDefault ");
for (auto it : qos_flows) { for (auto it : qos_flows) {
...@@ -407,7 +410,9 @@ std::string smf_pdu_session::toString() const { ...@@ -407,7 +410,9 @@ std::string smf_pdu_session::toString() const {
s.append(it.second.toString()); s.append(it.second.toString());
} }
} }
} }
*/
if (policy_ptr) { if (policy_ptr) {
s.append("\t Policy Decision:").append("\n"); s.append("\t Policy Decision:").append("\n");
...@@ -3782,8 +3787,9 @@ bool smf_context::find_dnn_subscription( ...@@ -3782,8 +3787,9 @@ bool smf_context::find_dnn_subscription(
Logger::smf_app().info( Logger::smf_app().info(
"Find a DNN Subscription with key: %ld (SST %d, SD %ld (0x%x)), map size " "Find a DNN Subscription with key: %ld (SST %d, SD %ld (0x%x)), map size "
"%d", "%ld",
(uint8_t) snssai.sst, snssai.sd, snssai.sd, dnn_subscriptions.size()); key, (uint8_t) snssai.sst, snssai.sd, snssai.sd,
dnn_subscriptions.size());
std::unique_lock<std::recursive_mutex> lock(m_context); std::unique_lock<std::recursive_mutex> lock(m_context);
if (dnn_subscriptions.count(key) > 0) { if (dnn_subscriptions.count(key) > 0) {
......
...@@ -44,21 +44,50 @@ extern itti_mw* itti_inst; ...@@ -44,21 +44,50 @@ extern itti_mw* itti_inst;
extern smf_n4* smf_n4_inst; extern smf_n4* smf_n4_inst;
extern smf_config smf_cfg; extern smf_config smf_cfg;
//---------------------------------------------------------------------------------------------
edge edge::from_upf_info(const upf_info_t& upf_info) { edge edge::from_upf_info(const upf_info_t& upf_info) {
edge e; edge e = {};
snssai_upf_info_item_s snssai_item; snssai_upf_info_item_s snssai_item = {};
for (const auto& snssai : upf_info.snssai_upf_info_list) { Logger::smf_app().debug(
"Edge from UPF info, UPF info %s", upf_info.to_string().c_str());
for (auto& snssai : upf_info.snssai_upf_info_list) {
snssai_item.snssai = snssai.snssai; snssai_item.snssai = snssai.snssai;
snssai_item.dnn_upf_info_list = snssai.dnn_upf_info_list; snssai_item.dnn_upf_info_list = snssai.dnn_upf_info_list;
e.snssai_dnns.insert(snssai); bool found = false;
for (auto& item : e.snssai_dnns) {
if (item.snssai == snssai.snssai) {
// Update item if exist
found = true;
snssai_item.dnn_upf_info_list.insert(
item.dnn_upf_info_list.begin(), item.dnn_upf_info_list.end());
item.dnn_upf_info_list = snssai_item.dnn_upf_info_list;
Logger::smf_app().debug(
"Updated item info: %s", snssai_item.to_string().c_str());
break;
}
}
// Insert a new item otherwise
if (!found) e.snssai_dnns.insert(snssai_item);
}
if (!e.snssai_dnns.empty()) {
Logger::smf_app().debug("Edge from UPF info");
for (const auto s : e.snssai_dnns) {
Logger::smf_app().debug("info: %s", s.to_string().c_str());
}
} else {
Logger::smf_app().debug("Edge from UPF info, empty");
} }
return e; return e;
} }
//---------------------------------------------------------------------------------------------
edge edge::from_upf_info( edge edge::from_upf_info(
const upf_info_t& upf_info, const interface_upf_info_item_t& interface) { const upf_info_t& upf_info, const interface_upf_info_item_t& interface) {
edge e; // TODO: Bring updates from the previous funtion to this one
edge e = {};
e.type = pfcp_association::iface_type_from_string(interface.interface_type); e.type = pfcp_association::iface_type_from_string(interface.interface_type);
e.nw_instance = interface.network_instance; e.nw_instance = interface.network_instance;
...@@ -93,21 +122,33 @@ edge edge::from_upf_info( ...@@ -93,21 +122,33 @@ edge edge::from_upf_info(
return e; return e;
} }
//---------------------------------------------------------------------------------------------
bool edge::serves_network( bool edge::serves_network(
const std::string& dnn, const snssai_t& snssai, const std::string& dnn, const snssai_t& snssai,
const std::unordered_set<std::string>& dnais, const std::unordered_set<std::string>& dnais,
std::string& matched_dnai) const { std::string& matched_dnai) const {
Logger::smf_app().debug(
"Serves Network, DNN %s, S-NSSAI %s", dnn.c_str(),
snssai.toString().c_str());
// just create a snssai_upf_info_item for fast lookup // just create a snssai_upf_info_item for fast lookup
snssai_upf_info_item_s snssai_item; snssai_upf_info_item_s snssai_item = {};
snssai_item.snssai = snssai; snssai_item.snssai = snssai;
// For debugging purpose
if (!snssai_dnns.empty()) {
Logger::smf_app().debug("S-NSSAI UPF info list");
for (const auto& s : snssai_dnns) {
Logger::smf_app().debug(
"S-NSSAI UPF info item %s", s.to_string().c_str());
}
}
auto snssai_it = snssai_dnns.find(snssai_item); for (const auto& snssai_it : snssai_dnns) {
if (snssai_it != snssai_dnns.end()) { if (snssai_it.snssai == snssai_item.snssai) {
// create temp item for fast lookup // create temp item for fast lookup
dnn_upf_info_item_s dnn_item; dnn_upf_info_item_s dnn_item = {};
dnn_item.dnn = dnn; dnn_item.dnn = dnn;
auto dnn_it = snssai_it->dnn_upf_info_list.find(dnn_item); auto dnn_it = snssai_it.dnn_upf_info_list.find(dnn_item);
if (dnn_it != snssai_it->dnn_upf_info_list.end()) { if (dnn_it != snssai_it.dnn_upf_info_list.end()) {
if (!dnais.empty()) { if (!dnais.empty()) {
// should be only 1 DNAI // should be only 1 DNAI
for (const auto& dnai : dnn_it->dnai_list) { for (const auto& dnai : dnn_it->dnai_list) {
...@@ -123,16 +164,21 @@ bool edge::serves_network( ...@@ -123,16 +164,21 @@ bool edge::serves_network(
} }
} }
} }
}
Logger::smf_app().debug("Could not serve network, return false");
return false; return false;
} }
//---------------------------------------------------------------------------------------------
bool edge::serves_network( bool edge::serves_network(
const std::string& dnn, const snssai_t& snssai) const { const std::string& dnn, const snssai_t& snssai) const {
std::unordered_set<string> set; std::unordered_set<string> set;
std::string s; std::string s = {};
return serves_network(dnn, snssai, set, s); return serves_network(dnn, snssai, set, s);
} }
//---------------------------------------------------------------------------------------------
std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::pdr_id_t& pdr_id) { std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::pdr_id_t& pdr_id) {
// it may happen that 2 qos flows have the same PDR ID e.g. in an // it may happen that 2 qos flows have the same PDR ID e.g. in an
// UL CL scenario, but then they will also have the same FTEID // UL CL scenario, but then they will also have the same FTEID
...@@ -144,6 +190,7 @@ std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::pdr_id_t& pdr_id) { ...@@ -144,6 +190,7 @@ std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::pdr_id_t& pdr_id) {
return {}; return {};
} }
//---------------------------------------------------------------------------------------------
std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::qfi_t& qfi) { std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::qfi_t& qfi) {
for (auto& flow_it : qos_flows) { for (auto& flow_it : qos_flows) {
if (flow_it->qfi == qfi) { if (flow_it->qfi == qfi) {
...@@ -153,6 +200,7 @@ std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::qfi_t& qfi) { ...@@ -153,6 +200,7 @@ std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::qfi_t& qfi) {
return {}; return {};
} }
//---------------------------------------------------------------------------------------------
std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::far_id_t& far_id) { std::shared_ptr<smf_qos_flow> edge::get_qos_flow(const pfcp::far_id_t& far_id) {
for (auto& flow_it : qos_flows) { for (auto& flow_it : qos_flows) {
if (flow_it->far_id_ul.second == far_id || if (flow_it->far_id_ul.second == far_id ||
...@@ -214,7 +262,7 @@ void smf_qos_flow::deallocate_ressources() { ...@@ -214,7 +262,7 @@ void smf_qos_flow::deallocate_ressources() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
iface_type pfcp_association::iface_type_from_string(const std::string& input) { iface_type pfcp_association::iface_type_from_string(const std::string& input) {
iface_type type_tmp; iface_type type_tmp = {};
if (input == "N3") { if (input == "N3") {
type_tmp = iface_type::N3; type_tmp = iface_type::N3;
} else if (input == "N6") { } else if (input == "N6") {
...@@ -229,7 +277,7 @@ iface_type pfcp_association::iface_type_from_string(const std::string& input) { ...@@ -229,7 +277,7 @@ iface_type pfcp_association::iface_type_from_string(const std::string& input) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::string pfcp_association::string_from_iface_type(const iface_type& type) { std::string pfcp_association::string_from_iface_type(const iface_type& type) {
std::string output; std::string output = {};
switch (type) { switch (type) {
case iface_type::N3: case iface_type::N3:
return "N3"; return "N3";
...@@ -282,12 +330,13 @@ void pfcp_association::restore_n4_sessions() { ...@@ -282,12 +330,13 @@ void pfcp_association::restore_n4_sessions() {
} }
} }
//---------------------------------------------------------------------------------------------
bool pfcp_association::find_interface_edge( bool pfcp_association::find_interface_edge(
const iface_type& type_match, std::vector<edge>& edges) { const iface_type& type_match, std::vector<edge>& edges) {
if (!is_upf_profile_set()) { if (!is_upf_profile_set()) {
return false; return false;
} }
upf_info_t upf_info; upf_info_t upf_info = {};
upf_node_profile.get_upf_info(upf_info); upf_node_profile.get_upf_info(upf_info);
for (const auto& iface : upf_info.interface_upf_info_list) { for (const auto& iface : upf_info.interface_upf_info_list) {
...@@ -310,10 +359,12 @@ bool pfcp_association::find_interface_edge( ...@@ -310,10 +359,12 @@ bool pfcp_association::find_interface_edge(
return !edges.empty(); return !edges.empty();
} }
//---------------------------------------------------------------------------------------------
bool pfcp_association::find_n3_edge(std::vector<edge>& edges) { bool pfcp_association::find_n3_edge(std::vector<edge>& edges) {
return find_interface_edge(iface_type::N3, edges); return find_interface_edge(iface_type::N3, edges);
} }
//---------------------------------------------------------------------------------------------
bool pfcp_association::find_n6_edge(std::vector<edge>& edges) { bool pfcp_association::find_n6_edge(std::vector<edge>& edges) {
bool success = find_interface_edge(iface_type::N6, edges); bool success = find_interface_edge(iface_type::N6, edges);
if (success) { if (success) {
...@@ -375,6 +426,16 @@ std::string pfcp_association::get_printable_name() { ...@@ -375,6 +426,16 @@ std::string pfcp_association::get_printable_name() {
} }
} }
//------------------------------------------------------------------------------
void pfcp_association::display() {
Logger::smf_app().debug("\tUPF Node Id: %s", node_id.toString().c_str());
if (upf_profile_is_set) {
Logger::smf_app().debug("\tUPF Node profile:");
upf_node_profile.display();
}
}
/******************************************************************************/ /******************************************************************************/
/***************************** PFCP ASSOCIATIONS ******************************/ /***************************** PFCP ASSOCIATIONS ******************************/
/******************************************************************************/ /******************************************************************************/
...@@ -383,7 +444,7 @@ std::shared_ptr<pfcp_association> pfcp_associations::check_association_on_add( ...@@ -383,7 +444,7 @@ std::shared_ptr<pfcp_association> pfcp_associations::check_association_on_add(
pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp, pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp,
bool& restore_n4_sessions, const bool use_function_features, bool& restore_n4_sessions, const bool use_function_features,
pfcp::up_function_features_s& function_features) { pfcp::up_function_features_s& function_features) {
std::shared_ptr<pfcp_association> sa; std::shared_ptr<pfcp_association> sa = {};
if (get_association(node_id, sa)) { if (get_association(node_id, sa)) {
itti_inst->timer_remove(sa->timer_heartbeat); itti_inst->timer_remove(sa->timer_heartbeat);
if (sa->recovery_time_stamp == recovery_time_stamp) { if (sa->recovery_time_stamp == recovery_time_stamp) {
...@@ -405,6 +466,7 @@ std::shared_ptr<pfcp_association> pfcp_associations::check_association_on_add( ...@@ -405,6 +466,7 @@ std::shared_ptr<pfcp_association> pfcp_associations::check_association_on_add(
return {}; // empty ptr return {}; // empty ptr
} }
//---------------------------------------------------------------------------------------------
bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) { bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) {
// TODO why is this even here? We can see in the logs that UPF IP is requested // TODO why is this even here? We can see in the logs that UPF IP is requested
// before, at least for NRF scenario // before, at least for NRF scenario
...@@ -412,9 +474,9 @@ bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) { ...@@ -412,9 +474,9 @@ bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) {
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_FQDN) { if (node_id.node_id_type == pfcp::NODE_ID_TYPE_FQDN) {
Logger::smf_app().info("Node ID Type FQDN: %s", node_id.fqdn.c_str()); Logger::smf_app().info("Node ID Type FQDN: %s", node_id.fqdn.c_str());
std::string ip_addr; std::string ip_addr = {};
uint32_t port; uint32_t port = {0};
uint8_t addr_type; uint8_t addr_type = {0};
if (!fqdn::resolve(node_id.fqdn, ip_addr, port, addr_type)) { if (!fqdn::resolve(node_id.fqdn, ip_addr, port, addr_type)) {
Logger::smf_app().warn( Logger::smf_app().warn(
...@@ -441,6 +503,7 @@ bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) { ...@@ -441,6 +503,7 @@ bool pfcp_associations::resolve_upf_hostname(pfcp::node_id_t& node_id) {
return true; // no FQDN so we just continue return true; // no FQDN so we just continue
} }
//---------------------------------------------------------------------------------------------
void pfcp_associations::associate_with_upf_profile( void pfcp_associations::associate_with_upf_profile(
std::shared_ptr<pfcp_association>& sa, const pfcp::node_id_t& node_id) { std::shared_ptr<pfcp_association>& sa, const pfcp::node_id_t& node_id) {
// TODO wouldn't it be better to use a shared lock? because here we have only // TODO wouldn't it be better to use a shared lock? because here we have only
...@@ -460,7 +523,7 @@ void pfcp_associations::associate_with_upf_profile( ...@@ -460,7 +523,7 @@ void pfcp_associations::associate_with_upf_profile(
bool pfcp_associations::add_association( bool pfcp_associations::add_association(
pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp, pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp,
bool& restore_n4_sessions) { bool& restore_n4_sessions) {
pfcp::up_function_features_s tmp; pfcp::up_function_features_s tmp = {};
std::shared_ptr<pfcp_association> sa = check_association_on_add( std::shared_ptr<pfcp_association> sa = check_association_on_add(
node_id, recovery_time_stamp, restore_n4_sessions, false, tmp); node_id, recovery_time_stamp, restore_n4_sessions, false, tmp);
if (sa) return true; if (sa) return true;
...@@ -515,6 +578,7 @@ bool pfcp_associations::add_association( ...@@ -515,6 +578,7 @@ bool pfcp_associations::add_association(
} }
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool pfcp_associations::add_association( bool pfcp_associations::add_association(
pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp, pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp,
...@@ -566,40 +630,42 @@ bool pfcp_associations::update_association( ...@@ -566,40 +630,42 @@ bool pfcp_associations::update_association(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool pfcp_associations::get_association( bool pfcp_associations::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 { std::shared_ptr<pfcp_association> association = {};
std::size_t hash_node_id = std::hash<pfcp::node_id_t>{}(node_id); std::size_t hash_node_id = {};
auto association = associations_graph.get_association(hash_node_id); pfcp::node_id_t node_id_tmp = node_id;
if (!association) { // Resolve FQDN/IP Addr if necessary
// We didn't find association, may be because hash map is made with fqdn::resolve(node_id_tmp);
// node_id_type FQDN
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) { // We suppose that by default hash map is made with node_id_type FQDN
std::string hostname; if (node_id_tmp.node_id_type == pfcp::NODE_ID_TYPE_FQDN) {
std::string ip_str = conv::toString(node_id.u1.ipv4_address); hash_node_id = std::hash<pfcp::node_id_t>{}(node_id_tmp);
association = associations_graph.get_association(hash_node_id);
if (!fqdn::reverse_resolve(ip_str, hostname)) { if (association) {
Logger::smf_app().warn( sa = association;
"Could not resolve hostname for IP address %s", ip_str.c_str()); return true;
return false; }
node_id_tmp.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS;
} else if (node_id_tmp.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id_tmp);
association = associations_graph.get_association(hash_node_id);
if (association) {
sa = association;
return true;
} }
pfcp::node_id_t node_id_tmp = {};
node_id_tmp.node_id_type = pfcp::NODE_ID_TYPE_FQDN; node_id_tmp.node_id_type = pfcp::NODE_ID_TYPE_FQDN;
node_id_tmp.fqdn = hostname;
Logger::smf_app().debug(
"Hash lookup for association retry: Associated Hostname -> %s",
hostname.c_str());
if (get_association(node_id_tmp, sa)) return true;
} }
// We didn't found association, may be because hash map is made with
// node_id_type IP ADDR // We didn't found association, may be because hash map is made with different
// ToDo (Might stuck in recursive loop here) // node type
return false; hash_node_id = std::hash<pfcp::node_id_t>{}(node_id_tmp);
} else { association = associations_graph.get_association(hash_node_id);
if (association) {
sa = association; sa = association;
return true; return true;
} }
return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -781,6 +847,8 @@ bool pfcp_associations::add_peer_candidate_node( ...@@ -781,6 +847,8 @@ bool pfcp_associations::add_peer_candidate_node(
std::make_shared<pfcp_association>(node_id); std::make_shared<pfcp_association>(node_id);
s->set_upf_node_profile(profile); s->set_upf_node_profile(profile);
pending_associations.push_back(s); pending_associations.push_back(s);
Logger::smf_app().info("Added a pending association candidate");
s->display();
return true; return true;
} }
...@@ -811,10 +879,10 @@ void upf_graph::insert_into_graph(const std::shared_ptr<pfcp_association>& sa) { ...@@ -811,10 +879,10 @@ void upf_graph::insert_into_graph(const std::shared_ptr<pfcp_association>& sa) {
"just add the node"); "just add the node");
Logger::smf_app().info("Assume that the UPF has a N3 and a N6 interface."); Logger::smf_app().info("Assume that the UPF has a N3 and a N6 interface.");
edge n3_edge; edge n3_edge = {};
n3_edge.type = iface_type::N3; n3_edge.type = iface_type::N3;
n3_edge.uplink = false; n3_edge.uplink = false;
edge n6_edge; edge n6_edge = {};
n6_edge.type = iface_type::N6; n6_edge.type = iface_type::N6;
n6_edge.uplink = true; n6_edge.uplink = true;
...@@ -951,13 +1019,16 @@ bool upf_graph::remove_association( ...@@ -951,13 +1019,16 @@ bool upf_graph::remove_association(
return false; return false;
} }
//---------------------------------------------------------------------------------------------
void upf_graph::add_upf_graph_edge( void upf_graph::add_upf_graph_edge(
const std::shared_ptr<pfcp_association>& source, edge& edge_info_src_dst) { const std::shared_ptr<pfcp_association>& source, edge& edge_info_src_dst) {
add_upf_graph_node(source); add_upf_graph_node(source);
std::unique_lock lock_graph(graph_mutex); std::unique_lock lock_graph(graph_mutex);
auto it_src = adjacency_list.find(source); auto it_src = adjacency_list.find(source);
if (it_src == adjacency_list.end()) {
return;
}
bool exists = false; bool exists = false;
for (const auto& edge : it_src->second) { for (const auto& edge : it_src->second) {
if (edge == edge_info_src_dst) { if (edge == edge_info_src_dst) {
...@@ -1173,6 +1244,7 @@ void upf_graph::start_asynch_dfs_procedure( ...@@ -1173,6 +1244,7 @@ void upf_graph::start_asynch_dfs_procedure(
} }
} }
//---------------------------------------------------------------------------------------------
edge upf_graph::get_access_edge() const { edge upf_graph::get_access_edge() const {
std::shared_lock graph_lock(graph_mutex); std::shared_lock graph_lock(graph_mutex);
edge info; edge info;
...@@ -1188,6 +1260,7 @@ edge upf_graph::get_access_edge() const { ...@@ -1188,6 +1260,7 @@ edge upf_graph::get_access_edge() const {
return info; return info;
} }
//---------------------------------------------------------------------------------------------
void upf_graph::update_edge_info( void upf_graph::update_edge_info(
const std::shared_ptr<pfcp_association>& upf, const edge& info) { const std::shared_ptr<pfcp_association>& upf, const edge& info) {
std::unique_lock graph_lock(graph_mutex); std::unique_lock graph_lock(graph_mutex);
...@@ -1205,26 +1278,31 @@ void upf_graph::update_edge_info( ...@@ -1205,26 +1278,31 @@ void upf_graph::update_edge_info(
} }
} }
//---------------------------------------------------------------------------------------------
std::shared_ptr<upf_graph> upf_graph::select_upf_node( std::shared_ptr<upf_graph> upf_graph::select_upf_node(
const snssai_t& snssai, const std::string& dnn) { const snssai_t& snssai, const std::string& dnn) {
Logger::smf_app().info("Select UPF Node");
std::shared_ptr<upf_graph> upf_graph_ptr = std::make_shared<upf_graph>(); std::shared_ptr<upf_graph> upf_graph_ptr = std::make_shared<upf_graph>();
std::shared_lock graph_lock(graph_mutex); std::shared_lock graph_lock(graph_mutex);
std::shared_ptr<pfcp_association> not_found; std::shared_ptr<pfcp_association> not_found = {};
if (adjacency_list.empty()) { if (adjacency_list.empty()) {
Logger::smf_app().warn("No UPF available"); Logger::smf_app().warn("No UPF available");
} }
// First, only consider UPFs with profile ID set // First, only consider UPFs with profile ID set
for (const auto& it : adjacency_list) { for (const auto& it : adjacency_list) {
std::shared_ptr<pfcp_association> current_upf = it.first; std::shared_ptr<pfcp_association> current_upf = it.first;
Logger::smf_app().debug("Current UPF info");
current_upf->display();
if (current_upf->is_upf_profile_set()) { if (current_upf->is_upf_profile_set()) {
upf_info_t upf_info; upf_info_t upf_info = {};
std::vector<snssai_t> snssais = {}; std::vector<snssai_t> snssais = {};
current_upf->get_upf_node_profile().get_upf_info(upf_info); current_upf->get_upf_node_profile().get_upf_info(upf_info);
bool has_access = false; bool has_access = false;
bool has_exit = false; bool has_exit = false;
edge access_edge; edge access_edge = {};
edge exit_edge; edge exit_edge = {};
for (const auto& edge : it.second) { for (const auto& edge : it.second) {
Logger::smf_app().debug("Verify Slice/DNN support");
// verify that UPF belongs to the same slice and supports this dnn // verify that UPF belongs to the same slice and supports this dnn
if (edge.serves_network(dnn, snssai)) { if (edge.serves_network(dnn, snssai)) {
if (edge.type == iface_type::N3) { if (edge.type == iface_type::N3) {
...@@ -1268,10 +1346,11 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_node( ...@@ -1268,10 +1346,11 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_node(
return upf_graph_ptr; return upf_graph_ptr;
} }
//---------------------------------------------------------------------------------------------
std::shared_ptr<upf_graph> upf_graph::select_upf_node( std::shared_ptr<upf_graph> upf_graph::select_upf_node(
const int node_selection_criteria) { const int node_selection_criteria) {
std::shared_lock graph_lock(graph_mutex); std::shared_lock graph_lock(graph_mutex);
std::shared_ptr<pfcp_association> association; std::shared_ptr<pfcp_association> association = {};
std::shared_ptr<upf_graph> upf_graph_ptr = std::make_shared<upf_graph>(); std::shared_ptr<upf_graph> upf_graph_ptr = std::make_shared<upf_graph>();
Logger::smf_app().error("Called non-implemented UPF selection function"); Logger::smf_app().error("Called non-implemented UPF selection function");
...@@ -1302,6 +1381,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_node( ...@@ -1302,6 +1381,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_node(
} }
return upf_graph_ptr; return upf_graph_ptr;
} }
return upf_graph_ptr;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1327,7 +1407,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_nodes( ...@@ -1327,7 +1407,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_nodes(
// std::shared_ptr<upf_graph> correct_sub_graph_ptr; // std::shared_ptr<upf_graph> correct_sub_graph_ptr;
std::unordered_set<std::string> dnais_from_all_rules; std::unordered_set<std::string> dnais_from_all_rules;
std::shared_ptr<upf_graph> sub_graph_ptr; std::shared_ptr<upf_graph> sub_graph_ptr = {};
// run DFS for each PCC rule, get different graphs and merge them // run DFS for each PCC rule, get different graphs and merge them
...@@ -1443,6 +1523,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_nodes( ...@@ -1443,6 +1523,7 @@ std::shared_ptr<upf_graph> upf_graph::select_upf_nodes(
return sub_graph_ptr; return sub_graph_ptr;
} }
//---------------------------------------------------------------------------------------------
bool upf_graph::verify() { bool upf_graph::verify() {
int access_count = 0; int access_count = 0;
bool has_exit = false; bool has_exit = false;
...@@ -1511,8 +1592,9 @@ bool upf_graph::verify() { ...@@ -1511,8 +1592,9 @@ bool upf_graph::verify() {
return false; return false;
} }
//---------------------------------------------------------------------------------------------
std::string upf_graph::get_dnai_list(const std::unordered_set<string>& dnais) { std::string upf_graph::get_dnai_list(const std::unordered_set<string>& dnais) {
std::string out; std::string out = {};
for (const auto& dnai : dnais) { for (const auto& dnai : dnais) {
out.append(dnai).append(", "); out.append(dnai).append(", ");
...@@ -1523,6 +1605,7 @@ std::string upf_graph::get_dnai_list(const std::unordered_set<string>& dnais) { ...@@ -1523,6 +1605,7 @@ std::string upf_graph::get_dnai_list(const std::unordered_set<string>& dnais) {
return out; return out;
} }
//---------------------------------------------------------------------------------------------
void upf_graph::set_dfs_selection_criteria( void upf_graph::set_dfs_selection_criteria(
const std::unordered_set<std::string>& all_dnais, const std::unordered_set<std::string>& all_dnais,
const std::string& flow_description, uint32_t precedence, const std::string& flow_description, uint32_t precedence,
...@@ -1534,6 +1617,7 @@ void upf_graph::set_dfs_selection_criteria( ...@@ -1534,6 +1617,7 @@ void upf_graph::set_dfs_selection_criteria(
dfs_dnn = dnn; dfs_dnn = dnn;
} }
//---------------------------------------------------------------------------------------------
void upf_graph::create_subgraph_dfs( void upf_graph::create_subgraph_dfs(
std::shared_ptr<upf_graph>& sub_graph, std::shared_ptr<upf_graph>& sub_graph,
const std::shared_ptr<pfcp_association>& start_node, const std::shared_ptr<pfcp_association>& start_node,
...@@ -1622,6 +1706,7 @@ void upf_graph::create_subgraph_dfs( ...@@ -1622,6 +1706,7 @@ void upf_graph::create_subgraph_dfs(
} }
} }
//---------------------------------------------------------------------------------------------
bool upf_graph::full() const { bool upf_graph::full() const {
std::shared_lock graph_lock(graph_mutex); std::shared_lock graph_lock(graph_mutex);
......
...@@ -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);
...@@ -313,6 +328,13 @@ struct edge { ...@@ -313,6 +328,13 @@ struct edge {
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;
} }
}; };
...@@ -615,8 +637,7 @@ class pfcp_associations { ...@@ -615,8 +637,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;
......
...@@ -27,11 +27,12 @@ ...@@ -27,11 +27,12 @@
\email: Tien-Thinh.Nguyen@eurecom.fr \email: Tien-Thinh.Nguyen@eurecom.fr
*/ */
#include "smf_profile.hpp"
#include "3gpp_conversions.hpp"
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include "logger.hpp" #include "logger.hpp"
#include "smf_profile.hpp"
#include "string.hpp" #include "string.hpp"
using namespace std; using namespace std;
...@@ -282,17 +283,11 @@ void nf_profile::from_json(const nlohmann::json& data) { ...@@ -282,17 +283,11 @@ void nf_profile::from_json(const nlohmann::json& data) {
if (data.find("sNssais") != data.end()) { if (data.find("sNssais") != data.end()) {
for (auto it : data["sNssais"]) { for (auto it : data["sNssais"]) {
snssai_t s = {}; snssai_t s = {};
s.sst = it["sst"].get<int>(); s.sd = SD_NO_VALUE;
s.sd = 0xFFFFFF; if (it.find("sst") != it.end()) s.sst = it["sst"].get<int>();
try { if (it.find("sd") != it.end()) {
s.sd = std::stoul(it["sd"].get<std::string>(), nullptr, 10); xgpp_conv::sd_string_to_int(it["sd"].get<std::string>(), s.sd);
} catch (const std::exception& e) {
Logger::smf_app().warn(
"Error when converting from string to int for snssai.SD, error: %s",
e.what());
} }
// s.sD = it["sd"].get<std::string>();
snssais.push_back(s); snssais.push_back(s);
} }
} }
...@@ -472,20 +467,13 @@ void smf_profile::from_json(const nlohmann::json& data) { ...@@ -472,20 +467,13 @@ void smf_profile::from_json(const nlohmann::json& data) {
for (auto it : snssai_smf_info_list) { for (auto it : snssai_smf_info_list) {
snssai_smf_info_item_t smf_info_item = {}; snssai_smf_info_item_t smf_info_item = {};
smf_info_item.snssai.sd = SD_NO_VALUE;
if (it.find("sNssai") != it.end()) { if (it.find("sNssai") != it.end()) {
if (it["sNssai"].find("sst") != it["sNssai"].end()) if (it["sNssai"].find("sst") != it["sNssai"].end())
smf_info_item.snssai.sst = it["sNssai"]["sst"].get<int>(); smf_info_item.snssai.sst = it["sNssai"]["sst"].get<int>();
if (it["sNssai"].find("sd") != it["sNssai"].end()) { if (it["sNssai"].find("sd") != it["sNssai"].end()) {
smf_info_item.snssai.sd = 0xFFFFFF; xgpp_conv::sd_string_to_int(
try { it["sNssai"]["sd"].get<std::string>(), smf_info_item.snssai.sd);
smf_info_item.snssai.sd = std::stoul(
it["sNssai"]["sd"].get<std::string>(), nullptr, 10);
} catch (const std::exception& e) {
Logger::smf_app().warn(
"Error when converting from string to int for snssai.SD, "
"error: %s",
e.what());
}
} }
} }
if (it.find("dnnSmfInfoList") != it.end()) { if (it.find("dnnSmfInfoList") != it.end()) {
...@@ -629,20 +617,13 @@ void upf_profile::from_json(const nlohmann::json& data) { ...@@ -629,20 +617,13 @@ void upf_profile::from_json(const nlohmann::json& data) {
for (auto it : snssai_upf_info_list) { for (auto it : snssai_upf_info_list) {
snssai_upf_info_item_t upf_info_item = {}; snssai_upf_info_item_t upf_info_item = {};
upf_info_item.snssai.sd = SD_NO_VALUE;
if (it.find("sNssai") != it.end()) { if (it.find("sNssai") != it.end()) {
if (it["sNssai"].find("sst") != it["sNssai"].end()) if (it["sNssai"].find("sst") != it["sNssai"].end())
upf_info_item.snssai.sst = it["sNssai"]["sst"].get<int>(); upf_info_item.snssai.sst = it["sNssai"]["sst"].get<int>();
if (it["sNssai"].find("sd") != it["sNssai"].end()) { if (it["sNssai"].find("sd") != it["sNssai"].end()) {
upf_info_item.snssai.sd = 0xFFFFFF; xgpp_conv::sd_string_to_int(
try { it["sNssai"]["sd"].get<std::string>(), upf_info_item.snssai.sd);
upf_info_item.snssai.sd = std::stoul(
it["sNssai"]["sd"].get<std::string>(), nullptr, 10);
} catch (const std::exception& e) {
Logger::smf_app().warn(
"Error when converting from string to int for snssai.SD, "
"error: %s",
e.what());
}
} }
} }
if (it.find("dnnUpfInfoList") != it.end()) { if (it.find("dnnUpfInfoList") != it.end()) {
......
...@@ -927,7 +927,7 @@ bool smf_sbi::get_sm_data( ...@@ -927,7 +927,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) {
......
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