Commit 5b856fa3 authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

Trying to get all available information for the UPF to avoid hash lookup issue later on

parent 9aa51384
...@@ -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) {
......
...@@ -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,81 @@ bool fqdn::resolve( ...@@ -73,6 +74,81 @@ 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: {
if (inet_aton(util::trim(ip_addr_str).c_str(), &ipv4_addr) == 0) {
Logger::smf_app().debug("Bad IPv4 Addr format for UPF");
return false;
}
node_id.u1.ipv4_address.s_addr = ipv4_addr.s_addr;
Logger::smf_app().debug(
"Resolve FQDN %s, IP Addr %s", node_id.fqdn.c_str(),
ip_addr_str.c_str());
} break;
case 1: {
// TODO
Logger::smf_app().warn(
"Resolve FQDN: %s. IPv6 Addr, this mode has not been "
"supported yet!",
node_id.fqdn.c_str());
return false;
} break;
default:
Logger::smf_app().warn("Unknown Address type");
return false;
}
} else {
return false; // No FQDN available
}
// Resolve hostname from an IP Addr
} else if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
// Don't need to do reserve_resolve if FQDN is already available
if (!node_id.fqdn.empty()) {
return true;
} else {
std::string hostname = {};
std::string ip_str = conv::toString(node_id.u1.ipv4_address);
if (!fqdn::reverse_resolve(ip_str, hostname)) {
Logger::smf_app().warn(
"Could not resolve hostname for IP address %s", ip_str.c_str());
return false;
} else {
node_id.fqdn = hostname;
Logger::smf_app().debug(
"Resolve IP Addr %s, FQDN %s", ip_str.c_str(),
node_id.fqdn.c_str());
}
return true;
}
} else {
// Don't support IPv6 for the moment
return false;
}
return true;
}
bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) { bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) {
Logger::smf_app().debug("Resolving an IP address (name %s)", ip_addr.c_str()); Logger::smf_app().debug("Resolving an IP address (name %s)", ip_addr.c_str());
int tries = 0; int tries = 0;
...@@ -107,4 +183,4 @@ bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) { ...@@ -107,4 +183,4 @@ bool fqdn::reverse_resolve(const std::string& ip_addr, std::string& host_name) {
} }
} }
return false; return false;
} }
\ No newline at end of file
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#ifndef FILE_FQDN_HPP_SEEN #ifndef FILE_FQDN_HPP_SEEN
#define FILE_FQDN_HPP_SEEN #define FILE_FQDN_HPP_SEEN
#include <string> #include <string>
#include "3gpp_29.244.h"
class fqdn { class fqdn {
public: public:
/* /*
...@@ -41,6 +42,7 @@ class fqdn { ...@@ -41,6 +42,7 @@ class fqdn {
const std::string& host_name, std::string& address, uint32_t& port, const std::string& host_name, std::string& address, uint32_t& port,
uint8_t& addr_type, const std::string& protocol = "http"); uint8_t& addr_type, const std::string& protocol = "http");
static bool resolve(pfcp::node_id_t& node_id);
/** /**
* @brief Resolves an IP address to get the hostname * @brief Resolves an IP address to get the hostname
* @param ip_address to resolve * @param ip_address to resolve
......
...@@ -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>(
...@@ -1455,19 +1461,26 @@ bool smf_app::handle_nf_status_notification( ...@@ -1455,19 +1461,26 @@ 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);
upf_profile* upf_node_profile =
dynamic_cast<upf_profile*>(profile.get());
start_upf_association(n, std::ref(*upf_node_profile));
*/
} 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]));
} }
// Do reserve_resolve to find FQDN if not available
if (n.fqdn.empty()) {
std::string hostname = {};
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;
}
}
} }
if (n.node_id_type != pfcp::NODE_ID_TYPE_UNKNOWN) { if (n.node_id_type != pfcp::NODE_ID_TYPE_UNKNOWN) {
...@@ -1478,7 +1491,7 @@ bool smf_app::handle_nf_status_notification( ...@@ -1478,7 +1491,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);
......
...@@ -375,6 +375,16 @@ std::string pfcp_association::get_printable_name() { ...@@ -375,6 +375,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 ******************************/
/******************************************************************************/ /******************************************************************************/
...@@ -566,40 +576,57 @@ bool pfcp_associations::update_association( ...@@ -566,40 +576,57 @@ 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); // Resolve to get IP addr if necessary
// resolve_upf_hostname(node_id_tmp);
if (!fqdn::reverse_resolve(ip_str, hostname)) { hash_node_id = std::hash<pfcp::node_id_t>{}(node_id_tmp);
Logger::smf_app().warn( association = associations_graph.get_association(hash_node_id);
"Could not resolve hostname for IP address %s", ip_str.c_str()); if (association) {
return false; 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.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_tmp.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS;
// node_id_type IP ADDR } else if (node_id_tmp.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
// ToDo (Might stuck in recursive loop here) /*
return false; // Don't need to do reserve_resolve if FQDN is already available
} else { if (node_id_tmp.fqdn.empty()) {
std::string hostname = {};
std::string ip_str = conv::toString(node_id_tmp.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 {
node_id_tmp.fqdn = hostname;
}
}*/
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;
}
node_id_tmp.node_id_type = pfcp::NODE_ID_TYPE_FQDN;
}
// We didn't found association, may be because hash map is made with different
// node type
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id_tmp);
association = associations_graph.get_association(hash_node_id);
if (association) {
sa = association; sa = association;
return true; return true;
} }
return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -781,6 +808,8 @@ bool pfcp_associations::add_peer_candidate_node( ...@@ -781,6 +808,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;
} }
......
...@@ -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);
...@@ -615,8 +630,7 @@ class pfcp_associations { ...@@ -615,8 +630,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;
......
...@@ -67,13 +67,19 @@ class smf_procedure { ...@@ -67,13 +67,19 @@ class smf_procedure {
virtual itti_msg_type_t get_procedure_type() { return ITTI_MSG_TYPE_NONE; } virtual itti_msg_type_t get_procedure_type() { return ITTI_MSG_TYPE_NONE; }
virtual smf_procedure_code handle_itti_msg( virtual smf_procedure_code handle_itti_msg(
itti_n4_session_establishment_response& resp, itti_n4_session_establishment_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg( virtual smf_procedure_code handle_itti_msg(
itti_n4_session_modification_response& resp, itti_n4_session_modification_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
virtual smf_procedure_code handle_itti_msg( virtual smf_procedure_code handle_itti_msg(
itti_n4_session_deletion_response& resp, itti_n4_session_deletion_response& resp,
std::shared_ptr<smf::smf_context> pc) {} std::shared_ptr<smf::smf_context> pc) {
return smf_procedure_code::OK;
}
}; };
class smf_qos_flow; class smf_qos_flow;
......
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