Commit 6a06fd2e authored by gauthier's avatar gauthier
Browse files

S11 Downlink Data Notification sent

parent d91a9bbe
......@@ -391,6 +391,10 @@ public:
itti_s11_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
itti_s11_downlink_data_notification(const gtpv2c::gtpv2c_downlink_data_notification& ies, const task_id_t orig, const task_id_t dest) :
itti_s11_downlink_data_notification(orig, dest) {
gtp_ies = ies;
}
const char* get_msg_name() {return typeid(itti_s11_downlink_data_notification).name();};
gtpv2c::gtpv2c_downlink_data_notification gtp_ies;
......
......@@ -56,23 +56,27 @@ static std::string string_to_hex(const std::string& input)
//------------------------------------------------------------------------------
gtpv2c_stack::gtpv2c_stack(const string& ip_address, const unsigned short port_num, const util::thread_sched_params& sched_params) :
udp_s(udp_server(ip_address.c_str(), port_num)),
udp_s_allocated(ip_address.c_str(), 0){
udp_s_allocated(ip_address.c_str(), 0), m_seq_num() {
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
seq_num = (uint32_t)ts.tv_nsec & 0x7FFFFFFF;
Logger::gtpv2_c().info( "gtpv2c_stack created listening to %s:%d initial seq num %d", ip_address.c_str(), port_num, seq_num);
Logger::gtpv2_c().info( "gtpv2c_stack created listening to %s:%d", ip_address.c_str(), port_num);
gtpc_tx_id2seq_num = {};
proc_cleanup_timers = {};
msg_out_retry_timers = {};
pending_procedures = {};
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
restart_counter = 0;
udp_s.start_receive(this, sched_params);
udp_s_allocated.start_receive(this, sched_params);
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::get_next_seq_num() {
std::unique_lock lock(m_seq_num);
seq_num++;
if (seq_num & 0x80000000) {
seq_num = 0;
......@@ -195,7 +199,9 @@ void gtpv2c_stack::start_msg_retry_timer(gtpv2c_procedure& p, uint32_t time_out_
if (!p.retry_timer_id) {
p.retry_timer_id = itti_inst->timer_setup (time_out_milli_seconds/1000, time_out_milli_seconds%1000, task_id);
msg_out_retry_timers.insert(std::pair<timer_id_t, uint32_t>(p.retry_timer_id, seq_num));
//Logger::gtpv2_c().trace( "Started Msg retry timer %d, proc " PROC_ID_FMT ", seq %d",p.retry_timer_id, p.gtpc_tx_id, seq_num);
#if TRACE_IS_ON
Logger::gtpv2_c().trace( "Started Msg retry timer %d, proc " PROC_ID_FMT ", seq %d",p.retry_timer_id, p.gtpc_tx_id, seq_num);
#endif
} else {
Logger::gtpv2_c().error( "Try to overwrite Msg retry timer %d, proc " PROC_ID_FMT ", seq %d!",p.retry_timer_id, p.gtpc_tx_id, seq_num);
}
......@@ -206,7 +212,9 @@ void gtpv2c_stack::stop_msg_retry_timer(gtpv2c_procedure& p)
if (p.retry_timer_id) {
itti_inst->timer_remove(p.retry_timer_id);
msg_out_retry_timers.erase(p.retry_timer_id);
//Logger::gtpv2_c().trace( "Stopped Msg retry timer %d, proc " PROC_ID_FMT ", seq %d",p.retry_timer_id, p.gtpc_tx_id, p.retry_msg->get_sequence_number());
#if TRACE_IS_ON
Logger::gtpv2_c().trace( "Stopped Msg retry timer %d, proc " PROC_ID_FMT ", seq %d",p.retry_timer_id, p.gtpc_tx_id, p.retry_msg->get_sequence_number());
#endif
p.retry_timer_id = 0;
}
}
......@@ -215,7 +223,9 @@ void gtpv2c_stack::stop_msg_retry_timer(timer_id_t& t)
{
itti_inst->timer_remove(t);
msg_out_retry_timers.erase(t);
//Logger::gtpv2_c().trace( "Stopped Msg retry timer %d",t);
#if TRACE_IS_ON
Logger::gtpv2_c().trace( "Stopped Msg retry timer %d",t);
#endif
}
//------------------------------------------------------------------------------
void gtpv2c_stack::start_proc_cleanup_timer(gtpv2c_procedure& p, uint32_t time_out_milli_seconds, const task_id_t& task_id, const uint32_t& seq_num)
......@@ -223,7 +233,9 @@ void gtpv2c_stack::start_proc_cleanup_timer(gtpv2c_procedure& p, uint32_t time_o
if (!p.proc_cleanup_timer_id) {
p.proc_cleanup_timer_id = itti_inst->timer_setup (time_out_milli_seconds/1000, time_out_milli_seconds%1000, task_id);
proc_cleanup_timers.insert(std::pair<timer_id_t, uint32_t>(p.proc_cleanup_timer_id, seq_num));
//Logger::gtpv2_c().trace( "Started proc cleanup timer %d, proc " PROC_ID_FMT " t-out %" PRIu32" ms",p.proc_cleanup_timer_id,p.gtpc_tx_id, time_out_milli_seconds);
#if TRACE_IS_ON
Logger::gtpv2_c().trace( "Started proc cleanup timer %d, proc " PROC_ID_FMT " t-out %" PRIu32" ms",p.proc_cleanup_timer_id,p.gtpc_tx_id, time_out_milli_seconds);
#endif
} else {
Logger::gtpv2_c().error( "Try to overwrite proc cleanup timer %d, proc " PROC_ID_FMT " t-out %" PRIu32" ms",p.proc_cleanup_timer_id,p.gtpc_tx_id, time_out_milli_seconds);
}
......@@ -232,7 +244,9 @@ void gtpv2c_stack::start_proc_cleanup_timer(gtpv2c_procedure& p, uint32_t time_o
void gtpv2c_stack::stop_proc_cleanup_timer(gtpv2c_procedure& p)
{
itti_inst->timer_remove(p.proc_cleanup_timer_id);
//Logger::gtpv2_c().trace( "Stopped proc cleanup timer %d, proc " PROC_ID_FMT "",p.proc_cleanup_timer_id, p.gtpc_tx_id);
#if TRACE_IS_ON
Logger::gtpv2_c().trace( "Stopped proc cleanup timer %d, proc " PROC_ID_FMT "",p.proc_cleanup_timer_id, p.gtpc_tx_id);
#endif
msg_out_retry_timers.erase(p.proc_cleanup_timer_id);
p.proc_cleanup_timer_id = 0;
}
......@@ -411,7 +425,6 @@ uint32_t gtpv2c_stack::send_initial_message(const endpoint& dest, const teid_t t
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
udp_s_allocated.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), dest);
return msg.get_sequence_number();
......@@ -436,7 +449,6 @@ uint32_t gtpv2c_stack::send_initial_message(const endpoint& dest, const teid_t t
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
udp_s_allocated.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), dest);
return msg.get_sequence_number();
......
......@@ -49,9 +49,9 @@ namespace gtpv2c {
class gtpv2c_procedure {
public:
std::shared_ptr<gtpv2c_msg> retry_msg;
endpoint remote_endpoint;
timer_id_t retry_timer_id;
timer_id_t proc_cleanup_timer_id;
endpoint remote_endpoint;
timer_id_t retry_timer_id;
timer_id_t proc_cleanup_timer_id;
uint64_t gtpc_tx_id;
uint8_t initial_msg_type; // sent or received
uint8_t triggered_msg_type; // sent or received
......@@ -98,8 +98,9 @@ protected:
udp_server udp_s;
udp_server udp_s_allocated;
// seems no need for std::atomic_uint32_t
// seems no need for atomic
uint32_t seq_num;
std::mutex m_seq_num;
uint32_t restart_counter;
std::map<uint64_t, uint32_t> gtpc_tx_id2seq_num;
......@@ -147,6 +148,9 @@ public:
virtual void send_triggered_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_release_access_bearers_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
void time_out_event(const uint32_t timer_id, const task_id_t& task_id, bool &error);
};
} // namespace gtpv2c
......
......@@ -3518,6 +3518,13 @@ public:
void set(const imsi_t& v, const uint8_t instance = 0) {imsi = v;ie_presence_mask |= DOWNLINK_DATA_NOTIFICATION_PR_IE_IMSI;}
void set(const fteid_t& v, const uint8_t instance = 0) {sender_fteid_for_cp = v;ie_presence_mask |= DOWNLINK_DATA_NOTIFICATION_PR_IE_SENDER_FTEID_FOR_CP;}
void set(const indication_t& v, const uint8_t instance = 0) {indication_flags = v;ie_presence_mask |= DOWNLINK_DATA_NOTIFICATION_PR_IE_INDICATION_FLAGS;}
bool get(cause_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_CAUSE) {v = cause;return true;}return false;}
bool get(ebi_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_EPS_BEARER_ID) {v = eps_bearer_id;return true;}return false;}
bool get(arp_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_ARP) {v = arp;return true;}return false;}
bool get(imsi_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_IMSI) {v = imsi;return true;}return false;}
bool get(fteid_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_SENDER_FTEID_FOR_CP) {v = sender_fteid_for_cp;return true;}return false;}
bool get(indication_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_INDICATION_FLAGS) {v = indication_flags;return true;}return false;}
};
//-----------------------------------------------------------------------------
......
......@@ -29,6 +29,7 @@
#include <thread>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h> // srand
#include <unistd.h> // get_pid(), pause()
using namespace gtpv2c;
......@@ -65,6 +66,7 @@ void my_app_signal_handler(int s){
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
srand (time(NULL));
// Logger
Logger::init( "spgwc" );
......
......@@ -46,8 +46,10 @@ pfcp_l4_stack::pfcp_l4_stack(const string& ip_address, const unsigned short port
pending_procedures = {};
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
seq_num = (uint32_t)ts.tv_nsec & 0x7FFFFFFF;
restart_counter = 0;
udp_s_8805.start_receive(this, sched_params);
udp_s_allocated.start_receive(this, sched_params);
......
......@@ -83,25 +83,25 @@ enum pfcp_transaction_action {
};
class pfcp_l4_stack : public udp_application {
#define PFCP_T1_RESPONSE_MS 1000
#define PFCP_N1_REQUESTS 3
#define PFCP_PROC_TIME_OUT_MS ((PFCP_T1_RESPONSE_MS) * (PFCP_N1_REQUESTS + 1 + 1))
#define PFCP_T1_RESPONSE_MS 1000
#define PFCP_N1_REQUESTS 3
#define PFCP_PROC_TIME_OUT_MS ((PFCP_T1_RESPONSE_MS) * (PFCP_N1_REQUESTS + 1 + 1))
protected:
uint32_t id;
udp_server udp_s_8805;
udp_server udp_s_allocated;
uint32_t id;
udp_server udp_s_8805;
udp_server udp_s_allocated;
// seems no need for std::atomic_uint32_t
uint32_t seq_num;
uint32_t restart_counter;
uint32_t seq_num;
uint32_t restart_counter;
std::map<uint64_t, uint32_t> trxn_id2seq_num;
std::map<timer_id_t, uint32_t> proc_cleanup_timers;
std::map<timer_id_t, uint32_t> msg_out_retry_timers;
std::map<uint32_t , pfcp_procedure> pending_procedures;
std::map<uint64_t, uint32_t> trxn_id2seq_num;
std::map<timer_id_t, uint32_t> proc_cleanup_timers;
std::map<timer_id_t, uint32_t> msg_out_retry_timers;
std::map<uint32_t , pfcp_procedure> pending_procedures;
static const char* msg_type2cstr[256];
static const char* msg_type2cstr[256];
uint32_t get_next_seq_num();
......
......@@ -208,6 +208,12 @@ void sgwc_app_task (void *args_p)
}
break;
case S5S8_DOWNLINK_DATA_NOTIFICATION:
if (itti_s5s8_downlink_data_notification* m = dynamic_cast<itti_s5s8_downlink_data_notification*>(msg)) {
sgwc_app_inst->handle_itti_msg(ref(*m));
}
break;
case S11_DELETE_SESSION_REQUEST:
if (itti_s11_delete_session_request* m = dynamic_cast<itti_s11_delete_session_request*>(msg)) {
sgwc_app_inst->handle_itti_msg(ref(*m));
......@@ -462,10 +468,10 @@ void sgwc_app::handle_itti_msg (itti_s5s8_delete_session_response& m)
}
Logger::sgwc_app().debug("sgw_eps_bearer_context: %s!", p.first->toString().c_str());
} else {
Logger::sgwc_app().debug("Received S5S8 DELETE_SESSION_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore DSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 DELETE_SESSION_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore!", m.teid);
}
} else {
Logger::sgwc_app().debug("Received S5S8 DELETE_SESSION_RESPONSE with dest teid " TEID_FMT " unknown, ignore DSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 DELETE_SESSION_RESPONSE with dest teid " TEID_FMT " unknown, ignore!", m.teid);
}
}
//------------------------------------------------------------------------------
......@@ -478,10 +484,10 @@ void sgwc_app::handle_itti_msg (itti_s5s8_modify_bearer_response& m)
p.first->handle_itti_msg(m, p.second);
Logger::sgwc_app().debug("sgw_eps_bearer_context: %s!", p.first->toString().c_str());
} else {
Logger::sgwc_app().debug("Received S5S8 MODIFY_BEARER_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore CSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 MODIFY_BEARER_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore!", m.teid);
}
} else {
Logger::sgwc_app().debug("Received S5S8 MODIFY_BEARER_RESPONSE with dest teid " TEID_FMT " unknown, ignore CSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 MODIFY_BEARER_RESPONSE with dest teid " TEID_FMT " unknown, ignore!", m.teid);
}
}
//------------------------------------------------------------------------------
......@@ -494,10 +500,27 @@ void sgwc_app::handle_itti_msg (itti_s5s8_release_access_bearers_response& m)
p.first->handle_itti_msg(m, p.second);
Logger::sgwc_app().debug("sgw_eps_bearer_context: %s!", p.first->toString().c_str());
} else {
Logger::sgwc_app().debug("Received S5S8 RELEASE_ACCESS_BEARERS_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore CSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 RELEASE_ACCESS_BEARERS_RESPONSE with dest teid " TEID_FMT ", SGW contexts not found, ignore!", m.teid);
}
} else {
Logger::sgwc_app().debug("Received S5S8 RELEASE_ACCESS_BEARERS_RESPONSE with dest teid " TEID_FMT " unknown, ignore!", m.teid);
}
}
//------------------------------------------------------------------------------
void sgwc_app::handle_itti_msg (itti_s5s8_downlink_data_notification& m)
{
Logger::sgwc_app().debug("Received S5S8 DOWNLINK_DATA_NOTIFICATION sender teid " TEID_FMT " gtpc_tx_id " PROC_ID_FMT " ", m.teid, m.gtpc_tx_id);
if (is_s5s8sgw_teid_2_sgw_contexts(m.teid)) {
std::pair<std::shared_ptr<sgw_eps_bearer_context>, std::shared_ptr<sgw_pdn_connection>> p = s5s8sgw_teid_2_sgw_contexts(m.teid);
if ((p.first.get()) && (p.second.get())) {
p.first->handle_itti_msg(m, p.second);
Logger::sgwc_app().debug("sgw_eps_bearer_context: %s!", p.first->toString().c_str());
} else {
Logger::sgwc_app().debug("Received S5S8 DOWNLINK_DATA_NOTIFICATION with dest teid " TEID_FMT ", SGW contexts not found, ignore!", m.teid);
}
} else {
Logger::sgwc_app().debug("Received S5S8 RELEASE_ACCESS_BEARERS_RESPONSE with dest teid " TEID_FMT " unknown, ignore CSResp", m.teid);
Logger::sgwc_app().debug("Received S5S8 DOWNLINK_DATA_NOTIFICATION with dest teid " TEID_FMT " unknown, ignore!", m.teid);
}
}
......@@ -118,6 +118,7 @@ public:
void handle_itti_msg (itti_s5s8_delete_session_response& m);
void handle_itti_msg (itti_s5s8_modify_bearer_response& m);
void handle_itti_msg (itti_s5s8_release_access_bearers_response& m);
void handle_itti_msg (itti_s5s8_downlink_data_notification& m);
};
}
......
......@@ -210,6 +210,23 @@ void sgw_eps_bearer_context::create_procedure(itti_s11_delete_session_request& d
}
}
//------------------------------------------------------------------------------
void sgw_eps_bearer_context::create_procedure(itti_s5s8_downlink_data_notification& ddn, std::shared_ptr<sgw_pdn_connection> spc)
{
downlink_data_notification_procedure* p = new downlink_data_notification_procedure(ddn);
insert_procedure(p);
int rc = p->run(shared_from_this(), spc);
switch (rc) {
case RETURNerror:
// TODO handle error code
Logger::sgwc_app().info( "S5S8 DOWNLINK_DATA_NOTIFICATION procedure failed");
case RETURNclear:
remove_procedure(p);
break;
case RETURNok:
default:;
}
}
//------------------------------------------------------------------------------
void sgw_eps_bearer_context::insert_procedure(sebc_procedure* proc)
{
pending_procedures.push_back(shared_ptr<sebc_procedure>(proc));
......@@ -358,6 +375,17 @@ void sgw_eps_bearer_context::handle_itti_msg (itti_s5s8_delete_session_response&
}
}
//------------------------------------------------------------------------------
void sgw_eps_bearer_context::handle_itti_msg (itti_s5s8_downlink_data_notification& ddn, std::shared_ptr<sgw_pdn_connection> spc)
{
shared_ptr<sebc_procedure> sp = find_procedure(ddn.gtpc_tx_id);
if (sp.get()) {
Logger::sgwc_app().error("S5S8 DOWNLINK_DATA_NOTIFICATION ignored, existing procedure found gtpc_tx_id %d!", ddn.gtpc_tx_id);
return;
} else {
create_procedure(ddn, spc);
}
}
//------------------------------------------------------------------------------
std::string sgw_eps_bearer_context::toString() const
{
std::string s = {};
......
......@@ -207,6 +207,7 @@ public:
void create_procedure(itti_s11_modify_bearer_request& );
void create_procedure(itti_s11_delete_session_request& );
void create_procedure(itti_s11_release_access_bearers_request& );
void create_procedure(itti_s5s8_downlink_data_notification&, std::shared_ptr<sgw_pdn_connection> spc);
void insert_procedure(sebc_procedure* proc);
std::shared_ptr<sebc_procedure> find_procedure(const uint64_t& gtpc_tx_id);
......@@ -227,6 +228,7 @@ public:
void handle_itti_msg (itti_s5s8_delete_session_response& m, std::shared_ptr<sgw_pdn_connection> spc);
void handle_itti_msg (itti_s5s8_modify_bearer_response& m, std::shared_ptr<sgw_pdn_connection> spc);
void handle_itti_msg (itti_s5s8_release_access_bearers_response& m, std::shared_ptr<sgw_pdn_connection> spc);
void handle_itti_msg (itti_s5s8_downlink_data_notification& m, std::shared_ptr<sgw_pdn_connection> spc);
std::string toString() const;
......
......@@ -39,22 +39,26 @@ extern itti_mw *itti_inst;
extern sgwc_app *sgwc_app_inst;
extern sgwc_config sgwc_cfg;
void sebc_procedure::handle_itti_msg (itti_s5s8_create_session_response& csresp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
void sebc_procedure::handle_itti_msg (itti_s5s8_create_session_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
{
Logger::sgwc_app().error( "Unhandled message itti_s5s8_create_session_response");
}
void sebc_procedure::handle_itti_msg (itti_s5s8_delete_session_response& dsresp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
void sebc_procedure::handle_itti_msg (itti_s5s8_delete_session_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
{
Logger::sgwc_app().error( "Unhandled message itti_s5s8_delete_session_response");
}
void sebc_procedure::handle_itti_msg (itti_s5s8_modify_bearer_response& dsresp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
void sebc_procedure::handle_itti_msg (itti_s5s8_modify_bearer_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
{
Logger::sgwc_app().error( "Unhandled message itti_s5s8_modify_bearer_response");
}
void sebc_procedure::handle_itti_msg (itti_s5s8_release_access_bearers_response& dsresp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
void sebc_procedure::handle_itti_msg (itti_s5s8_release_access_bearers_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
{
Logger::sgwc_app().error( "Unhandled message itti_s5s8_release_access_bearers_response");
}
void sebc_procedure::handle_itti_msg (itti_s5s8_downlink_data_notification& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc)
{
Logger::sgwc_app().error( "Unhandled message itti_s5s8_downlink_data_notification");
}
//------------------------------------------------------------------------------
int create_session_request_procedure::run(shared_ptr<sgw_eps_bearer_context> c)
......@@ -820,3 +824,41 @@ void release_access_bearers_request_procedure::handle_itti_msg (itti_s5s8_releas
}
}
//------------------------------------------------------------------------------
int downlink_data_notification_procedure::run(std::shared_ptr<sgw_eps_bearer_context> sebc, std::shared_ptr<sgw_pdn_connection> pdn)
{
if ((nullptr == sebc.get()) || (nullptr == pdn.get())) {
return RETURNerror;
} else {
ebc = sebc;
pdn_connection = pdn;
ebi_t ebi = {};
if (not (msg.gtp_ies.get(ebi))) {
Logger::sgwc_app().error( "downlink_data_notification_procedure: Could not get ebi in %s", msg.get_msg_name());
return RETURNerror;
}
std::shared_ptr<sgw_eps_bearer> b = {};
if (not pdn_connection->get_eps_bearer(ebi, b)) {
Logger::sgwc_app().error( "downlink_data_notification_procedure: Could not get EPS bearer context %d", ebi.ebi);
return RETURNerror;
}
itti_s11_downlink_data_notification *s11 = new itti_s11_downlink_data_notification(msg.gtp_ies, TASK_SGWC_APP, TASK_SGWC_S11);
s11->teid = ebc->mme_fteid_s11.teid_gre_key;
s11->gtpc_tx_id = get_trxn_id();
s11->r_endpoint = endpoint(ebc->mme_fteid_s11.ipv4_address, gtpv2c::default_port);
s11_triggered = std::shared_ptr<itti_s11_downlink_data_notification>(s11);
Logger::pgwc_app().info( "Sending ITTI message %s to task TASK_SGWC_S11", s11->gtp_ies.get_msg_name());
int ret = itti_inst->send_msg(s11_triggered);
if (RETURNok != ret) {
Logger::pgwc_app().error( "Could not send ITTI message %s to task TASK_SGWC_S11", s11->gtp_ies.get_msg_name());
return RETURNerror;
}
return RETURNok;
}
}
......@@ -29,6 +29,7 @@
*/
#include "itti_msg_s11.hpp"
#include "itti_msg_s5s8.hpp"
#include "msg_gtpv2c.hpp"
#include "uint_generator.hpp"
......@@ -62,6 +63,7 @@ public:
virtual void handle_itti_msg (itti_s5s8_delete_session_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc);
virtual void handle_itti_msg (itti_s5s8_modify_bearer_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc);
virtual void handle_itti_msg (itti_s5s8_release_access_bearers_response& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc);
virtual void handle_itti_msg (itti_s5s8_downlink_data_notification& resp, std::shared_ptr<sgw_eps_bearer_context> ebc, std::shared_ptr<sgw_pdn_connection> spc);
};
//------------------------------------------------------------------------------
......@@ -162,6 +164,25 @@ public:
std::shared_ptr<sgw_eps_bearer_context> ebc;
std::shared_ptr<sgw_pdn_connection> pdn_connection;
};
//------------------------------------------------------------------------------
class downlink_data_notification_procedure : public sebc_procedure {
public:
explicit downlink_data_notification_procedure(itti_s5s8_downlink_data_notification& msg) : sebc_procedure(msg.gtpc_tx_id), msg(msg),
s11_triggered(), ebc(), pdn_connection() {}
int run(std::shared_ptr<sgw_eps_bearer_context> context,
std::shared_ptr<sgw_pdn_connection> spc);
//void handle_itti_msg (itti_sxab_session_report_response& resp);
//~downlink_data_notification_procedure() {}
itti_s5s8_downlink_data_notification msg;
std::shared_ptr<itti_s11_downlink_data_notification> s11_triggered;
std::shared_ptr<sgw_eps_bearer_context> ebc;
std::shared_ptr<sgw_pdn_connection> pdn_connection;
};
}
#include "sgwc_eps_bearer_context.hpp"
......
......@@ -96,6 +96,12 @@ void sgw_s11_task (void *args_p)
}
break;
case S11_DOWNLINK_DATA_NOTIFICATION:
if (itti_s11_downlink_data_notification* m = dynamic_cast<itti_s11_downlink_data_notification*>(msg)) {
sgw_s11_inst->send_msg(ref(*m));
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::sgwc_s11().debug( "TIME-OUT event timer id %d", to->timer_id);
......@@ -148,6 +154,11 @@ void sgw_s11::send_msg(itti_s11_release_access_bearers_response& i)
send_triggered_message(i.r_endpoint, i.teid, i.gtp_ies, i.gtpc_tx_id);
}
//------------------------------------------------------------------------------
void sgw_s11::send_msg(itti_s11_downlink_data_notification& i)
{
send_initial_message(i.r_endpoint, i.teid, i.gtp_ies, TASK_SGWC_S11, i.gtpc_tx_id);
}
//------------------------------------------------------------------------------
void sgw_s11::handle_receive_create_session_request(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
......
......@@ -59,6 +59,7 @@ public:
void send_msg(itti_s11_delete_session_response& m);
void send_msg(itti_s11_modify_bearer_response& m);
void send_msg(itti_s11_release_access_bearers_response& m);
void send_msg(itti_s11_downlink_data_notification& m);
void send_echo_response(const endpoint& r_endpoint, const uint64_t trxn_id);
......
......@@ -221,6 +221,29 @@ void sgw_s5s8::handle_receive_delete_session_response(gtpv2c_msg& msg, const end
}
// else ignore
}
//------------------------------------------------------------------------------
void sgw_s5s8::handle_receive_downlink_data_notification(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
gtpv2c_downlink_data_notification msg_ies_container = {};
msg.to_core_type(msg_ies_container);
handle_receive_message_cb(msg, remote_endpoint, TASK_SGWC_S5S8, error, gtpc_tx_id);
if (!error) {
itti_s5s8_downlink_data_notification *itti_msg = new itti_s5s8_downlink_data_notification(TASK_SGWC_S5S8, TASK_SGWC_APP);
itti_msg->gtp_ies = msg_ies_container;
itti_msg->r_endpoint = remote_endpoint;
itti_msg->gtpc_tx_id = gtpc_tx_id;
itti_msg->teid = msg.get_teid();
std::shared_ptr<itti_s5s8_downlink_data_notification> i = std::shared_ptr<itti_s5s8_downlink_data_notification>(itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::sgwc_s5s8().error( "Could not send ITTI message %s to task TASK_SGWC_APP", i->get_msg_name());
}
}
// else ignore
}
//------------------------------------------------------------------------------
void sgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const endpoint& remote_endpoint)
......@@ -254,6 +277,10 @@ void sgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const endpoint& remote
handle_receive_release_access_bearers_response(msg, remote_endpoint);
}
break;
case GTP_DOWNLINK_DATA_NOTIFICATION: {
handle_receive_downlink_data_notification(msg, remote_endpoint);
}
break;
case GTP_CHANGE_NOTIFICATION_REQUEST:
case GTP_CHANGE_NOTIFICATION_RESPONSE:
......@@ -315,7 +342,6 @@ void sgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const endpoint& remote
case GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST:
case GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE:
case GTP_RELEASE_ACCESS_BEARERS_REQUEST:
case GTP_DOWNLINK_DATA_NOTIFICATION:
case GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE:
case GTP_PGW_RESTART_NOTIFICATION:
case GTP_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE:
......
......@@ -45,6 +45,7 @@ private:
void handle_receive_delete_session_response(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint);
void handle_receive_modify_bearer_response(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint);
void handle_receive_release_access_bearers_response(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint);
void handle_receive_downlink_data_notification(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint);
public:
sgw_s5s8();
......
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