Commit 8c76eaf5 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge branch 'status_change_notification' into 'develop'

Status change notification

See merge request oai/cn5g/oai-cn5g-nrf!32
parents 722fe5e7 a344c67d
......@@ -72,7 +72,7 @@ bool api_conv::profile_api_to_nrf_profile(
"\tStatus: %s", profile.get()->get_nf_status().c_str());
profile.get()->set_nf_heartBeat_timer(api_profile.getHeartBeatTimer());
Logger::nrf_app().debug(
"\tHeartBeart timer: %d", profile.get()->get_nf_heartBeat_timer());
"\tHeartbeat timer: %d", profile.get()->get_nf_heartBeat_timer());
profile.get()->set_nf_priority(api_profile.getPriority());
Logger::nrf_app().debug("\tPriority: %d", profile.get()->get_nf_priority());
profile.get()->set_nf_capacity(api_profile.getCapacity());
......
......@@ -171,7 +171,7 @@ void nrf_app::handle_register_nf_instance(
Logger::nrf_app().info(
"Added/Updated NF Profile (ID %s) to the DB", nf_instance_id.c_str());
// Heartbeart management for this NF profile
// Heartbeat management for this NF profile
// get current time
uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
......@@ -216,7 +216,8 @@ void nrf_app::handle_update_nf_instance(
std::shared_ptr<nrf_profile> sn = {};
sn = find_nf_profile(nf_instance_id);
bool op_success = true;
bool is_heartbeart_procedure = false;
bool is_heartbeat_procedure = false;
std::string heartbeat_value = {};
if (sn.get() != nullptr) {
for (auto p : patchItem) {
......@@ -237,7 +238,8 @@ void nrf_app::handle_update_nf_instance(
switch (op) {
case PATCH_OP_REPLACE: {
if (path.compare("nfStatus") == 0) {
is_heartbeart_procedure = true;
is_heartbeat_procedure = true;
heartbeat_value = p.getValue();
Logger::nrf_app().info("NF Heart-Beat procedure!");
}
if (sn.get()->replace_profile_info(path, p.getValue())) {
......@@ -277,7 +279,7 @@ void nrf_app::handle_update_nf_instance(
problem_details.setCause(
protocol_application_error_e2str[MANDATORY_IE_INCORRECT]);
} else {
if (!is_heartbeart_procedure)
if (!is_heartbeat_procedure)
// update successful,
// Notify NF status change event
m_event_sub.nf_status_profile_changed(
......@@ -286,7 +288,7 @@ void nrf_app::handle_update_nf_instance(
}
// for NF Heartbeat procedure
if (is_heartbeart_procedure and (http_code == HTTP_STATUS_CODE_200_OK)) {
if (is_heartbeat_procedure and (http_code == HTTP_STATUS_CODE_200_OK)) {
http_code = HTTP_STATUS_CODE_204_NO_CONTENT;
uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
......@@ -307,11 +309,17 @@ void nrf_app::handle_update_nf_instance(
sn.get()->subscribe_heartbeat_timeout_nfupdate(ms);
}
// sn.get()->subscribe_heartbeat_timeout_nfupdate(ms);
// update NF updated flag
sn.get()->set_status_updated(true);
// Subscribe again to heartbeat timeout if not done (e.g., change status
// from SUSPENDED to REGISTERED)
if (!sn.get()->is_heartbeat_timeout_nfupdate_active()) {
sn.get()->subscribe_heartbeat_timeout_nfupdate(ms);
}
// update NF status
sn.get()->set_nf_status("REGISTERED");
if (sn.get()->set_nf_status(heartbeat_value)) {
// update NF updated flag
sn.get()->set_status_updated(true);
}
return;
}
......@@ -849,7 +857,8 @@ void nrf_app::find_nf_profiles(
nf_type_t nf_type = api_conv::string_to_nf_type(sub_condition.nf_type);
for (auto profile : instance_id2nrf_profile) {
if (profile.second.get()->get_nf_type() == nf_type) {
if ((profile.second.get()->get_nf_type() == nf_type) and
profile.second->is_nf_active()) {
profiles.push_back(profile.second);
}
}
......@@ -990,13 +999,13 @@ void nrf_app::subscribe_task_tick(uint64_t ms) {
Logger::nrf_app().debug("subscribe task_tick: %d", ms);
m_event_sub.subscribe_task_tick(
boost::bind(&nrf_app::handle_heartbeart_timeout, this, _1), interval,
boost::bind(&nrf_app::handle_heartbeat_timeout, this, _1), interval,
ms % 20000);
}
//------------------------------------------------------------------------------
void nrf_app::handle_heartbeart_timeout(uint64_t ms) {
Logger::nrf_app().info("handle_heartbeart_timeout %d", ms);
void nrf_app::handle_heartbeat_timeout(uint64_t ms) {
Logger::nrf_app().info("handle_heartbeat_timeout %d", ms);
}
//------------------------------------------------------------------------------
......
......@@ -325,7 +325,7 @@ class nrf_app {
* @param [uint64_t] ms: current time in milliseconds
* @return void
*/
void handle_heartbeart_timeout(uint64_t ms);
void handle_heartbeat_timeout(uint64_t ms);
/*
* Verify whether a subscription is authorized
......
......@@ -269,6 +269,8 @@ void nrf_client::notify_subscribed_event(
json_data["nfProfile"] = json_profile;
}
// TODO: profileChanges in case of "NF_PROFILE_CHANGED" instead of NF Profile
std::string body = json_data.dump();
for (auto uri : uris) {
......
......@@ -30,6 +30,7 @@
#include "nrf_profile.hpp"
#include <unistd.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
......@@ -82,22 +83,39 @@ nf_type_t nrf_profile::get_nf_type() const {
}
//------------------------------------------------------------------------------
void nrf_profile::set_nf_status(const std::string& status) {
bool nrf_profile::set_nf_status(const std::string& status) {
Logger::nrf_app().debug("Set NF status to %s", status.c_str());
std::unique_lock lock(heartbeart_mutex);
if (!(boost::iequals(status, "REGISTERED") or
boost::iequals(status, "UNDISCOVERABLE") or
boost::iequals(status, "SUSPENDED"))) {
return false;
}
std::unique_lock lock(nf_profile_mutex);
nf_status = status;
return true;
}
//------------------------------------------------------------------------------
void nrf_profile::get_nf_status(std::string& status) const {
std::shared_lock lock(nf_profile_mutex);
status = nf_status;
}
//------------------------------------------------------------------------------
std::string nrf_profile::get_nf_status() const {
std::shared_lock lock(nf_profile_mutex);
return nf_status;
}
//------------------------------------------------------------------------------
bool nrf_profile::is_nf_active() const {
std::shared_lock lock(nf_profile_mutex);
if (boost::iequals(nf_status, "REGISTERED")) {
return true;
}
return false;
}
//------------------------------------------------------------------------------
void nrf_profile::set_nf_heartBeat_timer(const int32_t& timer) {
heartBeat_timer = timer;
......@@ -650,12 +668,12 @@ void nrf_profile::subscribe_heartbeat_timeout_nfregistration(uint64_t ms) {
its.it_value.tv_nsec / 1000000; // convert sec, nsec to msec
Logger::nrf_app().debug(
"Subscribe to the HeartBeartTimer expire event (after NF "
"Subscribe to the HeartbeatTimer expire event (after NF "
"registration): interval %d, current time %ld",
2 * HEART_BEAT_TIMER, ms);
first_hb_connection = m_event_sub.subscribe_task_tick(
boost::bind(
&nrf_profile::handle_heartbeart_timeout_nfregistration, this, _1),
&nrf_profile::handle_heartbeat_timeout_nfregistration, this, _1),
interval, ms + interval);
}
......@@ -676,8 +694,8 @@ void nrf_profile::subscribe_heartbeat_timeout_nfupdate(uint64_t ms) {
if (first_update) {
ms = ms + 2000; // Not a realtime NF: adding 2000ms interval between the
// expected NF update message and HBT
task_connection = m_event_sub.subscribe_task_tick(
boost::bind(&nrf_profile::handle_heartbeart_timeout_nfupdate, this, _1),
hb_update_connection = m_event_sub.subscribe_task_tick(
boost::bind(&nrf_profile::handle_heartbeat_timeout_nfupdate, this, _1),
interval, ms + interval);
first_update = false;
}
......@@ -685,8 +703,9 @@ void nrf_profile::subscribe_heartbeat_timeout_nfupdate(uint64_t ms) {
//------------------------------------------------------------------------------
bool nrf_profile::unsubscribe_heartbeat_timeout_nfupdate() {
if (task_connection.connected()) {
task_connection.disconnect();
std::unique_lock lock(hb_mutex);
if (hb_update_connection.connected()) {
hb_update_connection.disconnect();
Logger::nrf_app().debug(
"Unsubscribe to the Heartbeat Timer timeout event (after NF Update)");
return true;
......@@ -695,8 +714,19 @@ bool nrf_profile::unsubscribe_heartbeat_timeout_nfupdate() {
}
}
//------------------------------------------------------------------------------
bool nrf_profile::is_heartbeat_timeout_nfupdate_active() {
std::shared_lock lock(hb_mutex);
if (hb_update_connection.connected()) {
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
bool nrf_profile::unsubscribe_heartbeat_timeout_nfregistration() {
std::unique_lock lock(hb_mutex);
if (first_hb_connection.connected()) {
first_hb_connection.disconnect();
Logger::nrf_app().debug(
......@@ -709,21 +739,21 @@ bool nrf_profile::unsubscribe_heartbeat_timeout_nfregistration() {
}
//------------------------------------------------------------------------------
void nrf_profile::handle_heartbeart_timeout(uint64_t ms) {
void nrf_profile::handle_heartbeat_timeout(uint64_t ms) {
Logger::nrf_app().info(
"\nHandle heartbeart timeout, NF instance ID %s, time %d",
"\nHandle heartbeat timeout, NF instance ID %s, time %d",
nf_instance_id.c_str(), ms);
set_nf_status("SUSPENDED");
}
//------------------------------------------------------------------------------
void nrf_profile::handle_heartbeart_timeout_nfregistration(uint64_t ms) {
void nrf_profile::handle_heartbeat_timeout_nfregistration(uint64_t ms) {
Logger::nrf_app().info(
"\nHandle the first Heartbeat timeout, NF instance ID %s, current time "
"%d",
nf_instance_id.c_str(), ms);
// Set status to SUSPENDED and unsubscribe to the HBT
if (!is_updated) {
if (!get_status_updated()) {
set_nf_status("SUSPENDED");
}
......@@ -732,27 +762,43 @@ void nrf_profile::handle_heartbeart_timeout_nfregistration(uint64_t ms) {
}
//------------------------------------------------------------------------------
void nrf_profile::handle_heartbeart_timeout_nfupdate(uint64_t ms) {
void nrf_profile::handle_heartbeat_timeout_nfupdate(uint64_t ms) {
uint64_t current_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
Logger::nrf_app().info(
"\nHandle heartbeart timeout (NF update), NF instance ID %s, time %ld, "
"\nHandle heartbeat timeout (NF update), NF instance ID %s, time %ld, "
"current "
"ms %ld",
nf_instance_id.c_str(), ms, current_ms);
if (!is_updated) {
if (!get_status_updated()) {
set_nf_status("SUSPENDED");
// TODO: Notify to the subscribers
// notifCondition with ["monitoredAttributes": [ "/nfStatus""]
m_event_sub.nf_status_profile_changed(nf_instance_id);
unsubscribe_heartbeat_timeout_nfupdate();
}
set_status_updated(false);
}
//------------------------------------------------------------------------------
void nrf_profile::set_status_updated(bool status) {
std::unique_lock lock(heartbeart_mutex);
std::unique_lock lock(nf_profile_mutex);
is_updated = status;
}
//------------------------------------------------------------------------------
void nrf_profile::get_status_updated(bool& status) {
std::shared_lock lock(nf_profile_mutex);
status = is_updated;
}
//------------------------------------------------------------------------------
bool nrf_profile::get_status_updated() {
std::shared_lock lock(nf_profile_mutex);
return is_updated;
}
//------------------------------------------------------------------------------
void amf_profile::add_amf_info(const amf_info_t& info) {
amf_info = info;
......
......@@ -64,7 +64,8 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
priority(0),
capacity(0),
nf_services(),
heartbeart_mutex() {
hb_mutex(),
nf_profile_mutex() {
nf_instance_name = "";
nf_status = "";
json_data = {};
......@@ -84,7 +85,8 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
priority(0),
capacity(0),
nf_services(),
heartbeart_mutex() {
hb_mutex(),
nf_profile_mutex() {
nf_instance_name = "";
nf_status = "";
json_data = {};
......@@ -105,7 +107,8 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
capacity(0),
nf_services(),
nf_type(NF_TYPE_UNKNOWN),
heartbeart_mutex() {
hb_mutex(),
nf_profile_mutex() {
nf_instance_name = "";
nf_status = "";
json_data = {};
......@@ -117,7 +120,7 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
virtual ~nrf_profile() {
Logger::nrf_app().debug("Delete NRF Profile instance...");
if (task_connection.connected()) task_connection.disconnect();
if (hb_update_connection.connected()) hb_update_connection.disconnect();
if (first_hb_connection.connected()) first_hb_connection.disconnect();
}
......@@ -168,7 +171,7 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
* @param [const std::string &] status: instance status
* @return void
*/
void set_nf_status(const std::string& status);
bool set_nf_status(const std::string& status);
/*
* Get NF instance status
......@@ -184,6 +187,13 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
*/
std::string get_nf_status() const;
/*
* Verify NF status
* @param
* @return true if NF status is REGISTERED, otherwise return false
*/
bool is_nf_active() const;
/*
* Get NF type
* @param
......@@ -456,25 +466,25 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
void subscribe_heartbeat_timeout_nfregistration(uint64_t ms);
/*
* Handle heartbeart timeout event
* Handle heartbeat timeout event
* @param [uint64_t] ms: current time
* @return void
*/
void handle_heartbeart_timeout(uint64_t ms);
void handle_heartbeat_timeout(uint64_t ms);
/*
* Handle heartbeart timeout event after NF Registration
* Handle heartbeat timeout event after NF Registration
* @param [uint64_t] ms: current time
* @return void
*/
void handle_heartbeart_timeout_nfregistration(uint64_t ms);
void handle_heartbeat_timeout_nfregistration(uint64_t ms);
/*
* Handle heartbeart timeout event after NF Update
* Handle heartbeat timeout event after NF Update
* @param [uint64_t] ms: current time
* @return void
*/
void handle_heartbeart_timeout_nfupdate(uint64_t ms);
void handle_heartbeat_timeout_nfupdate(uint64_t ms);
/*
* Unubscribe to HBT event (after NF Registration)
......@@ -490,6 +500,13 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
*/
bool unsubscribe_heartbeat_timeout_nfupdate();
/*
* Verify whether HBT is currently active
* @param void
* @return true if active, otherwise return false
*/
bool is_heartbeat_timeout_nfupdate_active();
/*
* Set status updated to true
* @param void
......@@ -497,15 +514,30 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
*/
void set_status_updated(bool status);
/*
* Get status updated
* @param void
* @return status
*/
bool get_status_updated();
/*
* Get status updated
* @param status
* @return void
*/
void get_status_updated(bool& status);
protected:
nrf_event& m_event_sub;
bs2::connection
task_connection; // connection for the HBT timeout (after NF Update)
hb_update_connection; // connection for the HBT timeout (after NF Update)
bs2::connection first_hb_connection; // connection for first HBT timeout
// (after NF Registration)
mutable std::shared_mutex hb_mutex;
bool first_update;
bool is_updated;
mutable std::shared_mutex heartbeart_mutex;
mutable std::shared_mutex nf_profile_mutex;
// From NFProfile (Section 6.1.6.2.2@3GPP TS 29.510 V16.0.0 (2019-06))
std::string nf_instance_id;
......
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