Commit 339f4777 authored by gauthier's avatar gauthier

spgwu part1

parent 41560bed
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_app.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "conversions.hpp"
#include "itti.hpp"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_app.hpp"
#include "spgwu_config.hpp"
#include "spgwu_s1u.hpp"
#include "spgwu_sx.hpp"
#include <stdexcept>
using namespace oai::cn::proto::pfcp;
using namespace oai::cn::core::itti;
using namespace oai::cn::nf::spgwu;
using namespace std;
// C includes
spgwu_sx *spgwu_sx_inst = nullptr;
spgwu_s1u *spgwu_s1u_inst = nullptr;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_app *spgwu_app_inst;
extern spgwu_config spgwu_cfg;
void spgwu_app_task (void*);
//------------------------------------------------------------------------------
void spgwu_app_task (void *args_p)
{
const task_id_t task_id = TASK_SPGWU_APP;
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case SXAB_SESSION_ESTABLISHMENT_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_establishment_request>(shared_msg));
break;
case SXAB_SESSION_MODIFICATION_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_modification_request>(shared_msg));
break;
case SXAB_SESSION_DELETION_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_deletion_request>(shared_msg));
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) {
case TASK_SPGWU_PFCP_SWITCH_MIN_COMMIT_INTERVAL:
pfcp_switch_inst->time_out_min_commit_interval(to->timer_id);
break;
case TASK_SPGWU_PFCP_SWITCH_MAX_COMMIT_INTERVAL:
pfcp_switch_inst->time_out_max_commit_interval(to->timer_id);
break;
default:
;
}
}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::spgwu_app().info( "Received terminate message");
return;
}
break;
default:
Logger::spgwu_app().info( "no handler for ITTI msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
spgwu_app::spgwu_app (const std::string& config_file)
{
Logger::spgwu_app().startup("Starting...");
spgwu_cfg.load(config_file);
spgwu_cfg.execute();
spgwu_cfg.display();
// teid_s11_cp = 0;
// teid_s5s8_cp = 0;
// teid_s5s8_up = 0;
// imsi2sgwu_eps_bearer_context = {};
// s11lteid2sgwu_eps_bearer_context = {};
// s5s8lteid2sgwu_contexts = {};
// s5s8uplteid = {};
if (itti_inst->create_task(TASK_SPGWU_APP, spgwu_app_task, nullptr) ) {
Logger::spgwu_app().error( "Cannot create task TASK_SPGWU_APP" );
throw std::runtime_error( "Cannot create task TASK_SPGWU_APP" );
}
try {
spgwu_sx_inst = new spgwu_sx();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create SPGWU_SX: %s", e.what() );
throw e;
}
try {
spgwu_s1u_inst = new spgwu_s1u();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create SPGWU_S1U: %s", e.what() );
throw e;
}
try {
pfcp_switch_inst = new pfcp_switch();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create PFCP_SWITCH: %s", e.what() );
throw e;
}
Logger::spgwu_app().startup( "Started" );
}
//------------------------------------------------------------------------------
spgwu_app::~spgwu_app()
{
if (spgwu_sx_inst) delete spgwu_sx_inst;
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_establishment_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_ESTABLISHMENT_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_establishment_response *sx_resp = new itti_sxab_session_establishment_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_establishment_request(m, sx_resp);
core::pfcp::node_id_t node_id = {};
spgwu_cfg.get_pfcp_node_id(node_id);
sx_resp->pfcp_ies.set(node_id);
sx_resp->trxn_id = m->trxn_id;
sx_resp->seid = m->pfcp_ies.cp_fseid.second.seid; // Mandatory IE, but... may be bad to do this
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_establishment_response> msg = std::shared_ptr<itti_sxab_session_establishment_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_modification_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_MODIFICATION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_modification_response *sx_resp = new itti_sxab_session_modification_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_modification_request(m, sx_resp);
sx_resp->trxn_id = m->trxn_id;
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_modification_response> msg = std::shared_ptr<itti_sxab_session_modification_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_deletion_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_DELETION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_deletion_response *sx_resp = new itti_sxab_session_deletion_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_deletion_request(m, sx_resp);
sx_resp->trxn_id = m->trxn_id;
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_deletion_response> msg = std::shared_ptr<itti_sxab_session_deletion_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_app.hpp
\author Lionel GAUTHIER
\date 2018
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_APP_HPP_SEEN
#define FILE_SPGWU_APP_HPP_SEEN
#include "common_root_types.h"
#include "itti_msg_sxab.hpp"
#include <boost/atomic.hpp>
#include <map>
#include <string>
#include <thread>
#include <memory>
#include <map>
#include <set>
namespace oai::cn::nf::spgwu {
class spgwu_app {
private:
std::thread::id thread_id;
std::thread thread;
// teid generators (linear)
// boost::atomic<teid_t> teid_sxab_cp;
// boost::atomic<teid_t> teid_s5s8_up;
// /* There shall be only one pair of TEID-C per UE over the S11 and the S4 interfaces. The same tunnel shall be
// shared for the control messages related to the same UE operation. A TEID-C on the S11/S4 interface shall be
// released after all its associated EPS bearers are deleted.*/
// std::map<imsi64_t, std::shared_ptr<sgwu_eps_bearer_context>> imsi2sgwu_eps_bearer_context;
// std::map<teid_t, std::shared_ptr<sgwu_eps_bearer_context>> s11lteid2sgwu_eps_bearer_context;
//
// std::map<teid_t, std::pair<std::shared_ptr<sgwu_eps_bearer_context>, std::shared_ptr<sgwu_pdn_connection>>> s5s8lteid2sgwu_contexts;
// std::set<teid_t> s5s8uplteid; // In case of overflow of generator of teid_t
//
// teid_t generate_s11_cp_teid();
// bool is_s11c_teid_exist(const teid_t& teid_s11_cp) const;
//
// bool is_s5s8sgwu_teid_2_sgwu_contexts(const teid_t& sgwu_teid) const;
//
// // s11lteid2sgwu_eps_bearer_context collection
// bool is_s11sgwu_teid_2_sgwu_eps_bearer_context(const teid_t& sgwu_teid) const;
//
// bool is_imsi64_2_sgwu_eps_bearer_context(const imsi64_t& imsi64) const;
// void set_imsi64_2_sgwu_eps_bearer_context(const imsi64_t& imsi64, std::shared_ptr<sgwu_eps_bearer_context> sebc);
//
// teid_t generate_s5s8_cp_teid();
// bool is_s5s8c_teid_exist(const teid_t& teid_s5s8_cp)const;
//
// bool is_s5s8u_teid_exist(const teid_t& teid_s5s8_up) const;
public:
// key is S11 S-GW local teid, value is S11 tunnel id pair
// map<teid_t, int> s11teid2mme_hashtable;
// key is paa, value is S11 s-gw local teid
//obj_hash_table_uint64_t *ip2s11teid;
// key is S1-U S-GW local teid
////hash_table_t *s1uteid2enb_hashtable;
// the key of this hashtable is the S11 s-gw local teid.
//hash_table_ts_t *s11_bearer_context_information_hashtable;
/* The TEID-C shall be unique per PDN-Connection on GTP based S2a, S2b, S5 and S8 interfaces. The same
tunnel shall be shared for the control messages related to all bearers associated to
the PDN-Connection. A TEID-C on the S2a/S2b/S5/S8 interface shall be released after all its associated EPS bearers are deleted. */
//gtpv1u_data_t gtpv1u_data;
spgwu_app(const std::string& config_file);
~spgwu_app();
spgwu_app(spgwu_app const&) = delete;
void operator=(spgwu_app const&) = delete;
teid_t generate_s5s8_up_teid();
// void handle_itti_msg core::(itti::itti_sxab_heartbeat_request& m);
// void handle_itti_msg (core::itti::itti_sxab_heartbeat_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_pfd_management_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_pfd_management_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_setup_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_setup_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_update_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_update_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_release_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_association_release_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_version_not_supported_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_node_report_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_node_report_response& m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_establishment_request> m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_modification_request> m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_deletion_request> m);
// void handle_itti_msg (core::itti::itti_sxab_session_deletion_response& m);
// void handle_itti_msg (core::itti::itti_sxab_session_report_request& m);
// void handle_itti_msg (core::itti::itti_sxab_session_report_response& m);
};
}
#endif /* FILE_SPGWU_APP_HPP_SEEN */
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_config.hpp
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_CONFIG_HPP_SEEN
#define FILE_SPGWU_CONFIG_HPP_SEEN
#include "3gpp_29.244.h"
#include <libconfig.h++>
#include <mutex>
#include <netinet/in.h>
#include <stdint.h>
#include <stdbool.h>
#include <string>
namespace oai::cn::nf::spgwu {
#define SPGWU_CONFIG_STRING_SPGWU_CONFIG "SPGW-U"
#define SPGWU_CONFIG_STRING_PID_DIRECTORY "PID_DIRECTORY"
#define SPGWU_CONFIG_STRING_INSTANCE "INSTANCE"
#define SPGWU_CONFIG_STRING_INTERFACES "INTERFACES"
#define SPGWU_CONFIG_STRING_INTERFACE_NAME "INTERFACE_NAME"
#define SPGWU_CONFIG_STRING_IPV4_ADDRESS "IPV4_ADDRESS"
#define SPGWU_CONFIG_STRING_PORT "PORT"
#define SPGWU_CONFIG_STRING_CPU_ID_THREAD_LOOP_READ "CPU_ID_THREAD_LOOP_READ"
#define SPGWU_CONFIG_STRING_INTERFACE_SGI "SGI"
#define SPGWU_CONFIG_STRING_INTERFACE_SX "SX"
#define SPGWU_CONFIG_STRING_INTERFACE_S1U_S12_S4_UP "S1U_S12_S4_UP"
#define SPGWU_CONFIG_STRING_PDN_NETWORK_LIST "PDN_NETWORK_LIST"
#define SPGWU_CONFIG_STRING_NETWORK_IPV4 "NETWORK_IPV4"
#define SPGWU_CONFIG_STRING_NETWORK_IPV6 "NETWORK_IPV6"
#define SPGWU_CONFIG_STRING_ADDRESS_PREFIX_DELIMITER "/"
#define SPGWU_CONFIG_STRING_SNAT "SNAT"
#define SPGWU_CONFIG_STRING_MAX_PFCP_SESSIONS "MAX_PFCP_SESSIONS"
#define SPGWU_CONFIG_STRING_SPGWC_LIST "SPGW-C_LIST"
#define SPGW_ABORT_ON_ERROR true
#define SPGW_WARN_ON_ERROR false
typedef struct interface_cfg_s {
std::string if_name;
struct in_addr addr4;
struct in_addr network4;
struct in6_addr addr6;
unsigned int mtu;
unsigned int port;
int cpu_id_thread_loop_read;
} interface_cfg_t;
typedef struct pdn_cfg_s {
struct in_addr network_ipv4;
int prefix_ipv4;
struct in6_addr network_ipv6;
int prefix_ipv6;
bool snat;
} pdn_cfg_t;
class spgwu_config {
private:
int load_interface(const libconfig::Setting& if_cfg, interface_cfg_t& cfg);
public:
/* Reader/writer lock for this configuration */
std::mutex m_rw_lock;
std::string pid_dir;
unsigned int instance;
interface_cfg_t s1_up;
interface_cfg_t sgi;
interface_cfg_t sx;
std::string gateway;
uint32_t max_pfcp_sessions;
std::vector<pdn_cfg_t> pdns;
std::vector<oai::cn::core::pfcp::node_id_t> spgwcs;
spgwu_config() : m_rw_lock(), pid_dir(), instance(0), s1_up(), sgi(), gateway(),sx(), pdns(), spgwcs(), max_pfcp_sessions(100) {};
void lock() {m_rw_lock.lock();};
void unlock() {m_rw_lock.unlock();};
int load(const std::string& config_file);
int execute();
void display();
int get_pfcp_node_id(oai::cn::core::pfcp::node_id_t& node_id);
int get_pfcp_fseid(oai::cn::core::pfcp::fseid_t& fseid);
};
} // namespace spgwu
#endif /* FILE_SPGWU_CONFIG_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_pfcp_association.cpp
\brief
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#include "common_defs.h"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_pfcp_association.hpp"
#include "spgwu_sx.hpp"
using namespace oai::cn::core;
using namespace oai::cn::core::itti;
using namespace oai::cn::nf::spgwu;
using namespace std;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_sx *spgwu_sx_inst;
//------------------------------------------------------------------------------
void pfcp_association::notify_add_session(const oai::cn::core::pfcp::fseid_t& cp_fseid)
{
std::unique_lock<std::mutex> l(m_sessions);
sessions.insert(cp_fseid);
}
//------------------------------------------------------------------------------
bool pfcp_association::has_session(const oai::cn::core::pfcp::fseid_t& cp_fseid)
{
std::unique_lock<std::mutex> l(m_sessions);
auto it = sessions.find(cp_fseid);
if (it != sessions.end()) {
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
void pfcp_association::notify_del_session(const oai::cn::core::pfcp::fseid_t& cp_fseid)
{
std::unique_lock<std::mutex> l(m_sessions);
sessions.erase(cp_fseid);
}
//------------------------------------------------------------------------------
void pfcp_association::del_sessions()
{
std::unique_lock<std::mutex> l(m_sessions);
for (std::set<core::pfcp::fseid_t>::iterator it=sessions.begin(); it!=sessions.end();) {
pfcp_switch_inst->remove_pfcp_session(*it);
sessions.erase(it++);
}
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_association(oai::cn::core::pfcp::node_id_t& node_id, oai::cn::core::pfcp::recovery_time_stamp_t& recovery_time_stamp)
{
std::shared_ptr<pfcp_association> sa = {};
if (remove_peer_candidate_node(node_id, sa)) {
sa->recovery_time_stamp = recovery_time_stamp;
sa->function_features = {};
std::size_t hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
associations.insert((int32_t)hash_node_id, sa);
trigger_heartbeat_request_procedure(sa);
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_association(oai::cn::core::pfcp::node_id_t& node_id, oai::cn::core::pfcp::recovery_time_stamp_t& recovery_time_stamp, oai::cn::core::pfcp::cp_function_features_t&
function_features)
{
std::shared_ptr<pfcp_association> sa = {};
if (remove_peer_candidate_node(node_id, sa)) {
sa->recovery_time_stamp = recovery_time_stamp;
sa->set(function_features);
std::size_t hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
associations.insert((int32_t)hash_node_id, sa);
trigger_heartbeat_request_procedure(sa);
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::get_association(const oai::cn::core::pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa) const
{
std::size_t hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
auto pit = associations.find((int32_t)hash_node_id);
if ( pit == associations.end() )
return false;
else {
sa = pit->second;
return true;
}
}
//------------------------------------------------------------------------------
bool pfcp_associations::get_association(const oai::cn::core::pfcp::fseid_t& cp_fseid, std::shared_ptr<pfcp_association>& sa) const
{
folly::AtomicHashMap<int32_t, std::shared_ptr<pfcp_association>>::iterator it;
FOR_EACH (it, associations) {
std::shared_ptr<pfcp_association> a = it->second;
if (it->second->has_session(cp_fseid)) {
sa = it->second;
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::remove_peer_candidate_node(oai::cn::core::pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& s)
{
for (std::vector<std::shared_ptr<pfcp_association>>::iterator it=pending_associations.begin(); it < pending_associations.end(); ++it) {
if ((*it)->node_id == node_id) {
s = *it;
pending_associations.erase(it);
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_peer_candidate_node(const oai::cn::core::pfcp::node_id_t& node_id)
{
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::spgwu_sx().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);
pending_associations.push_back(s);
return true;
//start_timer = itti_inst->timer_setup(0,0, TASK_SPGWU_SX, TASK_MME_S11_TIMEOUT_SEND_GTPU_PING, 0);
}
//------------------------------------------------------------------------------
void pfcp_associations::trigger_heartbeat_request_procedure(std::shared_ptr<pfcp_association>& s)
{
s->timer_heartbeat = itti_inst->timer_setup(5,0, TASK_SPGWU_SX, TASK_SPGWU_SX_TRIGGER_HEARTBEAT_REQUEST, s->hash_node_id);
}
//------------------------------------------------------------------------------
void pfcp_associations::initiate_heartbeat_request(core::itti::timer_id_t timer_id, uint64_t arg2_user)
{
size_t hash = (size_t)arg2_user;
for (auto it : associations) {
if (it.second->hash_node_id == hash) {
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE hash %u starting", hash);
it.second->num_retries_timer_heartbeat = 0;
spgwu_sx_inst->send_heartbeat_request(it.second);
}
}
}
//------------------------------------------------------------------------------
void pfcp_associations::timeout_heartbeat_request(core::itti::timer_id_t timer_id, uint64_t arg2_user)
{
size_t hash = (size_t)arg2_user;
for (auto it : associations) {
if (it.second->hash_node_id == hash) {
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE hash %u TIMED OUT", hash);
if (it.second->num_retries_timer_heartbeat < PFCP_ASSOCIATION_HEARTBEAT_MAX_RETRIES) {
it.second->num_retries_timer_heartbeat++;
spgwu_sx_inst->send_heartbeat_request(it.second);
} else {
it.second->del_sessions();
core::pfcp::node_id_t node_id = it.second->node_id;
std::size_t hash_node_id = it.second->hash_node_id;
associations.erase((uint32_t)hash_node_id);
add_peer_candidate_node(node_id);
break;
}
}
}
}
//------------------------------------------------------------------------------
void pfcp_associations::handle_receive_heartbeat_response(const uint64_t trxn_id)
{
for (auto it : associations) {
if (it.second->trxn_id_heartbeat == trxn_id) {
itti_inst->timer_remove(it.second->timer_heartbeat);
trigger_heartbeat_request_procedure(it.second);
return;
}
}
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE trxn_id %d NOT FOUND", trxn_id);
}
//------------------------------------------------------------------------------
void pfcp_associations::notify_add_session(const oai::cn::core::pfcp::node_id_t& node_id, const oai::cn::core::pfcp::fseid_t& cp_fseid)
{
std::shared_ptr<pfcp_association> sa = {};
if (get_association(node_id, sa)) {
sa->notify_add_session(cp_fseid);
}
}
//------------------------------------------------------------------------------
void pfcp_associations::notify_del_session(const oai::cn::core::pfcp::fseid_t& cp_fseid)
{
std::shared_ptr<pfcp_association> sa = {};
if (get_association(cp_fseid, sa)) {
sa->notify_del_session(cp_fseid);
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_pfcp_association.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN
#define FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN
#include "3gpp_29.244.h"
#include "itti.hpp"
#include <folly/AtomicHashMap.h>
#include <folly/AtomicLinkedList.h>
#include <mutex>
#include <vector>
namespace oai::cn::nf::spgwu {
#define PFCP_ASSOCIATION_HEARTBEAT_MAX_RETRIES 5
class pfcp_association {
public:
oai::cn::core::pfcp::node_id_t node_id;
std::size_t hash_node_id;
oai::cn::core::pfcp::recovery_time_stamp_t recovery_time_stamp;
std::pair<bool,oai::cn::core::pfcp::cp_function_features_t> function_features;
//
mutable std::mutex m_sessions;
std::set<oai::cn::core::pfcp::fseid_t> sessions;
//
oai::cn::core::itti::timer_id_t timer_heartbeat;
int num_retries_timer_heartbeat;
uint64_t trxn_id_heartbeat;
oai::cn::core::itti::timer_id_t timer_association;
pfcp_association(const oai::cn::core::pfcp::node_id_t& node_id) :
node_id(node_id), recovery_time_stamp(), function_features(), m_sessions(), sessions() {
hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
}
pfcp_association(const oai::cn::core::pfcp::node_id_t& node_id, oai::cn::core::pfcp::recovery_time_stamp_t& recovery_time_stamp) :
node_id(node_id), recovery_time_stamp(recovery_time_stamp), function_features(), m_sessions(), sessions() {
hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
}
pfcp_association(const oai::cn::core::pfcp::node_id_t& ni, oai::cn::core::pfcp::recovery_time_stamp_t& rts, oai::cn::core::pfcp::cp_function_features_t& uff):
node_id(ni), recovery_time_stamp(rts), m_sessions(), sessions() {
hash_node_id = std::hash<oai::cn::core::pfcp::node_id_t>{}(node_id);
function_features.first = true;
function_features.second = uff;
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
}
// pfcp_association(pfcp_association const & p)
// {
// node_id = p.node_id;
// hash_node_id = p.hash_node_id;
// recovery_time_stamp = p.recovery_time_stamp;
// function_features = p.function_features;
// sessions = p.sessions;
// num_sessions = p.num_sessions;
// timer_heartbeat = p.timer_heartbeat;
// num_retries_timer_heartbeat = p.num_retries_timer_heartbeat;
// trxn_id_heartbeat = p.trxn_id_heartbeat;
// }
void notify_add_session(const oai::cn::core::pfcp::fseid_t& cp_fseid);
bool has_session(const oai::cn::core::pfcp::fseid_t& cp_fseid);
void notify_del_session(const oai::cn::core::pfcp::fseid_t& cp_fseid);
void del_sessions();
void set(const oai::cn::core::pfcp::cp_function_features_t& ff) {function_features.first = true; function_features.second = ff;};
};
#define PFCP_MAX_ASSOCIATIONS 16
class pfcp_associations {
private:
std::vector<std::shared_ptr<pfcp_association>> pending_associations;
folly::AtomicHashMap<int32_t, std::shared_ptr<pfcp_association>> associations;
pfcp_associations() : associations(PFCP_MAX_ASSOCIATIONS), pending_associations() {};
void trigger_heartbeat_request_procedure(std::shared_ptr<pfcp_association>& s);
bool remove_peer_candidate_node(oai::cn::core::pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& s);
public:
static pfcp_associations& get_instance()
{
static pfcp_associations instance;
return instance;
}
pfcp_associations(pfcp_associations const&) = delete;
void operator=(pfcp_associations const&) = delete;
bool add_association(oai::cn::core::pfcp::node_id_t& node_id, oai::cn::core::pfcp::recovery_time_stamp_t& recovery_time_stamp);
bool add_association(oai::cn::core::pfcp::node_id_t& node_id, oai::cn::core::pfcp::recovery_time_stamp_t& recovery_time_stamp, oai::cn::core::pfcp::cp_function_features_t& function_features);
bool get_association(const oai::cn::core::pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa) const;
bool get_association(const oai::cn::core::pfcp::fseid_t& cp_fseid, std::shared_ptr<pfcp_association>& sa) const;
void notify_add_session(const oai::cn::core::pfcp::node_id_t& node_id, const oai::cn::core::pfcp::fseid_t& cp_fseid);
void notify_del_session(const oai::cn::core::pfcp::fseid_t& cp_fseid);
bool add_peer_candidate_node(const oai::cn::core::pfcp::node_id_t& node_id);
void initiate_heartbeat_request(oai::cn::core::itti::timer_id_t timer_id, uint64_t arg2_user);
void timeout_heartbeat_request(oai::cn::core::itti::timer_id_t timer_id, uint64_t arg2_user);
void handle_receive_heartbeat_response(const uint64_t trxn_id);
};
}
#endif /* FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN */
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_sx.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SGWU_SX_HPP_SEEN
#define FILE_SGWU_SX_HPP_SEEN
#include "pfcp.hpp"
#include "itti_msg_sxab.hpp"
#include "msg_pfcp.hpp"
#include "spgwu_pfcp_association.hpp"
#include <boost/asio.hpp>
#include <boost/asio/ip/address.hpp>
#include <thread>
namespace oai::cn::nf::spgwu {
#define TASK_SPGWU_SX_TRIGGER_HEARTBEAT_REQUEST (0)
#define TASK_SPGWU_SX_TIMEOUT_HEARTBEAT_REQUEST (1)
#define TASK_SPGWU_SX_TIMEOUT_ASSOCIATION_REQUEST (2)
class spgwu_sx : public oai::cn::proto::pfcp::pfcp_l4_stack {
private:
std::thread::id thread_id;
std::thread thread;
uint64_t recovery_time_stamp; //timestamp in seconds
core::pfcp::up_function_features_t up_function_features;
void start_association(const core::pfcp::node_id_t& node_id);
public:
spgwu_sx();
spgwu_sx(spgwu_sx const&) = delete;
void operator=(spgwu_sx const&) = delete;
void handle_itti_msg (core::itti::itti_sxab_heartbeat_request& s) {};
void handle_itti_msg (core::itti::itti_sxab_heartbeat_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_setup_request& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_setup_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_update_request& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_update_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_release_request& s) {};
void handle_itti_msg (core::itti::itti_sxab_association_release_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_version_not_supported_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_node_report_response& s) {};
void handle_itti_msg (core::itti::itti_sxab_session_set_deletion_request& s) {};
void handle_itti_msg (core::itti::itti_sxab_session_establishment_response& s);
void handle_itti_msg (core::itti::itti_sxab_session_modification_response& s);
void handle_itti_msg (core::itti::itti_sxab_session_deletion_response& s);
void handle_itti_msg (core::itti::itti_sxab_session_report_response& s) {};
void send_sx_msg (core::itti::itti_sxab_heartbeat_request& s) {};
void send_sx_msg (core::itti::itti_sxab_heartbeat_response& s) {};
void send_sx_msg (core::itti::itti_sxab_association_setup_request& s);
void send_sx_msg (core::itti::itti_sxab_association_setup_response& s) {};
void send_sx_msg (core::itti::itti_sxab_association_update_request& s) {};
void send_sx_msg (core::itti::itti_sxab_association_update_response& s) {};
void send_sx_msg (core::itti::itti_sxab_association_release_request& s) {};
void send_sx_msg (core::itti::itti_sxab_association_release_response& s) {};
void send_sx_msg (core::itti::itti_sxab_version_not_supported_response& s) {};
void send_sx_msg (core::itti::itti_sxab_node_report_request& s) {};
void send_sx_msg (core::itti::itti_sxab_session_set_deletion_response& s) {};
void send_sx_msg (core::itti::itti_sxab_session_establishment_response& s);
void send_sx_msg (core::itti::itti_sxab_session_modification_response& s);
void send_sx_msg (core::itti::itti_sxab_session_deletion_response& s);
void send_sx_msg (core::itti::itti_sxab_session_report_request& s) {};
void send_sx_msg(const core::pfcp::fseid_t& cp_fseid, const oai::cn::proto::pfcp::pfcp_session_report_request& s);
void send_heartbeat_request(std::shared_ptr<pfcp_association>& a);
void send_heartbeat_response(const boost::asio::ip::udp::endpoint& r_endpoint, const uint64_t trxn_id);
void handle_receive_pfcp_msg( proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint);
// node related
void handle_receive_heartbeat_request(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_heartbeat_response(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_association_setup_response(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
// session related
void handle_receive_session_establishment_request(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_session_modification_request(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_session_deletion_request(proto::pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void time_out_itti_event(const uint32_t timer_id);
};
}
#endif /* FILE_SGWU_SX_HPP_SEEN */
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