Commit d978e85e authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

support multiple UPFs (discovered with NRF)

parent 6f0d879d
......@@ -397,6 +397,45 @@ 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, const upf_profile& profile) {
std::time_t time_epoch = std::time(nullptr);
uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
pfcp_associations::get_instance().add_peer_candidate_node(node_id);
std::shared_ptr<itti_n4_association_setup_request> n4_asc =
std::shared_ptr<itti_n4_association_setup_request>(
new itti_n4_association_setup_request(TASK_SMF_APP, TASK_SMF_N4));
// n4_asc->trxn_id = smf_n4_inst->generate_trxn_id();
pfcp::cp_function_features_s cp_function_features;
cp_function_features = {};
cp_function_features.load = 1;
cp_function_features.ovrl = 1;
pfcp::node_id_t this_node_id = {};
if (smf_cfg.get_pfcp_node_id(this_node_id) == RETURNok) {
n4_asc->pfcp_ies.set(this_node_id);
pfcp::recovery_time_stamp_t r = {.recovery_time_stamp = (uint32_t) tv_ntp};
n4_asc->pfcp_ies.set(r);
n4_asc->pfcp_ies.set(cp_function_features);
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
n4_asc->r_endpoint =
endpoint(node_id.u1.ipv4_address, pfcp::default_port);
int ret = itti_inst->send_msg(n4_asc);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_N4",
n4_asc.get()->get_msg_name());
}
} else {
Logger::smf_app().warn("Start_association() node_id IPV6, FQDN!");
}
}
}
//------------------------------------------------------------------------------
void smf_app::handle_itti_msg(itti_n4_session_establishment_response& seresp) {
std::shared_ptr<smf_context> pc = {};
......@@ -1241,7 +1280,11 @@ bool smf_app::handle_nf_status_notification(
n.u1.ipv4_address.s_addr = ipv4_addrs[0].s_addr;
// memcpy(&n.u1.ipv4_address, &ipv4_addrs[0], sizeof(struct in_addr));
smf_cfg.upfs.push_back(n);
start_upf_association(n);
upf_profile* upf_node_profile =
dynamic_cast<upf_profile*>(profile.get());
start_upf_association(n, std::ref(*upf_node_profile));
// start_upf_association(n,
// std::static_pointer_cast<upf_profile>(profile));
} else {
Logger::smf_app().debug(
"UPF node already exist (%s)", inet_ntoa(ipv4_addrs[0]));
......
......@@ -654,6 +654,14 @@ class smf_app {
*/
void start_upf_association(const pfcp::node_id_t& node_id);
/*
* To start an association with a UPF (SMF-initiated association)
* @param [const pfcp::node_id_t] node_id: UPF Node ID
* @return void
*/
void start_upf_association(
const pfcp::node_id_t& node_id, const upf_profile& profile);
/*
* To store a promise of a PDU Session Create SM Contex Response to be
* triggered when the result is ready
......
......@@ -97,6 +97,18 @@ bool pfcp_associations::add_association(
sa = std::shared_ptr<pfcp_association>(association);
sa->recovery_time_stamp = recovery_time_stamp;
std::size_t hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
// Associate with UPF profile if exist
for (std::vector<std::shared_ptr<pfcp_association>>::iterator it =
pending_associations.begin();
it < pending_associations.end(); ++it) {
if ((*it)->node_id == node_id) {
Logger::smf_app().info("Associate with UPF profile");
sa->set_upf_node_profile((*it)->get_upf_node_profile());
break;
}
}
associations.insert((int32_t) hash_node_id, sa);
trigger_heartbeat_request_procedure(sa);
}
......@@ -282,6 +294,41 @@ bool pfcp_associations::select_up_node(
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::select_up_node(
pfcp::node_id_t& node_id, const snssai_t& snssai, const std::string& dnn) {
node_id = {};
if (associations.empty()) {
return false;
}
folly::AtomicHashMap<int32_t, std::shared_ptr<pfcp_association>>::iterator it;
FOR_EACH(it, associations) {
std::shared_ptr<pfcp_association> a = it->second;
// get the first node id if there's no upf profile (get UPFs from conf file)
if (!a->upf_profile_is_set) {
node_id = it->second->node_id;
return true;
}
// else, verify that UPF belongs to the same slice and supports this dnn
std::vector<snssai_t> snssais = {};
// a->upf_node_profile.get_nf_snssais(snssais);
upf_info_t upf_info = {};
a->upf_node_profile.get_upf_info(upf_info);
for (auto ui : upf_info.snssai_upf_info_list) {
if (ui.snssai == snssai) {
for (auto d : ui.dnn_upf_info_list) {
if (d.dnn.compare(dnn) == 0) {
node_id = it->second->node_id;
return true;
}
}
}
}
}
return false;
}
//------------------------------------------------------------------------------
void pfcp_associations::notify_add_session(
const pfcp::node_id_t& node_id, const pfcp::fseid_t& cp_fseid) {
......@@ -317,3 +364,24 @@ bool pfcp_associations::add_peer_candidate_node(
pending_associations.push_back(s);
return true;
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_peer_candidate_node(
const pfcp::node_id_t& node_id, const upf_profile& profile) {
for (std::vector<std::shared_ptr<pfcp_association>>::iterator it =
pending_associations.begin();
it < pending_associations.end(); ++it) {
if ((*it)->node_id == node_id) {
// TODO purge sessions of this node
Logger::smf_app().info("TODO purge sessions of this node");
pending_associations.erase(it);
break;
}
}
pfcp_association* association = new pfcp_association(node_id);
std::shared_ptr<pfcp_association> s =
std::shared_ptr<pfcp_association>(association);
s->set_upf_node_profile(profile);
pending_associations.push_back(s);
return true;
}
......@@ -35,6 +35,7 @@
#include "3gpp_29.244.h"
#include "itti.hpp"
#include "smf_profile.hpp"
namespace smf {
......@@ -61,12 +62,17 @@ class pfcp_association {
timer_id_t timer_association;
timer_id_t timer_graceful_release;
upf_profile upf_node_profile;
bool upf_profile_is_set;
explicit pfcp_association(const pfcp::node_id_t& node_id)
: node_id(node_id),
recovery_time_stamp(),
function_features(),
m_sessions(),
sessions() {
sessions(),
upf_node_profile(),
upf_profile_is_set(false) {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
......@@ -82,7 +88,9 @@ class pfcp_association {
recovery_time_stamp(recovery_time_stamp),
function_features(),
m_sessions(),
sessions() {
sessions(),
upf_node_profile(),
upf_profile_is_set(false) {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
......@@ -94,7 +102,12 @@ class pfcp_association {
pfcp_association(
const pfcp::node_id_t& ni, pfcp::recovery_time_stamp_t& rts,
pfcp::up_function_features_s& uff)
: node_id(ni), recovery_time_stamp(rts), m_sessions(), sessions() {
: node_id(ni),
recovery_time_stamp(rts),
m_sessions(),
sessions(),
upf_node_profile(),
upf_profile_is_set(false) {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
function_features.first = true;
function_features.second = uff;
......@@ -115,7 +128,9 @@ class pfcp_association {
trxn_id_heartbeat(p.trxn_id_heartbeat),
is_restore_sessions_pending(p.is_restore_sessions_pending),
timer_association(0),
timer_graceful_release(0) {}
timer_graceful_release(0),
upf_node_profile(p.upf_node_profile),
upf_profile_is_set(p.upf_profile_is_set) {}
void notify_add_session(const pfcp::fseid_t& cp_fseid);
bool has_session(const pfcp::fseid_t& cp_fseid);
......@@ -126,6 +141,14 @@ class pfcp_association {
function_features.first = true;
function_features.second = ff;
};
void set_upf_node_profile(const upf_profile& profile) {
upf_node_profile = profile;
upf_profile_is_set = true;
};
void get_upf_node_profile(upf_profile& profile) const {
profile = upf_node_profile;
};
upf_profile get_upf_node_profile() const { return upf_node_profile; };
};
enum node_selection_criteria_e {
......@@ -189,7 +212,11 @@ class pfcp_associations {
bool select_up_node(
pfcp::node_id_t& node_id, const int node_selection_criteria);
bool select_up_node(
pfcp::node_id_t& node_id, const snssai_t& snssai, const std::string& dnn);
bool add_peer_candidate_node(const pfcp::node_id_t& node_id);
bool add_peer_candidate_node(
const pfcp::node_id_t& node_id, const upf_profile& profile);
};
} // namespace smf
......
......@@ -417,6 +417,7 @@ class smf_profile : public nf_profile {
class upf_profile : public nf_profile {
public:
upf_profile() : nf_profile() { // custom_info = {};
nf_type = "UPF";
}
upf_profile(const std::string& id) : nf_profile(id) { // custom_info = {};
......
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