Commit 0767d579 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

handle PFCP Association Update Request from UP function

parent 7729be87
......@@ -2648,20 +2648,24 @@ public:
std::pair<bool, pfcp::cause_t> cause;
std::pair<bool, pfcp::up_function_features_s> up_function_features;
std::pair<bool, pfcp::cp_function_features_t> cp_function_features;
std::pair<bool, pfcp::pfcpaureq_flags_t> pfcpaureq_flags;
std::pair<bool, pfcp::alternative_smf_ip_address_t> alternative_smf_ip_address;
pfcp_association_update_response() :
node_id(),
cause(),
up_function_features(),
cp_function_features() {}
cp_function_features(),
pfcpaureq_flags(),
alternative_smf_ip_address() {}
pfcp_association_update_response(const pfcp_association_update_response& i) {
node_id = i.node_id;
cause = i.cause;
up_function_features = i.up_function_features;
cp_function_features = i.cp_function_features;
pfcpaureq_flags = i.pfcpaureq_flags;
alternative_smf_ip_address = i.alternative_smf_ip_address;
}
const char* get_msg_name() const {return "PFCP_ASSOCIATION_UPDATE_RESPONSE";};
......@@ -2669,11 +2673,15 @@ public:
bool get(pfcp::cause_t& v) const {if (cause.first) {v = cause.second;return true;}return false;}
bool get(pfcp::up_function_features_s& v) const {if (up_function_features.first) {v = up_function_features.second;return true;}return false;}
bool get(pfcp::cp_function_features_t& v) const {if (cp_function_features.first) {v = cp_function_features.second;return true;}return false;}
bool get(pfcp::pfcpaureq_flags_t& v) const {if (pfcpaureq_flags.first) {v = pfcpaureq_flags.second;return true;}return false;}
bool get(pfcp::alternative_smf_ip_address_t& v) const {if (alternative_smf_ip_address.first) {v = alternative_smf_ip_address.second;return true;}return false;}
void set(const pfcp::node_id_t& v) {node_id.first = true; node_id.second = v;}
void set(const pfcp::cause_t& v) {cause.first = true; cause.second = v;}
void set(const pfcp::up_function_features_s& v) {up_function_features.first = true; up_function_features.second = v;}
void set(const pfcp::cp_function_features_t& v) {cp_function_features.first = true; cp_function_features.second = v;}
void set(const pfcp::pfcpaureq_flags_t& v) {pfcpaureq_flags.first = true; pfcpaureq_flags.second = v;}
void set(const pfcp::alternative_smf_ip_address_t& v) {alternative_smf_ip_address.first = true; alternative_smf_ip_address.second = v;}
};
//------------------------------------------------------------------------------
......
......@@ -176,6 +176,10 @@ void smf_n4_task(void *args_p) {
pfcp_associations::get_instance().timeout_heartbeat_request(
to->timer_id, to->arg2_user);
break;
case TASK_SMF_N4_TIMEOUT_GRACEFUL_RELEASE_PERIOD:
pfcp_associations::get_instance().timeout_release_request(
to->timer_id, to->arg2_user);
break;
default:
;
}
......@@ -211,7 +215,7 @@ smf_n4::smf_n4()
tm_epoch.tm_mon = 2 - 1; // months count from January=0
tm_epoch.tm_mday = 8; // days count from 1
std::time_t time_epoch = std::mktime(&tm_epoch);
std::chrono::time_point<std::chrono::system_clock> now =
std::chrono::time_point < std::chrono::system_clock > now =
std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::time_t ellapsed = now_c - time_epoch;
......@@ -221,7 +225,7 @@ smf_n4::smf_n4()
std::time_t time_epoch_ntp = std::time(nullptr);
uint64_t tv_ntp = time_epoch_ntp + SECONDS_SINCE_FIRST_EPOCH;
recovery_time_stamp = tv_ntp;
// TODO may load this from config
cp_function_features = { };
cp_function_features.ovrl = 0;
......@@ -268,6 +272,8 @@ void smf_n4::handle_receive_pfcp_msg(pfcp_msg &msg,
handle_receive_association_setup_response(msg, remote_endpoint);
break;
case PFCP_ASSOCIATION_UPDATE_REQUEST:
handle_receive_association_update_request(msg, remote_endpoint);
break;
case PFCP_ASSOCIATION_UPDATE_RESPONSE:
case PFCP_ASSOCIATION_RELEASE_REQUEST:
case PFCP_ASSOCIATION_RELEASE_RESPONSE:
......@@ -441,6 +447,84 @@ void smf_n4::handle_receive_association_setup_response(
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_association_update_request(
pfcp::pfcp_msg &msg, const endpoint &remote_endpoint) {
bool error = true;
uint64_t trxn_id = 0;
pfcp_association_update_request msg_ies_container = { };
msg.to_core_type(msg_ies_container);
pfcp::cause_t cause = { .cause_value = pfcp::CAUSE_VALUE_REQUEST_ACCEPTED };
uint32_t graceful_release_period = PFCP_ASSOCIATION_GRACEFUL_RELEASE_PERIOD;
pfcp::node_id_t node_id = { };
handle_receive_message_cb(msg, remote_endpoint, TASK_SMF_N4, error, trxn_id);
if (error) {
return;
}
if (not msg_ies_container.node_id.first) {
Logger::smf_n4().warn(
"Received N4 ASSOCIATION UPDATE REQUEST without node id IE!, ignore message");
cause.cause_value = pfcp::CAUSE_VALUE_MANDATORY_IE_MISSING;
}
if (smf_cfg.get_pfcp_node_id(node_id) != RETURNok) {
Logger::smf_n4().warn(
"Received N4 ASSOCIATION UPDATE REQUEST could not set node id!, ignore message");
cause.cause_value = pfcp::CAUSE_VALUE_NO_ESTABLISHED_PFCP_ASSOCIATION;
}
if (cause.cause_value == pfcp::CAUSE_VALUE_REQUEST_ACCEPTED) {
if (msg_ies_container.up_function_features.first) {
//Update features and set cause accordingly
if (pfcp_associations::get_instance().update_association(
node_id, msg_ies_container.up_function_features.second))
cause.cause_value = pfcp::CAUSE_VALUE_REQUEST_ACCEPTED;
else
cause.cause_value = pfcp::CAUSE_VALUE_REQUEST_REJECTED;
}
//If the UP function has requested to release the PFCP association
if (msg_ies_container.pfcp_association_release_request.first) {
//Graceful Release Period
if (msg_ies_container.graceful_release_period.first) {
//TODO:
//max (PFCP_ASSOCIATION_GRACEFUL_RELEASE_PERIOD, graceful_release_period)
}
//Schedule PFCP Association Release Request to release the PFCP association
std::shared_ptr<pfcp_association> sa = std::shared_ptr < pfcp_association
> (nullptr);
if (pfcp_associations::get_instance().get_association(node_id, sa)) {
sa->timer_graceful_release = itti_inst->timer_setup(
graceful_release_period, 0, TASK_SMF_N4,
TASK_SMF_N4_TIMEOUT_GRACEFUL_RELEASE_PERIOD,
sa->hash_node_id);
}
}
if (msg_ies_container.user_plane_ip_resource_information.first) {
//TODO:
}
}
// send an PFCP Association Update Response
itti_n4_association_update_response a(TASK_SMF_N4, TASK_SMF_N4);
a.trxn_id = trxn_id;
a.pfcp_ies.set(cause);
a.pfcp_ies.set(node_id);
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
a.r_endpoint = remote_endpoint;
send_n4_msg(a);
} else {
Logger::smf_n4().warn(
"Received N4 ASSOCIATION UPDATE REQUEST TODO node_id IPV6, FQDN!, ignore message");
return;
}
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_session_establishment_response(
pfcp::pfcp_msg &msg, const endpoint &remote_endpoint) {
......@@ -457,8 +541,8 @@ void smf_n4::handle_receive_session_establishment_response(
itti_msg->r_endpoint = remote_endpoint;
itti_msg->trxn_id = trxn_id;
itti_msg->seid = msg.get_seid();
std::shared_ptr<itti_n4_session_establishment_response> i = std::shared_ptr<
itti_n4_session_establishment_response>(itti_msg);
std::shared_ptr<itti_n4_session_establishment_response> i = std::shared_ptr
< itti_n4_session_establishment_response > (itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n4().error(
......@@ -485,8 +569,8 @@ void smf_n4::handle_receive_session_modification_response(
itti_msg->r_endpoint = remote_endpoint;
itti_msg->trxn_id = trxn_id;
itti_msg->seid = msg.get_seid();
std::shared_ptr<itti_n4_session_modification_response> i = std::shared_ptr<
itti_n4_session_modification_response>(itti_msg);
std::shared_ptr<itti_n4_session_modification_response> i = std::shared_ptr
< itti_n4_session_modification_response > (itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n4().error(
......@@ -513,8 +597,8 @@ void smf_n4::handle_receive_session_deletion_response(
itti_msg->r_endpoint = remote_endpoint;
itti_msg->trxn_id = trxn_id;
itti_msg->seid = msg.get_seid();
std::shared_ptr<itti_n4_session_deletion_response> i = std::shared_ptr<
itti_n4_session_deletion_response>(itti_msg);
std::shared_ptr<itti_n4_session_deletion_response> i = std::shared_ptr
< itti_n4_session_deletion_response > (itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n4().error(
......@@ -541,8 +625,8 @@ void smf_n4::handle_receive_session_report_request(
itti_msg->r_endpoint = remote_endpoint;
itti_msg->trxn_id = trxn_id;
itti_msg->seid = msg.get_seid();
std::shared_ptr<itti_n4_session_report_request> i = std::shared_ptr<
itti_n4_session_report_request>(itti_msg);
std::shared_ptr<itti_n4_session_report_request> i = std::shared_ptr
< itti_n4_session_report_request > (itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n4().error(
......@@ -569,8 +653,7 @@ void smf_n4::send_heartbeat_request(std::shared_ptr<pfcp_association> &a) {
uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
pfcp::pfcp_heartbeat_request h = { };
pfcp::recovery_time_stamp_t r = { .recovery_time_stamp =
(uint32_t) tv_ntp };
pfcp::recovery_time_stamp_t r = { .recovery_time_stamp = (uint32_t) tv_ntp };
h.set(r);
pfcp::node_id_t &node_id = a->node_id;
......@@ -647,3 +730,19 @@ void smf_n4::send_association_setup_request(
send_request(i.r_endpoint, i.pfcp_ies, TASK_SMF_N4, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_release_request(std::shared_ptr<pfcp_association> &a) {
Logger::smf_n4().debug("Send N4 ASSOCIATION RELEASE REQUEST");
pfcp::pfcp_association_release_request release_request = { };
pfcp::node_id_t &node_id = a->node_id;
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
endpoint r_endpoint = endpoint(node_id.u1.ipv4_address, pfcp::default_port);
uint64_t trxn_id = generate_trxn_id();
release_request.set(node_id);
send_request(r_endpoint, release_request, TASK_SMF_N4, trxn_id);
} else {
Logger::smf_n4().warn("TODO send_release_request() node_id IPV6, FQDN!");
}
}
......@@ -37,10 +37,10 @@
namespace smf {
#define TASK_SMF_N4_TRIGGER_HEARTBEAT_REQUEST (0)
#define TASK_SMF_N4_TIMEOUT_HEARTBEAT_REQUEST (1)
#define TASK_SMF_N4_TIMEOUT_ASSOCIATION_REQUEST (2)
#define TASK_SMF_N4_TRIGGER_HEARTBEAT_REQUEST (0)
#define TASK_SMF_N4_TIMEOUT_HEARTBEAT_REQUEST (1)
#define TASK_SMF_N4_TIMEOUT_ASSOCIATION_REQUEST (2)
#define TASK_SMF_N4_TIMEOUT_GRACEFUL_RELEASE_PERIOD (3)
class smf_n4 : public pfcp::pfcp_l4_stack {
private:
std::thread::id thread_id;
......@@ -142,6 +142,8 @@ class smf_n4 : public pfcp::pfcp_l4_stack {
void send_heartbeat_response(const endpoint &r_endpoint,
const uint64_t trxn_id);
void send_release_request(std::shared_ptr<pfcp_association> &a);
void handle_receive_pfcp_msg(pfcp::pfcp_msg &msg, const endpoint &r_endpoint);
void handle_receive(char *recv_buffer, const std::size_t bytes_transferred,
const endpoint &r_endpoint);
......@@ -154,7 +156,8 @@ class smf_n4 : public pfcp::pfcp_l4_stack {
const endpoint &r_endpoint);
void handle_receive_association_setup_response(
pfcp::pfcp_msg &msg, const endpoint &remote_endpoint);
void handle_receive_association_update_request(
pfcp::pfcp_msg &msg, const endpoint &remote_endpoint);
void handle_receive_session_establishment_response(
pfcp::pfcp_msg &msg, const endpoint &r_endpoint);
void handle_receive_session_modification_response(pfcp::pfcp_msg &msg,
......
......@@ -136,6 +136,22 @@ bool pfcp_associations::add_association(
}
return true;
}
//------------------------------------------------------------------------------
bool pfcp_associations::update_association(
pfcp::node_id_t &node_id, pfcp::up_function_features_s &function_features) {
std::shared_ptr<pfcp_association> sa = std::shared_ptr<pfcp_association>(
nullptr);
if (get_association(node_id, sa)) {
sa->function_features.first = true;
sa->function_features.second = function_features;
} else {
return false;
}
return true;
}
//------------------------------------------------------------------------------
bool pfcp_associations::get_association(
const pfcp::node_id_t &node_id,
......@@ -193,6 +209,7 @@ void pfcp_associations::initiate_heartbeat_request(timer_id_t timer_id,
smf_n4_inst->send_heartbeat_request(pit->second);
}
}
//------------------------------------------------------------------------------
void pfcp_associations::timeout_heartbeat_request(timer_id_t timer_id,
uint64_t arg2_user) {
......@@ -215,6 +232,20 @@ void pfcp_associations::timeout_heartbeat_request(timer_id_t timer_id,
}
}
}
//------------------------------------------------------------------------------
void pfcp_associations::timeout_release_request(timer_id_t timer_id,
uint64_t arg2_user) {
size_t hash_node_id = (size_t) arg2_user;
auto pit = associations.find((int32_t) hash_node_id);
if (pit == associations.end())
return;
else {
Logger::smf_n4().info("PFCP RELEASE REQUEST hash %u", hash_node_id);
smf_n4_inst->send_release_request(pit->second);
}
}
//------------------------------------------------------------------------------
void pfcp_associations::handle_receive_heartbeat_response(
const uint64_t trxn_id) {
......
......@@ -40,6 +40,8 @@ namespace smf {
#define PFCP_ASSOCIATION_HEARTBEAT_INTERVAL_SEC 10
#define PFCP_ASSOCIATION_HEARTBEAT_MAX_RETRIES 2
#define PFCP_ASSOCIATION_GRACEFUL_RELEASE_PERIOD 5
class pfcp_association {
public:
pfcp::node_id_t node_id;
......@@ -57,6 +59,7 @@ class pfcp_association {
bool is_restore_sessions_pending;
timer_id_t timer_association;
timer_id_t timer_graceful_release;
explicit pfcp_association(const pfcp::node_id_t &node_id)
:
......@@ -71,6 +74,7 @@ class pfcp_association {
trxn_id_heartbeat = 0;
is_restore_sessions_pending = false;
timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID;
}
pfcp_association(const pfcp::node_id_t &node_id,
pfcp::recovery_time_stamp_t &recovery_time_stamp)
......@@ -86,6 +90,7 @@ class pfcp_association {
trxn_id_heartbeat = 0;
timer_association = ITTI_INVALID_TIMER_ID;
is_restore_sessions_pending = false;
timer_graceful_release = ITTI_INVALID_TIMER_ID;
}
pfcp_association(const pfcp::node_id_t &ni, pfcp::recovery_time_stamp_t &rts,
pfcp::up_function_features_s &uff)
......@@ -102,6 +107,7 @@ class pfcp_association {
trxn_id_heartbeat = 0;
is_restore_sessions_pending = false;
timer_association = ITTI_INVALID_TIMER_ID;
timer_graceful_release = ITTI_INVALID_TIMER_ID;
}
pfcp_association(pfcp_association const &p)
:
......@@ -113,7 +119,8 @@ class pfcp_association {
num_retries_timer_heartbeat(p.num_retries_timer_heartbeat),
trxn_id_heartbeat(p.trxn_id_heartbeat),
is_restore_sessions_pending(p.is_restore_sessions_pending),
timer_association(0) {
timer_association(0),
timer_graceful_release(0) {
}
void notify_add_session(const pfcp::fseid_t &cp_fseid);
......@@ -168,6 +175,8 @@ class pfcp_associations {
pfcp::recovery_time_stamp_t &recovery_time_stamp,
pfcp::up_function_features_s &function_features,
bool &restore_n4_sessions);
bool update_association(
pfcp::node_id_t &node_id, pfcp::up_function_features_s &function_features);
bool get_association(const pfcp::node_id_t &node_id,
std::shared_ptr<pfcp_association> &sa) const;
bool get_association(const pfcp::fseid_t &cp_fseid,
......@@ -181,6 +190,7 @@ class pfcp_associations {
void initiate_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user);
void timeout_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user);
void timeout_release_request(timer_id_t timer_id, uint64_t arg2_user);
void handle_receive_heartbeat_response(const uint64_t trxn_id);
bool select_up_node(pfcp::node_id_t &node_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