Commit 2db8bca2 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge branch 'feature_new_upf_graph' into 'develop'

Added and integrated UPF graph instead of PFCP associations list

See merge request oai/cn5g/oai-cn5g-smf!157
parents b6c7c991 556919c3
......@@ -35,6 +35,8 @@ void to_json(nlohmann::json& j, const DnnUpfInfoItem& o) {
if (o.dnaiListIsSet() || !o.m_DnaiList.empty()) j["dnaiList"] = o.m_DnaiList;
if (o.pduSessionTypesIsSet() || !o.m_PduSessionTypes.empty())
j["pduSessionTypes"] = o.m_PduSessionTypes;
if (o.dnaiNwInstanceListIsSet() || !o.m_DnaiNwInstanceList.empty())
j["dnaiNwInstanceList"] = o.m_DnaiNwInstanceList;
}
void from_json(const nlohmann::json& j, DnnUpfInfoItem& o) {
......@@ -47,6 +49,10 @@ void from_json(const nlohmann::json& j, DnnUpfInfoItem& o) {
j.at("pduSessionTypes").get_to(o.m_PduSessionTypes);
o.m_PduSessionTypesIsSet = true;
}
if (j.find("dnaiNwInstanceList") != j.end()) {
j.at("dnaiNwInstanceList").get_to(o.m_DnaiNwInstanceList);
o.m_DnaiNwInstanceListIsSet = true;
}
}
std::string DnnUpfInfoItem::getDnn() const {
......@@ -83,6 +89,21 @@ void DnnUpfInfoItem::unsetPduSessionTypes() {
m_PduSessionTypesIsSet = false;
}
std::map<std::string, std::string>& DnnUpfInfoItem::getDnaiNwInstanceList() {
return m_DnaiNwInstanceList;
}
void DnnUpfInfoItem::setDnaiNwInstanceList(
std::map<std::string, std::string> const& value) {
m_DnaiNwInstanceList = value;
m_DnaiNwInstanceListIsSet = true;
}
bool DnnUpfInfoItem::dnaiNwInstanceListIsSet() const {
return m_DnaiNwInstanceListIsSet;
}
void DnnUpfInfoItem::unsetDnaiNwInstanceList() {
m_DnaiNwInstanceListIsSet = false;
}
} // namespace model
} // namespace smf_server
} // namespace oai
......@@ -22,6 +22,7 @@
#include <string>
#include "PduSessionType.h"
#include <vector>
#include <map>
#include <nlohmann/json.hpp>
namespace oai {
......@@ -61,6 +62,11 @@ class DnnUpfInfoItem {
bool pduSessionTypesIsSet() const;
void unsetPduSessionTypes();
std::map<std::string, std::string>& getDnaiNwInstanceList();
void setDnaiNwInstanceList(std::map<std::string, std::string> const& value);
bool dnaiNwInstanceListIsSet() const;
void unsetDnaiNwInstanceList();
friend void to_json(nlohmann::json& j, const DnnUpfInfoItem& o);
friend void from_json(const nlohmann::json& j, DnnUpfInfoItem& o);
......@@ -71,6 +77,9 @@ class DnnUpfInfoItem {
bool m_DnaiListIsSet;
std::vector<PduSessionType> m_PduSessionTypes;
bool m_PduSessionTypesIsSet;
std::map<std::string, std::string> m_DnaiNwInstanceList;
bool m_DnaiNwInstanceListIsSet;
};
} // namespace model
......
......@@ -732,6 +732,16 @@ void PccRule::unsetTscaiInputUl() {
}
*/
std::string PccRule::getFirstFlowDescription() const {
std::string flow = "";
if (flowInfosIsSet() && getFlowInfos().size() > 0) {
if (getFlowInfos()[0].flowDescriptionIsSet()) {
flow = getFlowInfos()[0].getFlowDescription();
}
}
return flow;
}
} // namespace model
} // namespace smf_server
} // namespace oai
......@@ -210,6 +210,8 @@ class PccRule {
void unsetTscaiInputUl();
*/
std::string getFirstFlowDescription() const;
friend void to_json(nlohmann::json& j, const PccRule& o);
friend void from_json(const nlohmann::json& j, PccRule& o);
......
......@@ -27,6 +27,10 @@
#include "3gpp_24.501.h"
#include <nlohmann/json.hpp>
#include <map>
#include <vector>
#include <unordered_set>
typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64
......@@ -74,6 +78,9 @@ static uint64_t smf_supi_to_u64(supi_t supi) {
typedef struct s_nssai // section 28.4, TS23.003
{
const uint8_t HASH_SEED = 17;
const uint8_t HASH_FACTOR = 31;
uint8_t sst;
uint32_t sd;
s_nssai(const uint8_t& m_sst, const uint32_t m_sd) : sst(m_sst), sd(m_sd) {}
......@@ -110,6 +117,13 @@ typedef struct s_nssai // section 28.4, TS23.003
return s;
}
size_t operator()(const s_nssai&) const {
size_t res = HASH_SEED;
res = res * HASH_FACTOR + std::hash<uint32_t>()(sd);
res = res * HASH_FACTOR + std::hash<uint32_t>()(sst);
return res;
}
} snssai_t;
typedef uint8_t pdu_session_id;
......@@ -348,18 +362,30 @@ typedef struct nf_service_s {
typedef struct dnn_upf_info_item_s {
std::string dnn;
// std::vector<std::string> dnai_list
std::unordered_set<std::string> dnai_list;
// supported from R16.8
std::map<std::string, std::string> dnai_nw_instance_list;
// std::vector<std::string> pdu_session_types
dnn_upf_info_item_s& operator=(const dnn_upf_info_item_s& d) {
dnn = d.dnn;
dnn = d.dnn;
dnai_list = d.dnai_list;
dnai_nw_instance_list = d.dnai_nw_instance_list;
return *this;
}
bool operator==(const dnn_upf_info_item_s& s) const { return dnn == s.dnn; }
size_t operator()(const dnn_upf_info_item_s&) const {
return std::hash<std::string>()(dnn);
}
} dnn_upf_info_item_t;
typedef struct snssai_upf_info_item_s {
snssai_t snssai;
std::vector<dnn_upf_info_item_t> dnn_upf_info_list;
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) {
snssai = s.snssai;
......@@ -367,6 +393,14 @@ typedef struct snssai_upf_info_item_s {
return *this;
}
bool operator==(const snssai_upf_info_item_s& s) const {
return snssai == s.snssai;
}
size_t operator()(const snssai_upf_info_item_s&) const {
return snssai.operator()(snssai);
}
} snssai_upf_info_item_t;
typedef struct interface_upf_info_item_s {
......
......@@ -72,3 +72,39 @@ bool fqdn::resolve(
return false;
}
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;
while (tries < MAX_NB_RESOLVE_TRIES) {
try {
boost::asio::io_context io_context = {};
Logger::smf_app().debug("Reverse Resolving Try #%u", tries);
boost::asio::ip::address addr =
boost::asio::ip::address::from_string(ip_addr);
boost::asio::ip::tcp::endpoint ep;
ep.address(addr);
boost::asio::ip::tcp::resolver resolver(io_context);
boost::asio::ip::tcp::resolver::results_type endpoints =
resolver.resolve(ep);
for (const auto& endpoint : endpoints) {
// get the first endpoint
host_name = endpoint.host_name();
return true;
}
} catch (std::exception& e) {
tries++;
if (tries == MAX_NB_RESOLVE_TRIES) {
Logger::smf_app().warn(
"Cannot resolve IP address %s: %s -- After %d tries",
ip_addr.c_str(), e.what(), tries);
return false;
}
std::this_thread::sleep_for(std::chrono::seconds(TIME_BETWEEN_TRIES));
}
}
return false;
}
\ No newline at end of file
......@@ -40,6 +40,15 @@ class fqdn {
static bool resolve(
const std::string& host_name, std::string& address, uint32_t& port,
uint8_t& addr_type, const std::string& protocol = "http");
/**
* @brief Resolves an IP address to get the hostname
* @param ip_address to resolve
* @param host_name result, if return=true
* @return true if successful
*/
static bool reverse_resolve(
const std::string& ip_address, std::string& host_name);
};
#endif /* FILE_FQDN_HPP_SEEN */
......@@ -573,6 +573,11 @@ void smf_app::handle_itti_msg(std::shared_ptr<itti_n4_node_failure> snf) {
std::map<pdu_session_id_t, std::shared_ptr<smf_pdu_session>> sessions;
sc.get()->get_pdu_sessions(sessions);
// TODO commented out because this code does not anything (except logging)
// when does this happen? when a pfcp association fails? Then we need to
// remove all the other PFCP sessions in this graph and remove the PDU
// session as well
/*
for (auto s : sessions) {
pfcp::node_id_t n = s.second->get_upf_node_id();
if (n == node_id) {
......@@ -582,7 +587,7 @@ void smf_app::handle_itti_msg(std::shared_ptr<itti_n4_node_failure> snf) {
supi64, it.first);
// TODO: remove the session
}
}
} */
}
}
......@@ -669,7 +674,28 @@ void smf_app::handle_itti_msg(
return;
}
sp.get()->get_upf_node_id(up_node_id);
// TODO when is this triggered and what should we do in that case?
std::shared_ptr<upf_graph> graph = sp->get_sessions_graph();
if (!graph) {
Logger::smf_app().warn("PDU sessions graph does not exist!");
return;
}
std::vector<edge> dl_edges;
std::vector<edge> ul_edges;
std::shared_ptr<pfcp_association> current_upf;
smf_qos_flow empty_flow;
// TODO what is exactly happening here or should happen?
// and why is this not in the procedure?
graph->start_asynch_dfs_procedure(true, empty_flow);
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;
std::shared_ptr<itti_n4_session_failure_indication>
itti_n4_failure_indication =
......
......@@ -642,15 +642,15 @@ void smf_pdu_session::add_qos_rule(const QOSRulesIE& qos_rule) {
}
}
void smf_pdu_session::set_upf_node_id(const pfcp::node_id_t& node_id) {
upf_node_id = node_id;
std::shared_ptr<upf_graph> smf_pdu_session::get_sessions_graph() const {
return sessions_graph;
}
void smf_pdu_session::get_upf_node_id(pfcp::node_id_t& node_id) const {
node_id = upf_node_id;
}
pfcp::node_id_t smf_pdu_session::get_upf_node_id() const {
return upf_node_id;
void smf_pdu_session::set_sessions_graph(
const std::shared_ptr<upf_graph> upf_graph) {
sessions_graph = upf_graph;
}
//-----------------------------------------------------------------------------
void smf_pdu_session::set_urr_id(const uint32_t& urrId) {
urr_Id = urrId;
......
......@@ -47,6 +47,7 @@
#include "smf_procedure.hpp"
#include "uint_generator.hpp"
#include "smf_n7.hpp"
#include "smf_pfcp_association.hpp"
extern "C" {
#include "Ngap_PDUSessionAggregateMaximumBitRate.h"
......@@ -54,64 +55,13 @@ extern "C" {
#include "QOSFlowDescriptions.h"
#include "QOSRules.h"
#include "nas_message.h"
#include "smf_pfcp_association.hpp"
}
using namespace boost::placeholders;
namespace smf {
class smf_qos_flow {
public:
smf_qos_flow() { clear(); }
void clear() {
ul_fteid = {};
dl_fteid = {};
pdr_id_ul = {};
pdr_id_dl = {};
precedence = {};
far_id_ul = {};
far_id_dl = {};
released = false;
qos_profile = {};
cause_value = 0;
}
/*
* Release resources associated with this flow
* @param void
* @return void
*/
void deallocate_ressources();
/*
* Mark this flow as released
* @param void
* @return void
*/
void mark_as_released();
/*
* Represent flow as string to be printed
* @param void
* @return void
*/
std::string toString() 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::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;
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;
qos_profile_t qos_profile; // QoS profile
uint8_t cause_value; // cause
};
class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
public:
smf_pdu_session() : m_pdu_session_mutex() { clear(); }
......@@ -493,26 +443,9 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
*/
void set_nwi_core(const std::string& nwiCore);
/*
* Set UPF Node ID of this PDU Session
* @param [const pfcp::node_id_t&] node_id: UPF Node Id
* @return void
*/
void set_upf_node_id(const pfcp::node_id_t& node_id);
/*
* Get UPF Node ID of this PDU Session
* @param [pfcp::node_id_t&] node_id: UPF Node Id
* @return void
*/
void get_upf_node_id(pfcp::node_id_t& node_id) const;
void set_sessions_graph(const std::shared_ptr<upf_graph> upf_graph);
/*
* Get UPF Node ID of this PDU Session
* @param void
* @return UPF Node Id
*/
pfcp::node_id_t get_upf_node_id() const;
std::shared_ptr<upf_graph> get_sessions_graph() const;
/*
* Get DNN associated with this PDU Session
......@@ -573,7 +506,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
std::string nwi_access; // associated nwi_access
std::string nwi_core; // associated nwi_core
pfcp::node_id_t upf_node_id;
std::shared_ptr<upf_graph> sessions_graph;
pdu_session_status_e pdu_session_status;
upCnx_state_e
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -538,6 +538,16 @@ void upf_profile::display() const {
s.snssai.sd);
for (auto d : s.dnn_upf_info_list) {
Logger::smf_app().debug("\t\t\tDNN %s", d.dnn.c_str());
for (auto dnai : d.dnai_list) {
Logger::smf_app().debug("\t\t\t\tDNAI List: %s", dnai.c_str());
}
for (auto nwinstance : d.dnai_nw_instance_list) {
Logger::smf_app().debug(
"\t\t\t\tDNAI NW Instance List: %s : "
"%s",
nwinstance.first.c_str(), nwinstance.second.c_str());
}
}
}
if (!upf_info.interface_upf_info_list.empty()) {
......@@ -575,8 +585,10 @@ void upf_profile::to_json(nlohmann::json& data) const {
tmp["sNssai"]["sd"] = std::to_string(s.snssai.sd);
tmp["dnnSmfInfoList"] = nlohmann::json::array();
for (auto d : s.dnn_upf_info_list) {
nlohmann::json dnn_json = {};
dnn_json["dnn"] = d.dnn;
nlohmann::json dnn_json = {};
dnn_json["dnn"] = d.dnn;
dnn_json["dnaiList"] = d.dnai_list;
dnn_json["dnaiNwInstanceList"] = d.dnai_nw_instance_list;
tmp["dnnSmfInfoList"].push_back(dnn_json);
}
data["upfInfo"]["sNssaiUpfInfoList"].push_back(tmp);
......@@ -637,8 +649,17 @@ void upf_profile::from_json(const nlohmann::json& data) {
for (auto d : it["dnnUpfInfoList"]) {
if (d.find("dnn") != d.end()) {
dnn_item.dnn = d["dnn"].get<std::string>();
upf_info_item.dnn_upf_info_list.push_back(dnn_item);
}
if (d.find("dnaiList") != d.end()) {
dnn_item.dnai_list =
d["dnaiList"].get<std::unordered_set<std::string>>();
}
if (d.find("dnaiNwInstanceList") != d.end()) {
dnn_item.dnai_nw_instance_list =
d["dnaiNwInstanceList"]
.get<std::map<std::string, std::string>>();
}
upf_info_item.dnn_upf_info_list.insert(dnn_item);
}
}
upf_info.snssai_upf_info_list.push_back(upf_info_item);
......
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