Unverified Commit 87fac28e authored by lionelgo's avatar lionelgo Committed by GitHub

Merge pull request #1 from OPENAIRINTERFACE/develop

Develop
parents 3392e5d3 a69056a0
This diff is collapsed.
......@@ -23,33 +23,33 @@ SPGW-U =
INSTANCE = @INSTANCE@; # 0 is the default
PID_DIRECTORY = "@PID_DIRECTORY@"; # /var/run is the default
ITTI_TASKS :
{
ITTI_TIMER_SCHED_PARAMS :
{
CPU_ID = 1;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 85;
};
S1U_SCHED_PARAMS :
{
CPU_ID = 1;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 84;
};
SX_SCHED_PARAMS :
{
CPU_ID = 1;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 84;
};
ASYNC_CMD_SCHED_PARAMS :
{
CPU_ID = 1;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 84;
};
};
#ITTI_TASKS :
#{
#ITTI_TIMER_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 85;
#};
#S1U_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#SX_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#ASYNC_CMD_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#};
INTERFACES :
{
......@@ -57,39 +57,39 @@ SPGW-U =
{
# S-GW binded interface for S1-U communication (GTPV1-U) can be ethernet interface, virtual ethernet interface, we don't advise wireless interfaces
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP@"; # STRING, interface name, YOUR NETWORK CONFIG HERE
IPV4_ADDRESS = "read"; # STRING, CIDR or read to let app read interface configured IP address
PORT = @SGW_UDP_PORT_FOR_S1U_S12_S4_UP@; # Default is 2152
SCHED_PARAMS :
{
CPU_ID = 2;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 98;
};
IPV4_ADDRESS = "read"; # STRING, CIDR or "read to let app read interface configured IP address
#PORT = 2152; # Default is 2152
#SCHED_PARAMS :
#{
#CPU_ID = 2;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 98;
#};
};
SX :
{
# S/P-GW binded interface for SX communication
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_SX@"; # STRING, interface name
IPV4_ADDRESS = "read"; # STRING, CIDR or read to let app read interface configured IP address
PORT = 8805; # Default is 8805
SCHED_PARAMS :
{
CPU_ID = 1;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 95;
};
IPV4_ADDRESS = "read"; # STRING, CIDR or "read" to let app read interface configured IP address
#PORT = 8805; # Default is 8805
#SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 95;
#};
};
SGI :
{
# No config to set, the software will set the SGi interface to the interface used for the default route.
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_SGI@"; # STRING, interface name or "default_gateway"
IPV4_ADDRESS = "read"; # STRING, CIDR or read to let app read interface configured IP address
SCHED_PARAMS :
{
CPU_ID = 3;
SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
SCHED_PRIORITY = 98;
};
IPV4_ADDRESS = "read"; # STRING, CIDR or "read" to let app read interface configured IP address
#SCHED_PARAMS :
#{
#CPU_ID = 3;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 98;
#};
};
};
......
......@@ -796,10 +796,10 @@ namespace pfcp {
if (i64 < this64) return true;
else if (i64 > this64) return false;
i64 = ((uint64_t)i.ipv6_address.s6_addr32[4] << 32) |
((uint64_t)i.ipv6_address.s6_addr32[5]);
this64 = ((uint64_t)this->ipv6_address.s6_addr32[4] << 32) |
((uint64_t)this->ipv6_address.s6_addr32[5]);
i64 = ((uint64_t)i.ipv6_address.s6_addr32[2] << 32) |
((uint64_t)i.ipv6_address.s6_addr32[3]);
this64 = ((uint64_t)this->ipv6_address.s6_addr32[2] << 32) |
((uint64_t)this->ipv6_address.s6_addr32[3]);
if (i64 < this64) return true;
else if (i64 > this64) return false;
} else if (this->v6) return true;
......
......@@ -391,6 +391,16 @@ struct imsi_s {
} u1;
uint num_digits;
imsi_s() : num_digits(0)
{
memset(u1.b, 0, sizeof(u1.b));
}
imsi_s(const imsi_s& i) : num_digits(i.num_digits)
{
memcpy(u1.b, i.u1.b, sizeof(u1.b));
}
std::string toString() const
{
std::string s = {};
......@@ -415,9 +425,9 @@ struct imsi_s {
{
imsi64_t imsi64 = 0;
for (int i=0; i < IMSI_BCD8_SIZE; i++) {
uint8_t d2 = u1.b[i];
uint8_t d1 = (d2 & 0xf0) >> 4;
d2 = d2 & 0x0f;
uint8_t d1 = u1.b[i];
uint8_t d2 = (d1 & 0xf0) >> 4;
d1 = d1 & 0x0f;
if (10 > d1) {
imsi64 = imsi64*10 + d1;
if (10 > d2) {
......@@ -431,6 +441,39 @@ struct imsi_s {
}
return imsi64;
}
imsi_s& operator++ () // prefix ++
{
int l_i = IMSI_BCD8_SIZE - 1;
uint8_t carry = 1;
while(l_i > 5) {
uint8_t b = u1.b[l_i];
uint8_t d0 = b & 0x0f;
uint8_t d1 = b & 0xf0;
if (d0 <= 9) {
d0 += carry;
if (d0 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d0 = 0;
u1.b[l_i] = d0 | d1;
}
}
if (d1 <= 9) {
d1 += carry;
if (d1 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d1 = 0;
u1.b[l_i] = d0 | d1;
}
}
l_i++;
}
return (*this);
}
} ;
typedef struct imsi_s imsi_t;
......@@ -578,7 +621,7 @@ typedef struct ip_address_s {
//-------------------------------------
// 8.10 Mobile Equipment Identity (MEI)
// The ME Identity field contains either the IMEI or the IMEISV as defined in subclause 6.2 of 3GPP TS 23.003
typedef struct mei_s {
struct mei_s {
#define MEI_MIN_LENGTH (15)
#define MEI_MAX_LENGTH (16)
union {
......@@ -603,10 +646,74 @@ typedef struct mei_s {
uint8_t b[MEI_MAX_LENGTH/2];
} u1;
uint num_digits;
} mei_t;
mei_s() : num_digits(0)
{
memset(u1.b, 0, sizeof(u1.b));
}
mei_s(const mei_s& i) : num_digits(i.num_digits)
{
memcpy(u1.b, i.u1.b, sizeof(u1.b));
}
std::string toString() const
{
std::string s = {};
int l_i = 0;
int l_j = 0;
while(l_i < MEI_MAX_LENGTH/2) {
if((u1.b[l_i] & 0xf) > 9)
break;
s.append(std::to_string(u1.b[l_i] & 0xf));
l_j++;
if(((u1.b[l_i] & 0xf0) >> 4) > 9)
break;
s.append(std::to_string((u1.b[l_i] & 0xf0) >> 4));
l_j++;
l_i++;
}
return s;
}
mei_s& operator++ () // prefix ++
{
int l_i = MEI_MAX_LENGTH/2 - 1 - 1; // depends if imei or imei_sv -1 again
uint8_t carry = 1;
while(l_i) {
uint8_t b = u1.b[l_i];
uint8_t d0 = b & 0x0f;
uint8_t d1 = b & 0xf0;
if (d0 <= 9) {
d0 += carry;
if (d0 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d0 = 0;
u1.b[l_i] = d0 | d1;
}
}
if (d1 <= 9) {
d1 += carry;
if (d1 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d1 = 0;
u1.b[l_i] = d0 | d1;
}
}
l_i++;
}
return (*this);
}
} ;
typedef struct mei_s mei_t;
//-------------------------------------
// 8.11 MSISDN
typedef struct msisdn_s {
struct msisdn_s {
#define MSISDN_MAX_LENGTH (15)
union {
struct {
......@@ -629,7 +736,73 @@ typedef struct msisdn_s {
uint8_t b[MSISDN_MAX_LENGTH/2+1];
} u1;
uint num_digits;
} msisdn_t;
msisdn_s() : num_digits(0)
{
memset(u1.b, 0, sizeof(u1.b));
}
msisdn_s(const msisdn_s& i) : num_digits(i.num_digits)
{
memcpy(u1.b, i.u1.b, sizeof(u1.b));
}
std::string toString() const
{
std::string s = {};
int l_i = 0;
int l_j = 0;
while(l_i < sizeof(u1.b)) {
if((u1.b[l_i] & 0xf) > 9)
break;
s.append(std::to_string(u1.b[l_i] & 0xf));
l_j++;
if(((u1.b[l_i] & 0xf0) >> 4) > 9)
break;
s.append(std::to_string((u1.b[l_i] & 0xf0) >> 4));
l_j++;
l_i++;
}
return s;
}
// Should be refined see spec
msisdn_s& operator++ () // prefix ++
{
int l_i = sizeof(u1.b) - 1;
uint8_t carry = 1;
while(l_i > 5) {
uint8_t b = u1.b[l_i];
uint8_t d0 = b & 0x0f;
uint8_t d1 = b & 0xf0;
if (d0 <= 9) {
d0 += carry;
if (d0 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d0 = 0;
u1.b[l_i] = d0 | d1;
}
}
if (d1 <= 9) {
d1 += carry;
if (d1 <= 9) {
u1.b[l_i] = d0 | d1;
return(*this);
} else {
d1 = 0;
u1.b[l_i] = d0 | d1;
}
}
l_i++;
}
return (*this);
}
};
typedef struct msisdn_s msisdn_t;
//-------------------------------------
// 8.12 Indication
typedef struct indication_s {
......@@ -833,9 +1006,31 @@ enum rat_type_e {
RAT_TYPE_E_LTE_M = 9,
RAT_TYPE_E_NR = 10,
};
typedef struct rat_type_s {
struct rat_type_s {
uint8_t rat_type;
} rat_type_t;
rat_type_s() : rat_type(RAT_TYPE_E_EUTRAN_WB_EUTRAN) {}
rat_type_s(const rat_type_e r) : rat_type(r) {}
rat_type_s(const rat_type_s& i) : rat_type(i.rat_type) {}
//------------------------------------------------------------------------------
std::string toString() const
{
switch(rat_type) {
case RAT_TYPE_E_EUTRAN_WB_EUTRAN: return std::string("EUTRAN_WB_EUTRAN");
case RAT_TYPE_E_EUTRAN_NB_IOT: return std::string("EUTRAN_NB_IOT");
case RAT_TYPE_E_LTE_M: return std::string("LTE_M");
case RAT_TYPE_E_NR: return std::string("NR");
case RAT_TYPE_E_VIRTUAL: return std::string("VIRTUAL");
case RAT_TYPE_E_RESERVED: return std::string("RESERVED");
case RAT_TYPE_E_UTRAN: return std::string("UTRAN");
case RAT_TYPE_E_GERAN: return std::string("GERAN");
case RAT_TYPE_E_WLAN: return std::string("WLAN");
case RAT_TYPE_E_GAN: return std::string("GAN");
case RAT_TYPE_E_HSPA_EVOLUTION: return std::string("HSPA_EVOLUTION");
default: return std::to_string(rat_type);
}
}
};
typedef struct rat_type_s rat_type_t;
//-------------------------------------
// 8.18 Serving Network
typedef struct serving_network_s {
......@@ -1068,6 +1263,19 @@ struct fully_qualified_tunnel_endpoint_identifier_s {
struct in_addr ipv4_address;
struct in6_addr ipv6_address;
bool operator<(const struct fully_qualified_tunnel_endpoint_identifier_s& f) const
{
return (teid_gre_key < f.teid_gre_key) or
(ipv4_address.s_addr < f.ipv4_address.s_addr) or
(interface_type < f.interface_type) or
(v4 == f.v4) or
(v6 == f.v6) or
(ipv6_address.s6_addr32[0] == f.ipv6_address.s6_addr32[0]) or
(ipv6_address.s6_addr32[1] == f.ipv6_address.s6_addr32[1]) or
(ipv6_address.s6_addr32[2] == f.ipv6_address.s6_addr32[2]) or
(ipv6_address.s6_addr32[3] == f.ipv6_address.s6_addr32[3]);
}
bool operator==(const struct fully_qualified_tunnel_endpoint_identifier_s& f) const
{
return (teid_gre_key == f.teid_gre_key) and
......@@ -1936,4 +2144,29 @@ typedef struct maximum_packet_loss_rate_s {
// 8.135 APN Rate Control Status
// 8.136 Extended Trace Information
namespace std {
template<>
class hash<fteid_t> {
public:
size_t operator()(const fteid_t &k) const
{
using std::size_t;
using std::hash;
std::size_t h1 = std::hash<uint32_t>()(k.interface_type);
std::size_t h2 = std::hash<uint32_t>()(k.teid_gre_key) ^ h1;
if (k.v4) {
h2 ^= std::hash<uint32_t>()(k.ipv4_address.s_addr);
}
if (k.v6) {
h2 ^= std::hash<uint32_t>()(k.ipv6_address.s6_addr32[0]);
h2 ^= std::hash<uint32_t>()(k.ipv6_address.s6_addr32[1]);
h2 ^= std::hash<uint32_t>()(k.ipv6_address.s6_addr32[2]);
h2 ^= std::hash<uint32_t>()(k.ipv6_address.s6_addr32[3]);
}
return h2;
}
};
}
#endif /* FILE_3GPP_29_274_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 endpoint.hpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_ENDPOINT_HPP_SEEN
#define FILE_ENDPOINT_HPP_SEEN
#include "conversions.hpp"
#include <arpa/inet.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <string.h>
class endpoint {
public :
struct sockaddr_storage addr_storage;
socklen_t addr_storage_len;
endpoint() : addr_storage(), addr_storage_len(sizeof(struct sockaddr_storage)) {};
endpoint(const endpoint& e) : addr_storage(e.addr_storage), addr_storage_len(e.addr_storage_len) {};
endpoint(const struct sockaddr_storage& addr, const socklen_t len) : addr_storage(addr), addr_storage_len(len) {};
endpoint(const struct in_addr& addr, const uint16_t port)
{
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
addr_in->sin_family = AF_INET;
addr_in->sin_port = htons(port);
addr_in->sin_addr.s_addr = addr.s_addr;
addr_storage_len = sizeof(struct sockaddr_in);
};
endpoint(const struct in6_addr& addr6, const uint16_t port)
{
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
addr_in6->sin6_family = AF_INET6;
addr_in6->sin6_port = htons(port);
addr_in6->sin6_flowinfo = 0;
memcpy(&addr_in6->sin6_addr, &addr6, sizeof(struct in6_addr));
addr_in6->sin6_scope_id = 0;
addr_storage_len = sizeof(struct sockaddr_in6);
};
uint16_t port() const
{
return ntohs(((struct sockaddr_in *)&addr_storage)->sin_port);
}
sa_family_t family() const
{
return addr_storage.ss_family;
}
std::string toString() const
{
std::string str;
if (addr_storage.ss_family == AF_INET) {
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
str.append(conv::toString(addr_in->sin_addr));
str.append(":").append(std::to_string(ntohs(addr_in->sin_port)));
}
else if (addr_storage.ss_family == AF_INET6) {
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
str.append(conv::toString(addr_in6->sin6_addr));
str.append(":").append(std::to_string(ntohs(addr_in6->sin6_port)));
}
return str;
}
};
#endif
......@@ -30,9 +30,9 @@
#define ITTI_MSG_S11_HPP_INCLUDED_
#include "3gpp_29.274.hpp"
#include "endpoint.hpp"
#include "itti_msg.hpp"
#include "msg_gtpv2c.hpp"
#include <boost/asio/ip/udp.hpp>
class itti_s11_msg : public itti_msg {
public:
......@@ -54,10 +54,10 @@ public:
destination = dest;
}
boost::asio::ip::udp::endpoint l_endpoint;
boost::asio::ip::udp::endpoint r_endpoint;
teid_t teid;
uint64_t gtpc_tx_id;
endpoint l_endpoint;
endpoint r_endpoint;
teid_t teid;
uint64_t gtpc_tx_id;
};
class itti_s11_create_session_request : public itti_s11_msg {
......@@ -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;
......
......@@ -30,9 +30,9 @@
#define ITTI_MSG_S5S8_HPP_INCLUDED_
#include "3gpp_29.274.hpp"
#include "endpoint.hpp"
#include "itti_msg.hpp"
#include "msg_gtpv2c.hpp"
#include <boost/asio/ip/udp.hpp>
class itti_s5s8_msg : public itti_msg {
public:
......@@ -54,10 +54,10 @@ public:
destination = dest;
}
boost::asio::ip::udp::endpoint l_endpoint;
boost::asio::ip::udp::endpoint r_endpoint;
teid_t teid;
uint64_t gtpc_tx_id;
endpoint l_endpoint;
endpoint r_endpoint;
teid_t teid;
uint64_t gtpc_tx_id;
};
class itti_s5s8_create_session_request : public itti_s5s8_msg {
......@@ -327,4 +327,77 @@ public:
gtpv2c::gtpv2c_delete_bearer_command gtp_ies;
} ;
//-----------------------------------------------------------------------------
/** @class itti_s5s8_downlink_data_notification
* @brief Downlink Data Notification, not in spec but necessary due to SGWU and PGWU tied together.
*
* The Downlink Data Notification message is sent on the S5S8 interface by the SGW to the MME as part of the S1 paging procedure.
*/
class itti_s5s8_downlink_data_notification : public itti_s5s8_msg {
public:
itti_s5s8_downlink_data_notification(const task_id_t origin, const task_id_t destination):
itti_s5s8_msg(S5S8_DOWNLINK_DATA_NOTIFICATION, origin, destination) {
}
itti_s5s8_downlink_data_notification(const itti_s5s8_downlink_data_notification& i) : itti_s5s8_msg(i) {
gtp_ies = i.gtp_ies;
}
itti_s5s8_downlink_data_notification(const itti_s5s8_downlink_data_notification& i, const task_id_t orig, const task_id_t dest) :
itti_s5s8_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s5s8_downlink_data_notification).name();};
gtpv2c::gtpv2c_downlink_data_notification gtp_ies;
} ;
//-----------------------------------------------------------------------------
/** @class itti_s5s8_downlink_data_notification_acknowledge
* @brief Downlink Data Notification Acknowledge, not in spec but necessary due to SGWU and PGWU tied together.
*
* The Downlink Data Notification Acknowledge message is sent on the S5S8 interface by the MME to the SGW as part of the S1 paging procedure.
*/
class itti_s5s8_downlink_data_notification_acknowledge : public itti_s5s8_msg {
public:
itti_s5s8_downlink_data_notification_acknowledge(const task_id_t origin, const task_id_t destination):
itti_s5s8_msg(S5S8_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE, origin, destination) {
}
itti_s5s8_downlink_data_notification_acknowledge(const itti_s5s8_downlink_data_notification_acknowledge& i) : itti_s5s8_msg(i) {
gtp_ies = i.gtp_ies;
}
itti_s5s8_downlink_data_notification_acknowledge(const itti_s5s8_downlink_data_notification_acknowledge& i, const task_id_t orig, const task_id_t dest) :
itti_s5s8_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
itti_s5s8_downlink_data_notification_acknowledge(const gtpv2c::gtpv2c_downlink_data_notification_acknowledge& ies, const task_id_t orig, const task_id_t dest) :
itti_s5s8_downlink_data_notification_acknowledge(orig, dest) {
gtp_ies = ies;
}
const char* get_msg_name() {return typeid(itti_s5s8_downlink_data_notification_acknowledge).name();};
gtpv2c::gtpv2c_downlink_data_notification_acknowledge gtp_ies;
} ;
//-----------------------------------------------------------------------------
/** @class itti_s5s8_downlink_data_notification_failure_indication
* @brief Downlink Data Notification Failure Indication, not in spec but necessary due to SGWU and PGWU tied together.
*
*/
class itti_s5s8_downlink_data_notification_failure_indication : public itti_s5s8_msg {
public:
itti_s5s8_downlink_data_notification_failure_indication(const task_id_t origin, const task_id_t destination):
itti_s5s8_msg(S5S8_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION, origin, destination) {
}
itti_s5s8_downlink_data_notification_failure_indication(const itti_s5s8_downlink_data_notification_failure_indication& i) : itti_s5s8_msg(i) {
gtp_ies = i.gtp_ies;
}
itti_s5s8_downlink_data_notification_failure_indication(const itti_s5s8_downlink_data_notification_failure_indication& i, const task_id_t orig, const task_id_t dest) :
itti_s5s8_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s5s8_downlink_data_notification_failure_indication).name();};
gtpv2c::gtpv2c_downlink_data_notification_failure_indication gtp_ies;
} ;
#endif /* ITTI_MSG_S5S8_HPP_INCLUDED_ */
......@@ -29,9 +29,9 @@
#define ITTI_MSG_SXAB_HPP_INCLUDED_
#include "3gpp_29.244.hpp"
#include "endpoint.hpp"
#include "itti_msg.hpp"
#include "msg_pfcp.hpp"
#include <boost/asio/ip/udp.hpp>
class itti_sxab_msg : public itti_msg {
public:
......@@ -53,10 +53,10 @@ public:
destination = dest;
}
boost::asio::ip::udp::endpoint l_endpoint;
boost::asio::ip::udp::endpoint r_endpoint;
seid_t seid;
uint64_t trxn_id;
endpoint l_endpoint;
endpoint r_endpoint;
seid_t seid;
uint64_t trxn_id;
};
//-----------------------------------------------------------------------------
......
......@@ -134,19 +134,20 @@ void xgpp_conv::pfcp_cause_to_core_cause(const pfcp::cause_t& pc, cause_t& c)
c.cause_value = SYSTEM_FAILURE; // ? ...
}
}
//------------------------------------------------------------------------------
bool xgpp_conv::sockaddr_storage_to_gtp_u_peer_address(const struct sockaddr_storage& peer_sockaddr, gtp_u_peer_address_t& peer_address)
bool xgpp_conv::endpoint_to_gtp_u_peer_address(const endpoint& ep, gtp_u_peer_address_t& peer_address)
{
switch (peer_sockaddr.ss_family) {
switch (ep.family()) {
case AF_INET: {
const struct sockaddr_in * const sin = reinterpret_cast<const sockaddr_in* const>(&peer_sockaddr);
const struct sockaddr_in * const sin = reinterpret_cast<const sockaddr_in* const>(&ep.addr_storage);
peer_address.ipv4_address.s_addr = sin->sin_addr.s_addr;
peer_address.is_v4 = true;
return true;
}
break;
case AF_INET6: {
const struct sockaddr_in6 * const sin6 = reinterpret_cast<const sockaddr_in6* const>(&peer_sockaddr);
const struct sockaddr_in6 * const sin6 = reinterpret_cast<const sockaddr_in6* const>(&ep.addr_storage);
peer_address.ipv6_address = sin6->sin6_addr;
peer_address.is_v4 = false;
return true;
......@@ -157,4 +158,3 @@ bool xgpp_conv::sockaddr_storage_to_gtp_u_peer_address(const struct sockaddr_sto
}
}
......@@ -31,6 +31,7 @@
#include "3gpp_29.274.h"
#include "3gpp_29.244.h"
#include "3gpp_29.281.h"
#include "endpoint.hpp"
namespace xgpp_conv {
......@@ -42,8 +43,7 @@ namespace xgpp_conv {
void pfcp_to_core_fteid(const pfcp::fteid_t& pfteid, fteid_t& fteid);
void pfcp_from_core_fteid(pfcp::fteid_t& pfteid, const fteid_t& fteid);
void pfcp_cause_to_core_cause(const pfcp::cause_t& pc, cause_t& c);
bool sockaddr_storage_to_gtp_u_peer_address(const struct sockaddr_storage& peer_sockaddr, gtp_u_peer_address_t& peer_address);
bool endpoint_to_gtp_u_peer_address(const endpoint& ep, gtp_u_peer_address_t& gpa);
}
#endif /* FILE_3GPP_CONVERSIONS_HPP_SEEN */
......@@ -21,6 +21,7 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
......
......@@ -78,17 +78,23 @@ void async_cmd_task (void* args_p)
}
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::async_cmd().info( "TIME-OUT event timer id %d", to->timer_id);
}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::async_cmd().info( "Received terminate message");
return;
}
break;
case HEALTH_PING:
break;
default:
Logger::sgwc_app().info( "no handler for msg type %d", msg->msg_type);
}
......
......@@ -167,3 +167,5 @@ std::string conv::toString(const struct in6_addr& in6addr)
}
return s;
}
......@@ -32,6 +32,7 @@
#include <string>
#include <netinet/in.h>
/* Used to format an uint32_t containing an ipv4 address */
#define IN_ADDR_FMT "%u.%u.%u.%u"
#define PRI_IN_ADDR(aDDRESS) \
......
......@@ -34,7 +34,8 @@
namespace util {
class thread_sched_params {
public:
public:
thread_sched_params() : cpu_id(0), sched_policy(SCHED_FIFO), sched_priority(84) {}
int cpu_id;
int sched_policy;
int sched_priority;
......
......@@ -28,4 +28,5 @@ include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/gtpv1u)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
......@@ -38,134 +38,7 @@ using namespace std;
extern itti_mw *itti_inst;
//------------------------------------------------------------------------------
static std::string string_to_hex(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
//------------------------------------------------------------------------------
void udp_server::udp_read_loop(const util::thread_sched_params& sched_params)
{
socklen_t r_endpoint_addr_len = 0;
struct sockaddr_storage r_endpoint = {};
size_t bytes_received = 0;
sched_params.apply(TASK_NONE, Logger::udp());
while (1) {
r_endpoint_addr_len = sizeof(struct sockaddr_storage);
if ((bytes_received = recvfrom (socket_, recv_buffer_, UDP_RECV_BUFFER_SIZE, 0, (struct sockaddr *)&r_endpoint, &r_endpoint_addr_len)) > 0) {
app_->handle_receive(recv_buffer_, bytes_received, r_endpoint, r_endpoint_addr_len);
} else {
Logger::udp().error( "Recvfrom failed %s\n", strerror (errno));
}
}
}
//------------------------------------------------------------------------------
int udp_server::create_socket (const struct in_addr &address, const uint16_t port)
{
struct sockaddr_in addr = {};
int sd = 0;
/*
* Create UDP socket
*/
if ((sd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
/*
* Socket creation has failed...
*/
Logger::udp().error( "Socket creation failed (%s)\n", strerror (errno));
return errno;
}
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = address.s_addr;
std::string ipv4 = conv::toString(address);
Logger::udp().debug("Creating new listen socket on address %s and port %" PRIu16 "\n", ipv4.c_str(), port);
if (bind (sd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in)) < 0) {
/*
* Bind failed
*/
Logger::udp().error("Socket bind failed (%s) for address %s and port %" PRIu16 "\n", strerror (errno), ipv4.c_str(), port);
close (sd);
return errno;
}
return sd;
}
//------------------------------------------------------------------------------
int udp_server::create_socket (const struct in6_addr &address, const uint16_t port)
{
struct sockaddr_in6 addr = {};
int sd = 0;
/*
* Create UDP socket
*/
if ((sd = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
/*
* Socket creation has failed...
*/
Logger::udp().error( "Socket creation failed (%s)\n", strerror (errno));
return errno;
}
addr.sin6_family = AF_INET6;
addr.sin6_port = htons (port);
addr.sin6_addr = address;
std::string ipv6 = conv::toString(address);
Logger::udp().debug("Creating new listen socket on address %s and port %" PRIu16 "\n", ipv6.c_str(), port);
if (bind (sd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in6)) < 0) {
/*
* Bind failed
*/
Logger::udp().error("Socket bind failed (%s) for address %s and port %" PRIu16 "\n", strerror (errno), ipv6.c_str(), port);
close (sd);
return errno;
}
return sd;
}
//------------------------------------------------------------------------------
int udp_server::create_socket (char * address, const uint16_t port_num)
{
unsigned char buf_in_addr[sizeof(struct in6_addr)];
if (inet_pton (AF_INET, address, buf_in_addr) == 1) {
struct in_addr addr4 = {};
memcpy (&addr4, buf_in_addr, sizeof (struct in_addr));
return create_socket(addr4, port_num);
} else if (inet_pton (AF_INET6, address, buf_in_addr) == 1) {
struct in6_addr addr6 = {};
memcpy (&addr6, buf_in_addr, sizeof (struct in6_addr));
return create_socket(addr6, port_num);
} else {
Logger::udp().error( "udp_server::create_socket(%s:%d)", address, port_num);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
throw std::system_error(socket_, std::generic_category(), "UDP socket creation failed!");
}
}
//------------------------------------------------------------------------------
void udp_server::start_receive(gtpu_l4_stack * gtp_stack, const util::thread_sched_params& sched_params)
{
app_ = gtp_stack;
Logger::udp().trace( "udp_server::start_receive");
thread_ = thread(&udp_server::udp_read_loop,this, sched_params);
thread_.detach();
}
////------------------------------------------------------------------------------
//void udp_server::handle_receive(const int& error, std::size_t bytes_transferred)
......@@ -232,7 +105,7 @@ uint32_t gtpu_l4_stack::get_next_seq_num() {
return seq_num;
}
//------------------------------------------------------------------------------
void gtpu_l4_stack::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len)
void gtpu_l4_stack::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint)
{
Logger::gtpv1_u().error( "TODO implement in derived class");
}
......@@ -315,20 +188,8 @@ void gtpu_l4_stack::send_response(const gtpv1u_echo_response& gtp_ies)
}
msg.dump_to(oss);
std::string bstream = oss.str();
switch (gtp_ies.r_endpoint.ss_family) {
case AF_INET: {
const struct sockaddr_in * const sin = reinterpret_cast<const sockaddr_in* const>(&gtp_ies.r_endpoint);
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), *sin);
}
break;
case AF_INET6: {
const struct sockaddr_in6 * const sin6 = reinterpret_cast<const sockaddr_in6* const>(&gtp_ies.r_endpoint);
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), *sin6);
}
break;
default:
Logger::gtpv1_u().debug( "gtpu_l4_stack::send_response %s, no known peer addr", gtp_ies.get_msg_name());
}
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), gtp_ies.r_endpoint);
}
//------------------------------------------------------------------------------
void gtpu_l4_stack::send_indication(const gtpv1u_error_indication& gtp_ies)
......@@ -345,18 +206,6 @@ void gtpu_l4_stack::send_indication(const gtpv1u_error_indication& gtp_ies)
}
msg.dump_to(oss);
std::string bstream = oss.str();
switch (gtp_ies.r_endpoint.ss_family) {
case AF_INET: {
const struct sockaddr_in * const sin = reinterpret_cast<const sockaddr_in* const>(&gtp_ies.r_endpoint);
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), *sin);
}
break;
case AF_INET6: {
const struct sockaddr_in6 * const sin6 = reinterpret_cast<const sockaddr_in6* const>(&gtp_ies.r_endpoint);
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), *sin6);
}
break;
default:
Logger::gtpv1_u().debug( "gtpu_l4_stack::send_indication %s, no known peer addr", gtp_ies.get_msg_name());
}
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), gtp_ies.r_endpoint);
}
......@@ -32,6 +32,7 @@
#include "itti.hpp"
#include "msg_gtpv1u.hpp"
#include "thread_sched.hpp"
#include "udp.hpp"
#include <iostream>
#include <map>
......@@ -45,101 +46,10 @@
namespace gtpv1u {
class gtpu_l4_stack;
static const uint16_t default_port = 2152;
class udp_server
{
public:
udp_server(const struct in_addr& address, const uint16_t port_num)
: app_(nullptr), port_(port_num)
{
socket_ = create_socket (address, port_);
if (socket_ > 0) {
Logger::udp().debug( "udp_server::udp_server(%s:%d)", conv::toString(address).c_str(), port_);
} else {
Logger::udp().error( "udp_server::udp_server(%s:%d)", conv::toString(address).c_str(), port_);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
throw std::system_error(socket_, std::generic_category(), "GTPV1-U socket creation failed!");
}
}
udp_server(const struct in6_addr& address, const uint16_t port_num)
: app_(nullptr), port_(port_num)
{
socket_ = create_socket (address, port_);
if (socket_ > 0) {
Logger::udp().debug( "udp_server::udp_server(%s:%d)", conv::toString(address).c_str(), port_);
} else {
Logger::udp().error( "udp_server::udp_server(%s:%d)", conv::toString(address).c_str(), port_);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
throw std::system_error(socket_, std::generic_category(), "GTPV1-U socket creation failed!");
}
}
udp_server(char * address, const uint16_t port_num)
: app_(nullptr), port_(port_num)
{
socket_ = create_socket (address, port_);
if (socket_ > 0) {
Logger::udp().debug( "udp_server::udp_server(%s:%d)", address, port_);
} else {
Logger::udp().error( "udp_server::udp_server(%s:%d)", address, port_);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
throw std::system_error(socket_, std::generic_category(), "GTPV1-U socket creation failed!");
}
}
~udp_server()
{
close(socket_);
}
void udp_read_loop(const util::thread_sched_params& thread_sched_params);
void async_send_to(const char* send_buffer, const ssize_t num_bytes, const struct sockaddr_in& peer_addr)
{
//Logger::udp().trace( "udp_server::async_send_to(%s:%d) %d bytes", toString(peer_addr.sin_addr).c_str(), peer_addr.sin_port, num_bytes);
ssize_t bytes_written = sendto (socket_, send_buffer, num_bytes, 0, (struct sockaddr *)&peer_addr, sizeof (struct sockaddr_in));
if (bytes_written != num_bytes) {
Logger::udp().error( "sendto failed(%d:%s)\n", errno, strerror (errno));
}
}
void async_send_to(const char* send_buffer, const ssize_t num_bytes, const struct sockaddr_in6& peer_addr)
{
ssize_t bytes_written = sendto (socket_, send_buffer, num_bytes, 0, (struct sockaddr *)&peer_addr, sizeof (struct sockaddr_in6));
if (bytes_written != num_bytes) {
Logger::udp().error( "sendto failed(%d:%s)\n", errno, strerror (errno));
}
}
void start_receive(gtpu_l4_stack * gtp_stack, const util::thread_sched_params& sched_params);
protected:
int create_socket (const struct in_addr& address, const uint16_t port);
int create_socket (const struct in6_addr& address, const uint16_t port);
int create_socket (char * address, const uint16_t port_num);
// void handle_receive(const int& error, std::size_t bytes_transferred);
static void handle_send(const char *, /*buffer*/
const int& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
gtpu_l4_stack* app_;
std::thread thread_;
int socket_;
uint16_t port_;
#define UDP_RECV_BUFFER_SIZE 8192
char recv_buffer_[UDP_RECV_BUFFER_SIZE];
};
class gtpu_l4_stack {
class gtpu_l4_stack : public udp_application {
#define GTPV1U_T3_RESPONSE_MS 1000
#define GTPV1U_N3_REQUESTS 5
#define GTPV1U_PROC_TIME_OUT_MS ((GTPV1U_T3_RESPONSE_MS) * (GTPV1U_N3_REQUESTS + 1))
......@@ -162,7 +72,7 @@ public:
gtpu_l4_stack(const struct in_addr& address, const uint16_t port_num, const util::thread_sched_params& sched_params);
gtpu_l4_stack(const struct in6_addr& address, const uint16_t port_num, const util::thread_sched_params& sched_params);
gtpu_l4_stack(char * ip_address, const uint16_t port_num, const util::thread_sched_params& sched_params);
virtual void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len);
virtual void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint);
void handle_receive_message_cb(const gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len, const task_id_t& task_id, bool &error, uint64_t& gtpc_tx_id);
void send_g_pdu(const struct sockaddr_in& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len);
......
......@@ -32,6 +32,7 @@
#include "3gpp_29.274.h"
#include "3gpp_29.281.h"
#include "endpoint.hpp"
#include "common_defs.h"
#include <utility>
......@@ -43,16 +44,14 @@ namespace gtpv1u {
class gtpv1u_ies_container {
public:
static const uint8_t msg_id = 0;
struct sockaddr_storage r_endpoint;
socklen_t r_endpoint_addr_len;
endpoint r_endpoint;
std::pair<bool, uint32_t> teid;
std::pair<bool, uint16_t> sequence_number;
std::pair<bool, uint8_t> npdu_number;
gtpv1u_ies_container() : r_endpoint(), r_endpoint_addr_len(0), teid(), sequence_number(), npdu_number() {}
gtpv1u_ies_container() : r_endpoint(), teid(), sequence_number(), npdu_number() {}
gtpv1u_ies_container(const gtpv1u_ies_container& i) :
r_endpoint(i.r_endpoint),
r_endpoint_addr_len(i.r_endpoint_addr_len),
teid(i.teid),
sequence_number(i.sequence_number),
npdu_number(i.npdu_number) {}
......@@ -60,7 +59,6 @@ public:
gtpv1u_ies_container& operator=(gtpv1u_ies_container other)
{
std::swap(r_endpoint, other.r_endpoint);
std::swap(r_endpoint_addr_len, other.r_endpoint_addr_len);
std::swap(teid, other.teid);
std::swap(sequence_number, other.sequence_number);
std::swap(npdu_number, other.npdu_number);
......
......@@ -834,6 +834,27 @@ gtpv2c_msg::gtpv2c_msg(const gtpv2c_release_access_bearers_response& gtp_ies) :
//if (gtp_ies.first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
//if (gtp_ies.first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_downlink_data_notification& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_DOWNLINK_DATA_NOTIFICATION);
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(gtp_ies.eps_bearer_id)); add_ie(sie);}
// TODO if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_ARP) {std::shared_ptr<gtpv2c_arp_ie> sie(new gtpv2c_arp_ie(gtp_ies.arp)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_IMSI) {std::shared_ptr<gtpv2c_imsi_ie> sie(new gtpv2c_imsi_ie(gtp_ies.imsi)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_SENDER_FTEID_FOR_CP) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.sender_fteid_for_cp)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_PR_IE_INDICATION_FLAGS) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_downlink_data_notification_acknowledge& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE);
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_IMSI) {std::shared_ptr<gtpv2c_imsi_ie> sie(new gtpv2c_imsi_ie(gtp_ies.imsi)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_echo_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
......
......@@ -354,6 +354,8 @@ public:
explicit gtpv2c_msg(const gtpv2c_modify_bearer_response& gtp_ies);
explicit gtpv2c_msg(const gtpv2c_release_access_bearers_request& gtp_ies);
explicit gtpv2c_msg(const gtpv2c_release_access_bearers_response& gtp_ies);
explicit gtpv2c_msg(const gtpv2c_downlink_data_notification& gtp_ies);
explicit gtpv2c_msg(const gtpv2c_downlink_data_notification_acknowledge& gtp_ies);
~gtpv2c_msg() {
ies.clear();
......
......@@ -23,10 +23,11 @@ add_library(GTPV2C STATIC
gtpv2c.cpp
)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/oai_spgw_c)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
This diff is collapsed.
......@@ -29,14 +29,11 @@
#define FILE_GTPV2C_HPP_SEEN
#include "3gpp_29.274.hpp"
#include "endpoint.hpp"
#include "itti.hpp"
#include "udp.hpp"
#include "uint_generator.hpp"
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <map>
#include <memory>
......@@ -47,12 +44,14 @@
namespace gtpv2c {
static const uint16_t default_port = 2123;
class gtpv2c_procedure {
public:
std::shared_ptr<gtpv2c_msg> retry_msg;
boost::asio::ip::udp::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
......@@ -83,81 +82,32 @@ public:
retry_count(p.retry_count) {}
};
class gtpv2c_stack;
class udp_server
{
public:
udp_server(boost::asio::io_service& io_service, boost::asio::ip::address address, const unsigned short port_num)
: app(nullptr), local_address_(address), socket_(io_service, boost::asio::ip::udp::endpoint(address, port_num))
{
boost::asio::socket_base::reuse_address option(true);
socket_.set_option(option);
Logger::udp().debug( "udp_server::udp_server(%s:%d) for GTPv2-C", address.to_string().c_str(), port_num);
}
void async_send_to(boost::shared_ptr<std::string> message, boost::asio::ip::udp::endpoint remote_endpoint)
{
Logger::udp().trace( "udp_server::async_send_to(%s:%d) %d bytes", remote_endpoint.address().to_string().c_str(), remote_endpoint.port(), message.get()->size());
socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint,
boost::bind(&udp_server::handle_send, this, message,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void start_receive(gtpv2c_stack * gtp_stack)
{
app = gtp_stack;
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
protected:
void handle_receive(const boost::system::error_code& error, std::size_t bytes_transferred);
void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
gtpv2c_stack* app;
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint remote_endpoint_;
boost::asio::ip::address local_address_;
boost::array<char, 4096> recv_buffer_;
};
enum gtpv2c_transaction_action {
DELETE_TX = 0,
CONTINUE_TX
};
class gtpv2c_stack {
class gtpv2c_stack : public udp_application {
#define GTPV2C_T3_RESPONSE_MS 1000
#define GTPV2C_N3_REQUESTS 3
#define GTPV2C_PROC_TIME_OUT_MS ((GTPV2C_T3_RESPONSE_MS) * (GTPV2C_N3_REQUESTS + 1) + 1000)
protected:
uint32_t id;
udp_server udp_s;
udp_server udp_s_allocated;
uint32_t id;
udp_server udp_s;
udp_server udp_s_allocated;
// seems no need for std::atomic_uint32_t
uint32_t seq_num;
uint32_t restart_counter;
// 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;
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 , gtpv2c_procedure> pending_procedures;
std::map<uint64_t, uint32_t> gtpc_tx_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 , gtpv2c_procedure> pending_procedures;
boost::array<char, 4096> send_buffer;
static const char* msg_type2cstr[256];
uint32_t get_next_seq_num();
......@@ -177,26 +127,31 @@ protected:
public:
static const uint8_t version = 2;
gtpv2c_stack(const std::string& ip_address, const unsigned short port_num);
virtual void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_message_cb(const gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint, const task_id_t& task_id, bool& error, uint64_t& gtpc_tx_id);
gtpv2c_stack(const std::string& ip_address, const unsigned short port_num, const util::thread_sched_params& sched_param);
virtual void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint);
void handle_receive_message_cb(const gtpv2c_msg& msg, const endpoint& r_endpoint, const task_id_t& task_id, bool& error, uint64_t& gtpc_tx_id);
// Path mangement messages
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const gtpv2c_echo_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const endpoint& r_endpoint, const gtpv2c_echo_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
// Tunnel management messages
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_release_access_bearers_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, 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);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_create_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_delete_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_modify_bearer_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_release_access_bearers_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_downlink_data_notification& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_create_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_delete_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_modify_bearer_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
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);
virtual void send_triggered_message(const endpoint& r_endpoint, const teid_t teid, const gtpv2c_downlink_data_notification_acknowledge& 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
......
......@@ -2562,6 +2562,7 @@ public:
void set(const serving_network_t& v, const uint8_t instance = 0) {serving_network = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SERVING_NETWORK;}
void set(const rat_type_t& v, const uint8_t instance = 0) {rat_type = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_RAT_TYPE;}
void set(const indication_t& v, const uint8_t instance = 0) {indication_flags = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_INDICATION_FLAGS;}
void set(const fteid_t& v, const uint8_t instance = 0) {sender_fteid_for_cp = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SENDER_FTEID_FOR_CONTROL_PLANE;}
void set_sender_fteid_for_cp(const fteid_t& v) {sender_fteid_for_cp = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SENDER_FTEID_FOR_CONTROL_PLANE;}
void set(const ambr_t& v, const uint8_t instance = 0) {apn_ambr = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_APN_AMBR;}
void set(const delay_value_t& v, const uint8_t instance = 0) {delay_dl_packet_notif_req = v;ie_presence_mask |= GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_DELAY_DOWNLINK_PACKET_NOTIFICATION_REQUEST;}
......@@ -3517,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;}
};
//-----------------------------------------------------------------------------
......@@ -3567,6 +3575,9 @@ public:
// Private Extension ///< optional
void set(const cause_t& v, const uint8_t instance = 0) {cause = v;ie_presence_mask |= DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_CAUSE;}
void set(const imsi_t& v, const uint8_t instance = 0) {imsi = v;ie_presence_mask |= DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_IMSI;}
bool get(cause_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_CAUSE) {v = cause;return true;}return false;}
bool get(imsi_t& v, const uint8_t instance = 0) const {if (ie_presence_mask & DOWNLINK_DATA_NOTIFICATION_ACK_PR_IE_IMSI) {v = imsi;return true;}return false;}
} ;
......
......@@ -106,6 +106,9 @@ typedef enum {
S5S8_DELETE_SESSION_RESPONSE,
S5S8_RELEASE_ACCESS_BEARERS_REQUEST,
S5S8_RELEASE_ACCESS_BEARERS_RESPONSE,
S5S8_DOWNLINK_DATA_NOTIFICATION,
S5S8_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE,
S5S8_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION,
SXAB_HEARTBEAT_REQUEST,
SXAB_HEARTBEAT_RESPONSE,
SXAB_PFCP_PFD_MANAGEMENT_REQUEST,
......
......@@ -269,6 +269,7 @@ ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/common ${CMAKE_CURRENT_BI
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/common/utils ${CMAKE_CURRENT_BINARY_DIR}/utils)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv2c ${CMAKE_CURRENT_BINARY_DIR}/gtpv2c)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pfcp ${CMAKE_CURRENT_BINARY_DIR}/pfcp)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/udp ${CMAKE_CURRENT_BINARY_DIR}/udp)
if(${SGW_AUTOTEST})
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv1u ${CMAKE_CURRENT_BINARY_DIR}/gtpv1u)
endif(${SGW_AUTOTEST})
......@@ -290,6 +291,7 @@ include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/sgwc)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_executable(spgwc
......@@ -310,5 +312,5 @@ if(${SGW_AUTOTEST})
SET(GTPV1U_LIB GTPV1U)
endif(${SGW_AUTOTEST})
target_link_libraries (spgwc ${ASAN} -Wl,--start-group CN_UTILS SGWC PGWC ${GTPV1U_LIB} GTPV2C PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group pthread m rt config++ event boost_system )
target_link_libraries (spgwc ${ASAN} -Wl,--start-group CN_UTILS SGWC PGWC UDP ${GTPV1U_LIB} GTPV2C PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group pthread m rt config++ event boost_system )
......@@ -25,11 +25,11 @@
#include "sgwc_app.hpp"
#include "sgwc_config.hpp"
#include <boost/asio.hpp>
#include <iostream>
#include <thread>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h> // srand
#include <unistd.h> // get_pid(), pause()
using namespace gtpv2c;
......@@ -44,7 +44,6 @@ pgw_app *pgw_app_inst = nullptr;
sgwc_app *sgwc_app_inst = nullptr;
pgw_config pgw_cfg;
sgwc_config sgwc_cfg;
boost::asio::io_service io_service;
//------------------------------------------------------------------------------
void my_app_signal_handler(int s){
......@@ -67,6 +66,7 @@ void my_app_signal_handler(int s){
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
srand (time(NULL));
// Logger
Logger::init( "spgwc" );
......@@ -119,9 +119,6 @@ int main(int argc, char **argv)
fflush(fp);
fclose(fp);
// once all udp servers initialized
io_service.run();
pause();
return 0;
}
......@@ -270,7 +270,7 @@ ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/common/utils ${CMAKE_CURR
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pfcp ${CMAKE_CURRENT_BINARY_DIR}/pfcp)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/spgwu/simpleswitch ${CMAKE_CURRENT_BINARY_DIR}/simpleswitch)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv1u ${CMAKE_CURRENT_BINARY_DIR}/gtpv1u)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv2c ${CMAKE_CURRENT_BINARY_DIR}/gtpv2c)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/udp ${CMAKE_CURRENT_BINARY_DIR}/udp)
################################################################################
......@@ -287,6 +287,7 @@ include_directories(${SRC_TOP_DIR}/gtpv1u)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/spgwu)
include_directories(${SRC_TOP_DIR}/spgwu/simpleswitch)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_executable(spgwu
......@@ -305,6 +306,6 @@ ENDIF(STATIC_LINKING)
# folly glog dl double-conversion for FB folly library
target_link_libraries (spgwu ${ASAN} -Wl,--start-group CN_UTILS SPGWU SPGW_SWITCH GTPV2C GTPV1U PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group
target_link_libraries (spgwu ${ASAN} -Wl,--start-group CN_UTILS SPGWU SPGW_SWITCH UDP GTPV1U PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group
pthread m rt config++ event boost_system)
......@@ -267,12 +267,12 @@ pfcp_ie * pfcp_ie::new_pfcp_ie_from_stream(std::istream& is) {
// return ie;
// }
// break;
// case PFCP_IE_REPORT_TYPE: {
// pfcp_report_type_ie *ie = new pfcp_report_type_ie(tlv);
// ie->load_from(is);
// return ie;
// }
// break;
case PFCP_IE_REPORT_TYPE: {
pfcp_report_type_ie *ie = new pfcp_report_type_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case PFCP_IE_OFFENDING_IE: {
pfcp_offending_ie_ie *ie = new pfcp_offending_ie_ie(tlv);
ie->load_from(is);
......@@ -531,12 +531,12 @@ pfcp_ie * pfcp_ie::new_pfcp_ie_from_stream(std::istream& is) {
// return ie;
// }
// break;
// case PFCP_IE_DOWNLINK_DATA_REPORT: {
// pfcp_downlink_data_report_ie *ie = new pfcp_downlink_data_report_ie(tlv);
// ie->load_from(is);
// return ie;
// }
// break;
case PFCP_IE_DOWNLINK_DATA_REPORT: {
pfcp_downlink_data_report_ie *ie = new pfcp_downlink_data_report_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case PFCP_IE_OUTER_HEADER_CREATION: {
pfcp_outer_header_creation_ie *ie = new pfcp_outer_header_creation_ie(tlv);
ie->load_from(is);
......@@ -970,11 +970,11 @@ pfcp_ie * pfcp_ie::new_pfcp_ie_from_stream(std::istream& is) {
// }
// break;
default:
Logger::pfcp().error("Unknown GTP IE type %d (length %d)", tlv.get_type(), tlv.get_length());
Logger::pfcp().error("Unknown PFCP IE type %d (length %d)", tlv.get_type(), tlv.get_length());
return nullptr;
}
} else {
Logger::pfcp().error("GTP IE type %d length %d", tlv.get_type(), tlv.get_length());
Logger::pfcp().error("PFCP IE type %d length %d", tlv.get_type(), tlv.get_length());
return nullptr;
}
}
......@@ -1027,6 +1027,23 @@ pfcp_msg::pfcp_msg(const pfcp_association_release_response& pfcp_ies) : pfcp_msg
if (pfcp_ies.cause.first) {std::shared_ptr<pfcp_cause_ie> sie(new pfcp_cause_ie(pfcp_ies.cause.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
pfcp_msg::pfcp_msg(const pfcp_node_report_request& pfcp_ies) : pfcp_msg_header() {
ies = {};
set_message_type(PFCP_NODE_REPORT_REQUEST);
std::pair<bool, pfcp::node_id_t> node_id;
std::pair<bool, pfcp::node_report_type_t> node_report_type;
// TODO LATER std::pair<bool, pfcp::user_plane_path_failure_report> user_plane_path_failure_report;
if (pfcp_ies.node_id.first) {std::shared_ptr<pfcp_node_id_ie> sie(new pfcp_node_id_ie(pfcp_ies.node_id.second)); add_ie(sie);}
if (pfcp_ies.node_report_type.first) {std::shared_ptr<pfcp_node_report_type_ie> sie(new pfcp_node_report_type_ie(pfcp_ies.node_report_type.second)); add_ie(sie);}
// TODO LATER if (pfcp_ies.user_plane_path_failure_report.first) {
// std::shared_ptr<pfcp_user_plane_path_failure_report_ie>
// sie(new pfcp_user_plane_path_failure_report_ie(pfcp_ies.user_plane_path_failure_report.second));
// add_ie(sie);
//}
}
//------------------------------------------------------------------------------
pfcp_msg::pfcp_msg(const pfcp_session_establishment_request& pfcp_ies) : pfcp_msg_header() {
ies = {};
set_message_type(PFCP_SESSION_ESTABLISHMENT_REQUEST);
......@@ -1188,7 +1205,26 @@ pfcp_msg::pfcp_msg(const pfcp_session_deletion_response& pfcp_ies) : pfcp_msg_he
//if (pfcp_ies.overload_control_information.first) {std::shared_ptr<pfcp_overload_control_information_ie> sie(new pfcp_overload_control_information_ie(pfcp_ies.overload_control_information.second)); add_ie(sie);}
//if (pfcp_ies.usage_report_information.first) {std::shared_ptr<pfcp_usage_report_within_session_deletion_response_ie> sie(new pfcp_usage_report_within_session_deletion_response_ie(pfcp_ies.additional_usage_reports_information.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
pfcp_msg::pfcp_msg(const pfcp_session_report_request& pfcp_ies) : pfcp_msg_header() {
ies = {};
set_message_type(PFCP_SESSION_REPORT_REQUEST);
if (pfcp_ies.report_type.first) {std::shared_ptr<pfcp_report_type_ie> sie(new pfcp_report_type_ie(pfcp_ies.report_type.second)); add_ie(sie);}
if (pfcp_ies.downlink_data_report.first) {std::shared_ptr<pfcp_downlink_data_report_ie> sie(new pfcp_downlink_data_report_ie(pfcp_ies.downlink_data_report.second)); add_ie(sie);}
//TODO std::pair<bool, pfcp::usage_report_within_pfcp_session_report_request> usage_report;
//TODO std::pair<bool, pfcp::error_indication_report> error_indication_report;
//TODO std::pair<bool, pfcp::load_control_information> load_control_information;
//TODO std::pair<bool, pfcp::overload_control_information> overload_control_information;
//TODO std::pair<bool, pfcp::additional_usage_reports_information_t> additional_usage_reports_information;
}
//------------------------------------------------------------------------------
pfcp_msg::pfcp_msg(const pfcp_session_report_response& pfcp_ies) : pfcp_msg_header() {
ies = {};
set_message_type(PFCP_SESSION_REPORT_RESPONSE);
if (pfcp_ies.cause.first) {std::shared_ptr<pfcp_cause_ie> sie(new pfcp_cause_ie(pfcp_ies.cause.second)); add_ie(sie);}
if (pfcp_ies.offending_ie.first) {std::shared_ptr<pfcp_offending_ie_ie> sie(new pfcp_offending_ie_ie(pfcp_ies.offending_ie.second)); add_ie(sie);}
// TODO if (pfcp_ies.update_bar.first) {std::shared_ptr<pfcp_update_bar_within_pfcp_session_report_response_ie> sie(new pfcp_update_bar_within_pfcp_session_report_response_ie(pfcp_ies.update_bar.second)); add_ie(sie);}
// TODO SPEC std::pair<bool, pfcp::sxsrrsp_flags_t> sxsrrsp_flags;
}
......@@ -333,7 +333,7 @@ public:
explicit pfcp_msg(const pfcp_association_release_request& pfcp_ies);
explicit pfcp_msg(const pfcp_association_release_response& pfcp_ies);
// pfcp_msg(const pfcp_version_not_supported_response& pfcp_ies);
// pfcp_msg(const pfcp_node_report_request& pfcp_ies);
pfcp_msg(const pfcp_node_report_request& pfcp_ies);
// pfcp_msg(const pfcp_node_report_response& pfcp_ies);
explicit pfcp_msg(const pfcp_session_establishment_request& pfcp_ies);
explicit pfcp_msg(const pfcp_session_establishment_response& pfcp_ies);
......@@ -341,8 +341,8 @@ public:
explicit pfcp_msg(const pfcp_session_modification_response& pfcp_ies);
explicit pfcp_msg(const pfcp_session_deletion_request& pfcp_ies);
explicit pfcp_msg(const pfcp_session_deletion_response& pfcp_ies);
// pfcp_msg(const pfcp_session_report_request& pfcp_ies);
// pfcp_msg(const pfcp_session_report_response& pfcp_ies);
explicit pfcp_msg(const pfcp_session_report_request& pfcp_ies);
explicit pfcp_msg(const pfcp_session_report_response& pfcp_ies);
~pfcp_msg() {
ies.clear();
......@@ -1898,50 +1898,66 @@ public:
// s.set(redirect_information);
// }
//};
////-------------------------------------
//// IE REPORT_TYPE
//class pfcp_report_type_ie : public pfcp_ie {
//public:
// uint8_t todo;
//
// //--------
// pfcp_report_type_ie(const pfcp::report_type_t& b) : pfcp_ie(PFCP_IE_REPORT_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_report_type_ie() : pfcp_ie(PFCP_IE_REPORT_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_report_type_ie(const pfcp_tlv& t) : pfcp_ie(t) {
// todo = 0;
// };
// //--------
// void to_core_type(pfcp::report_type_t& b) {
// b.todo = todo;
// }
// //--------
// void dump_to(std::ostream& os) {
// tlv.dump_to(os);
// os.write(reinterpret_cast<const char*>(&todo), sizeof(todo));
// }
// //--------
// void load_from(std::istream& is) {
// //tlv.load_from(is);
// if (tlv.get_length() != 1) {
// throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(), __FILE__, __LINE__);
// }
// is.read(reinterpret_cast<char*>(&todo), sizeof(todo));
// }
// //--------
// void to_core_type(pfcp_ies_container& s) {
// pfcp::report_type_t report_type = {};
// to_core_type(report_type);
// s.set(report_type);
// }
//};
//-------------------------------------
// IE REPORT_TYPE
class pfcp_report_type_ie : public pfcp_ie {
public:
union {
struct {
uint8_t dldr :1;
uint8_t usar :1;
uint8_t erir :1;
uint8_t upir :1;
uint8_t spare :4;
} bf;
uint8_t b;
} u1;
//--------
pfcp_report_type_ie(const pfcp::report_type_t& b) : pfcp_ie(PFCP_IE_REPORT_TYPE){
u1.b = 0;
u1.bf.dldr = b.dldr;
u1.bf.usar = b.usar;
u1.bf.erir = b.erir;
u1.bf.upir = b.upir;
tlv.set_length(1);
}
//--------
pfcp_report_type_ie() : pfcp_ie(PFCP_IE_REPORT_TYPE){
u1.b = 0;
tlv.set_length(1);
}
//--------
pfcp_report_type_ie(const pfcp_tlv& t) : pfcp_ie(t) {
u1.b = 0;
};
//--------
void to_core_type(pfcp::report_type_t& b) {
b.dldr = u1.bf.dldr;
b.usar = u1.bf.usar;
b.erir = u1.bf.erir;
b.upir = u1.bf.upir;
}
//--------
void dump_to(std::ostream& os) {
tlv.dump_to(os);
os.write(reinterpret_cast<const char*>(&u1.b), sizeof(u1.b));
}
//--------
void load_from(std::istream& is) {
//tlv.load_from(is);
if (tlv.get_length() != 1) {
throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(), __FILE__, __LINE__);
}
is.read(reinterpret_cast<char*>(&u1.b), sizeof(u1.b));
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::report_type_t report_type = {};
to_core_type(report_type);
s.set(report_type);
}
};
//-------------------------------------
// IE OFFENDING_IE
class pfcp_offending_ie_ie : public pfcp_ie {
......@@ -4065,49 +4081,34 @@ public:
// }
//};
////-------------------------------------
//// IE DOWNLINK_DATA_REPORT
//class pfcp_downlink_data_report_ie : public pfcp_ie {
//public:
// uint8_t todo;
//
// //--------
// pfcp_downlink_data_report_ie(const pfcp::downlink_data_report& b) : pfcp_ie(PFCP_IE_DOWNLINK_DATA_REPORT){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_downlink_data_report_ie() : pfcp_ie(PFCP_IE_DOWNLINK_DATA_REPORT){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_downlink_data_report_ie(const pfcp_tlv& t) : pfcp_ie(t) {
// todo = 0;
// };
// //--------
// void to_core_type(pfcp::downlink_data_report& b) {
// b.todo = todo;
// }
// //--------
// void dump_to(std::ostream& os) {
// tlv.dump_to(os);
// os.write(reinterpret_cast<const char*>(&todo), sizeof(todo));
// }
// //--------
// void load_from(std::istream& is) {
// //tlv.load_from(is);
// if (tlv.get_length() != 1) {
// throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(), __FILE__, __LINE__);
// }
// is.read(reinterpret_cast<char*>(&todo), sizeof(todo));
// }
// //--------
// void to_core_type(pfcp_ies_container& s) {
// pfcp::downlink_data_report downlink_data_report = {};
// to_core_type(downlink_data_report);
// s.set(downlink_data_report);
// }
//};
// IE DOWNLINK_DATA_REPORT
class pfcp_downlink_data_report_ie : public pfcp_grouped_ie {
public:
//--------
pfcp_downlink_data_report_ie(const pfcp::downlink_data_report& b) : pfcp_grouped_ie(PFCP_IE_DOWNLINK_DATA_REPORT){
tlv.set_length(0);
if (b.pdr_id.first) {std::shared_ptr<pfcp_pdr_id_ie> sie(new pfcp_pdr_id_ie(b.pdr_id.second)); add_ie(sie);}
// TODO Later(SXa, N4) if (b.downlink_data_service_information.first) {std::shared_ptr<pfcp_downlink_data_service_information_ie> sie(new pfcp_downlink_data_service_information_ie(b.downlink_data_service_information.second)); add_ie(sie);}
}
//--------
pfcp_downlink_data_report_ie() : pfcp_grouped_ie(PFCP_IE_DOWNLINK_DATA_REPORT){
}
//--------
explicit pfcp_downlink_data_report_ie(const pfcp_tlv& t) : pfcp_grouped_ie(t) {
};
//--------
void to_core_type(pfcp::downlink_data_report& c) {
for (auto sie : ies) {
sie.get()->to_core_type(c);
}
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::downlink_data_report i = {};
to_core_type(i);
s.set(i);
}
};
//-------------------------------------
// IE OUTER_HEADER_CREATION
class pfcp_outer_header_creation_ie : public pfcp_ie {
......@@ -4998,51 +4999,58 @@ public:
// }
//};
////-------------------------------------
//// IE NODE_REPORT_TYPE
//class pfcp_node_report_type_ie : public pfcp_ie {
//public:
// uint8_t todo;
//
// //--------
// pfcp_node_report_type_ie(const pfcp::node_report_type_t& b) : pfcp_ie(PFCP_IE_NODE_REPORT_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_node_report_type_ie() : pfcp_ie(PFCP_IE_NODE_REPORT_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_node_report_type_ie(const pfcp_tlv& t) : pfcp_ie(t) {
// todo = 0;
// };
// //--------
// void to_core_type(pfcp::node_report_type_t& b) {
// b.todo = todo;
// }
// //--------
// void dump_to(std::ostream& os) {
// tlv.dump_to(os);
// os.write(reinterpret_cast<const char*>(&todo), sizeof(todo));
// }
// //--------
// void load_from(std::istream& is) {
// //tlv.load_from(is);
// if (tlv.get_length() != 1) {
// throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(), __FILE__, __LINE__);
// }
// is.read(reinterpret_cast<char*>(&todo), sizeof(todo));
// }
// //--------
// void to_core_type(pfcp_ies_container& s) {
// pfcp::node_report_type_t node_report_type = {};
// to_core_type(node_report_type);
// s.set(node_report_type);
// }
//};
////-------------------------------------
//// IE USER_PLANE_PATH_FAILURE_REPORT
// IE NODE_REPORT_TYPE
class pfcp_node_report_type_ie : public pfcp_ie {
public:
union {
struct {
uint8_t upfr :1;
uint8_t spare1 :7;
} bf;
uint8_t b;
} u1;
//--------
pfcp_node_report_type_ie(const pfcp::node_report_type_t& b) : pfcp_ie(PFCP_IE_NODE_REPORT_TYPE){
u1.b = 0;
tlv.set_length(1);
}
//--------
pfcp_node_report_type_ie() : pfcp_ie(PFCP_IE_NODE_REPORT_TYPE){
u1.b = 0;
tlv.set_length(1);
}
//--------
pfcp_node_report_type_ie(const pfcp_tlv& t) : pfcp_ie(t) {
u1.b = 0;
};
//--------
void to_core_type(pfcp::node_report_type_t& b) {
u1.b = 0;
u1.bf.upfr = b.upfr;
}
//--------
void dump_to(std::ostream& os) {
tlv.dump_to(os);
os.write(reinterpret_cast<const char*>(&u1.b), sizeof(u1.b));
}
//--------
void load_from(std::istream& is) {
//tlv.load_from(is);
if (tlv.get_length() != 1) {
throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(), __FILE__, __LINE__);
}
is.read(reinterpret_cast<char*>(&u1.b), sizeof(u1.b));
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::node_report_type_t node_report_type = {};
to_core_type(node_report_type);
s.set(node_report_type);
}
};
//-------------------------------------
// IE USER_PLANE_PATH_FAILURE_REPORT
//class pfcp_user_plane_path_failure_report_ie : public pfcp_ie {
//public:
// uint8_t todo;
......
......@@ -24,6 +24,7 @@ include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/oai_spgwc)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_library(PFCP STATIC
......
This diff is collapsed.
This diff is collapsed.
......@@ -26,6 +26,7 @@ include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/pgwc)
include_directories(${SRC_TOP_DIR}/sgwc)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
......
This diff is collapsed.
......@@ -92,11 +92,11 @@ public:
pgw_app(pgw_app const&) = delete;
void operator=(pgw_app const&) = delete;
void send_delete_session_response_cause_request_accepted (const uint64_t gtpc_tx_id, const teid_t teid, boost::asio::ip::udp::endpoint& r_endpoint) const;
void send_delete_session_response_cause_context_not_found (const uint64_t gtpc_tx_id, const teid_t teid, boost::asio::ip::udp::endpoint& r_endpoint) const;
void send_modify_bearer_response_cause_context_not_found (const uint64_t gtpc_tx_id, const teid_t teid, boost::asio::ip::udp::endpoint& r_endpoint) const;
void send_release_access_bearers_response_cause_context_not_found(const uint64_t gtpc_tx_id, const teid_t teid, boost::asio::ip::udp::endpoint& r_endpoint) const;
void send_release_access_bearers_response_cause_request_accepted(const uint64_t gtpc_tx_id, const teid_t teid, boost::asio::ip::udp::endpoint& r_endpoint) const;
void send_delete_session_response_cause_request_accepted (const uint64_t gtpc_tx_id, const teid_t teid, const endpoint& r_endpoint) const;
void send_delete_session_response_cause_context_not_found (const uint64_t gtpc_tx_id, const teid_t teid, const endpoint& r_endpoint) const;
void send_modify_bearer_response_cause_context_not_found (const uint64_t gtpc_tx_id, const teid_t teid, const endpoint& r_endpoint) const;
void send_release_access_bearers_response_cause_context_not_found(const uint64_t gtpc_tx_id, const teid_t teid, const endpoint& r_endpoint) const;
void send_release_access_bearers_response_cause_request_accepted(const uint64_t gtpc_tx_id, const teid_t teid, const endpoint& r_endpoint) const;
fteid_t build_s5s8_cp_fteid(const struct in_addr ipv4_address, const teid_t teid);
fteid_t generate_s5s8_cp_fteid(const struct in_addr ipv4_address);
......@@ -105,7 +105,7 @@ public:
std::shared_ptr<pgw_context> s5s8cpgw_fteid_2_pgw_context(fteid_t& ls5s8_fteid);
void set_seid_2_pgw_context(const seid_t& seid, std::shared_ptr<pgw_context>& pc);
bool seid_2_pgw_context(const seid_t& seid, std::shared_ptr<pgw_context>& pc, std::shared_lock<std::shared_mutex>& lock_found) const;
bool seid_2_pgw_context(const seid_t& seid, std::shared_ptr<pgw_context>& pc) const;
void delete_pgw_context(std::shared_ptr<pgw_context> spc);
......@@ -124,9 +124,11 @@ public:
void handle_itti_msg (std::shared_ptr<itti_s5s8_delete_session_request> m);
void handle_itti_msg (std::shared_ptr<itti_s5s8_modify_bearer_request> m);
void handle_itti_msg (std::shared_ptr<itti_s5s8_release_access_bearers_request> m);
void handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& m);
void handle_itti_msg (itti_sxab_session_establishment_response& m);
void handle_itti_msg (itti_sxab_session_modification_response& m);
void handle_itti_msg (itti_sxab_session_deletion_response& m);
void handle_itti_msg (std::shared_ptr<itti_sxab_session_report_request> snr);
void handle_itti_msg (itti_sxab_association_setup_request& m);
void restore_sx_sessions(const seid_t& seid) const;
......
This diff is collapsed.
......@@ -31,6 +31,8 @@
#include "3gpp_29.244.h"
#include "3gpp_29.274.h"
#include "gtpv2c.hpp"
#include "pfcp.hpp"
#include "thread_sched.hpp"
#include <arpa/inet.h>
......@@ -136,7 +138,6 @@ typedef struct interface_cfg_s {
typedef struct itti_cfg_s {
util::thread_sched_params itti_timer_sched_params;
util::thread_sched_params s11_sched_params;
util::thread_sched_params sx_sched_params;
util::thread_sched_params s5s8_sched_params;
util::thread_sched_params pgw_app_sched_params;
......@@ -223,6 +224,18 @@ public:
}
force_push_pco = true;
ue_mtu = 1500;
itti.itti_timer_sched_params.sched_priority = 85;
itti.sx_sched_params.sched_priority = 84;
itti.s5s8_sched_params.sched_priority = 84;
itti.pgw_app_sched_params.sched_priority = 84;
itti.async_cmd_sched_params.sched_priority = 84;
s5s8_cp.thread_rd_sched_params.sched_priority = 90;
s5s8_cp.port = gtpv2c::default_port;
sx.thread_rd_sched_params.sched_priority = 90;
sx.port = pfcp::default_port;
};
~pgw_config();
void lock() {m_rw_lock.lock();};
......
This diff is collapsed.
......@@ -31,7 +31,6 @@
#include <map>
#include <mutex>
#include <memory>
#include <shared_mutex>
#include <utility>
#include <vector>
......@@ -161,6 +160,8 @@ public:
//pgw_eps_bearer& get_eps_bearer(const ebi_t& ebi) {return eps_bearers[ebi.ebi];}
void add_eps_bearer(pgw_eps_bearer& eps_bearer);
pgw_eps_bearer& get_eps_bearer(const ebi_t& ebi);
bool find_eps_bearer(const pfcp::pdr_id_t& pdr_id, pgw_eps_bearer& bearer);
bool has_eps_bearer(const pfcp::pdr_id_t& pdr_id, ebi_t& ebi);
void remove_eps_bearer(const ebi_t& ebi);
void remove_eps_bearer(pgw_eps_bearer& bearer);
void set(const paa_t& paa);
......@@ -239,14 +240,15 @@ public:
class apn_context {
public:
apn_context() : m_pdn_connections(), in_use(false), pdn_connections() {
apn_context() : m_context(), in_use(false), pdn_connections() {
apn_ambr = {0};
}
apn_context(apn_context& b) = delete;
void insert_pdn_connection(std::shared_ptr<pgw_pdn_connection>& sp);
bool find_pdn_connection(const teid_t xgw_s5s8c_teid, const bool is_local_teid, std::shared_ptr<pgw_pdn_connection>& pdn, std::shared_lock<std::shared_mutex>& lock_found);
bool find_pdn_connection(const teid_t xgw_s5s8c_teid, const bool is_local_teid, std::shared_ptr<pgw_pdn_connection>& pdn);
bool find_pdn_connection(const pfcp::pdr_id_t& pdr_id, std::shared_ptr<pgw_pdn_connection>& pdn, ebi_t& ebi);
void delete_pdn_connection(std::shared_ptr<pgw_pdn_connection>& pdn_connection);
int get_num_pdn_connections() const {return pdn_connections.size();};
// deallocate_ressources is for releasing LTE resources prior to the deletion of objects
......@@ -265,8 +267,7 @@ public:
// key is local s5s8 teid
//map<teid_t, shared_ptr<pgw_pdn_connection>> pdn_connections;
std::vector<std::shared_ptr<pgw_pdn_connection>> pdn_connections; // was list
mutable std::shared_mutex m_pdn_connections;
mutable std::recursive_mutex m_context;
};
class pgw_context;
......@@ -276,25 +277,23 @@ typedef std::pair<std::shared_ptr<apn_context>, std::shared_ptr<pgw_pdn_connecti
class pgw_context : public std::enable_shared_from_this<pgw_context> {
public:
pgw_context() : m_pending_procedures(), m_apns(),
imsi(), imsi_unauthenticated_indicator(false), apns(), pending_procedures() {
msisdn = {0};
}
pgw_context() : m_context(), imsi(), imsi_unauthenticated_indicator(false), apns(), pending_procedures(), msisdn() {}
pgw_context(pgw_context& b) = delete;
//void create_procedure(itti_s5s8_create_session_request& csreq);
void insert_procedure(std::shared_ptr<pgw_procedure>& sproc);
bool find_procedure(const uint64_t& trxn_id, std::shared_ptr<pgw_procedure>& proc, std::shared_lock<std::shared_mutex>& lock_found);
bool find_procedure(const uint64_t& trxn_id, std::shared_ptr<pgw_procedure>& proc);
void remove_procedure(pgw_procedure* proc);
#define IS_FIND_PDN_WITH_LOCAL_TEID true
#define IS_FIND_PDN_WITH_PEER_TEID false
bool find_pdn_connection(const std::string& apn, const teid_t xgw_s5s8c_teid, const bool is_local_teid, pdn_duo_t& pdn_connection, std::shared_lock<std::shared_mutex>& lock_found);
bool find_pdn_connection(const teid_t xgw_s5s8c_teid, const bool is_local_teid, pdn_duo_t& pdn_connection, std::shared_lock<std::shared_mutex>& lock_found);
bool find_pdn_connection(const std::string& apn, const teid_t xgw_s5s8c_teid, const bool is_local_teid, pdn_duo_t& pdn_connection);
bool find_pdn_connection(const teid_t xgw_s5s8c_teid, const bool is_local_teid, pdn_duo_t& pdn_connection);
bool find_pdn_connection(const pfcp::pdr_id_t& pdr_id, std::shared_ptr<pgw_pdn_connection>& pdn, ebi_t& ebi);
void insert_apn(std::shared_ptr<apn_context>& sa);
bool find_apn_context(const std::string& apn, std::shared_ptr<apn_context>& apn_context, std::shared_lock<std::shared_mutex>& lock_found);
bool find_apn_context(const std::string& apn, std::shared_ptr<apn_context>& apn_context);
int get_num_apn_contexts() {return apns.size();};
void delete_apn_context(std::shared_ptr<apn_context>& sa);
......@@ -304,9 +303,11 @@ public:
void handle_itti_msg (std::shared_ptr<itti_s5s8_delete_session_request> s5_trigger);
void handle_itti_msg (std::shared_ptr<itti_s5s8_modify_bearer_request> s5_trigger);
void handle_itti_msg (std::shared_ptr<itti_s5s8_release_access_bearers_request> s5_trigger);
void handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& );
void handle_itti_msg (itti_sxab_session_establishment_response& );
void handle_itti_msg (itti_sxab_session_modification_response& );
void handle_itti_msg (itti_sxab_session_deletion_response& );
void handle_itti_msg (std::shared_ptr<itti_sxab_session_report_request>&);
std::string toString() const;
......@@ -323,12 +324,13 @@ public:
// NOT IMPLEMENTED OMC identity // Identifies the OMC that shall receive the trace record(s).
std::vector<std::shared_ptr<apn_context>> apns; // was list
mutable std::shared_mutex m_apns;
//--------------------------------------------
// internals
std::vector<std::shared_ptr<pgw_procedure>> pending_procedures;
mutable std::shared_mutex m_pending_procedures;
// Big recursive lock
mutable std::recursive_mutex m_context;
};
}
......
......@@ -80,6 +80,12 @@ void pgw_s5s8_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)) {
pgw_s5s8_inst->send_msg(ref(*m));
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::pgwc_s5s8().debug( "TIME-OUT event timer id %d", to->timer_id);
......@@ -94,6 +100,9 @@ void pgw_s5s8_task (void *args_p)
}
break;
case HEALTH_PING:
break;
default:
Logger::pgwc_s5s8().info( "no handler for msg type %d", msg->msg_type);
}
......@@ -102,7 +111,7 @@ void pgw_s5s8_task (void *args_p)
}
//------------------------------------------------------------------------------
pgw_s5s8::pgw_s5s8 () : gtpv2c_stack(string(inet_ntoa(pgw_cfg.s5s8_cp.addr4)), pgw_cfg.s5s8_cp.port)
pgw_s5s8::pgw_s5s8 () : gtpv2c_stack(string(inet_ntoa(pgw_cfg.s5s8_cp.addr4)), pgw_cfg.s5s8_cp.port, pgw_cfg.s5s8_cp.thread_rd_sched_params)
{
Logger::pgwc_s5s8().startup("Starting...");
if (itti_inst->create_task(TASK_PGWC_S5S8, pgw_s5s8_task, nullptr) ) {
......@@ -133,7 +142,12 @@ void pgw_s5s8::send_msg(itti_s5s8_release_access_bearers_response& i)
send_triggered_message(i.r_endpoint, i.teid, i.gtp_ies, i.gtpc_tx_id);
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_create_session_request(gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::send_msg(itti_s5s8_downlink_data_notification& i)
{
send_initial_message(i.r_endpoint, i.teid, i.gtp_ies, TASK_PGWC_S5S8, i.gtpc_tx_id);
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_create_session_request(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
......@@ -152,11 +166,13 @@ void pgw_s5s8::handle_receive_create_session_request(gtpv2c_msg& msg, const boos
if (RETURNok != ret) {
Logger::pgwc_s5s8().error( "Could not send ITTI message %s to task TASK_PGWC_APP", i->get_msg_name());
}
} else {
Logger::pgwc_s5s8().error( "Error signalled by lower layer while receiving CREATE_SESSION_REQUEST");
}
// else ignore
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_delete_session_request(gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::handle_receive_delete_session_request(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
......@@ -179,7 +195,7 @@ void pgw_s5s8::handle_receive_delete_session_request(gtpv2c_msg& msg, const boos
// else ignore
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_modify_bearer_request(gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::handle_receive_modify_bearer_request(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
......@@ -202,7 +218,7 @@ void pgw_s5s8::handle_receive_modify_bearer_request(gtpv2c_msg& msg, const boost
// else ignore
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_release_access_bearers_request(gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::handle_receive_release_access_bearers_request(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
......@@ -225,7 +241,31 @@ void pgw_s5s8::handle_receive_release_access_bearers_request(gtpv2c_msg& msg, co
// else ignore
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::handle_receive_downlink_data_notification_acknowledge(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t gtpc_tx_id = 0;
gtpv2c_downlink_data_notification_acknowledge msg_ies_container = {};
msg.to_core_type(msg_ies_container);
handle_receive_message_cb(msg, remote_endpoint, TASK_SGWC_S11, error, gtpc_tx_id);
if (!error) {
itti_s5s8_downlink_data_notification_acknowledge *itti_msg = new itti_s5s8_downlink_data_notification_acknowledge(TASK_PGWC_S5S8, TASK_PGWC_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_acknowledge> i = std::shared_ptr<itti_s5s8_downlink_data_notification_acknowledge>(itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::pgwc_s5s8().error( "Could not send ITTI message %s to task TASK_PGWC_APP", i->get_msg_name());
}
}
// else ignore
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const endpoint& remote_endpoint)
{
//Logger::pgwc_s5s8().trace( "handle_receive_gtpv2c_msg msg type %d length %d", msg.get_message_type(), msg.get_message_length());
switch (msg.get_message_type()) {
......@@ -248,6 +288,10 @@ void pgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const boost::asio::ip:
handle_receive_delete_session_request(msg, remote_endpoint);
}
break;
case GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE: {
handle_receive_downlink_data_notification_acknowledge(msg, remote_endpoint);
}
break;
case GTP_DELETE_SESSION_RESPONSE:
case GTP_CHANGE_NOTIFICATION_REQUEST:
case GTP_CHANGE_NOTIFICATION_RESPONSE:
......@@ -316,7 +360,6 @@ void pgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const boost::asio::ip:
case GTP_RELEASE_ACCESS_BEARERS_RESPONSE:
case GTP_DOWNLINK_DATA_NOTIFICATION:
case GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE:
case GTP_PGW_RESTART_NOTIFICATION:
case GTP_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE:
case GTP_UPDATE_PDN_CONNECTION_SET_REQUEST:
......@@ -334,7 +377,8 @@ void pgw_s5s8::handle_receive_gtpv2c_msg(gtpv2c_msg& msg, const boost::asio::ip:
}
}
//------------------------------------------------------------------------------
void pgw_s5s8::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint)
void pgw_s5s8::handle_receive(char* recv_buffer, const std::size_t bytes_transferred,
const endpoint& remote_endpoint)
{
//Logger::pgwc_s5s8().info( "handle_receive(%d bytes)", bytes_transferred);
//std::cout << string_to_hex(recv_buffer, bytes_transferred) << std::endl;
......
......@@ -40,23 +40,25 @@ private:
std::thread::id thread_id;
std::thread thread;
void handle_receive_gtpv2c_msg(gtpv2c::gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_create_session_request(gtpv2c::gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint );
void handle_receive_delete_session_request(gtpv2c::gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_modify_bearer_request(gtpv2c::gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_release_access_bearers_request(gtpv2c::gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_gtpv2c_msg(gtpv2c::gtpv2c_msg& msg, const endpoint& r_endpoint);
void handle_receive_create_session_request(gtpv2c::gtpv2c_msg& msg, const endpoint& r_endpoint);
void handle_receive_delete_session_request(gtpv2c::gtpv2c_msg& msg, const endpoint& r_endpoint);
void handle_receive_modify_bearer_request(gtpv2c::gtpv2c_msg& msg, const endpoint& r_endpoint);
void handle_receive_release_access_bearers_request(gtpv2c::gtpv2c_msg& msg, const endpoint& r_endpoint);
void handle_receive_downlink_data_notification_acknowledge(gtpv2c::gtpv2c_msg& msg, const endpoint& remote_endpoint);
public:
pgw_s5s8();
pgw_s5s8(pgw_s5s8 const&) = delete;
void operator=(pgw_s5s8 const&) = delete;
void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint);
void send_msg(itti_s5s8_create_session_response& m);
void send_msg(itti_s5s8_delete_session_response& m);
void send_msg(itti_s5s8_modify_bearer_response& m);
void send_msg(itti_s5s8_release_access_bearers_response& m);
void send_msg(itti_s5s8_downlink_data_notification& i);
void time_out_itti_event(const uint32_t timer_id);
};
......
......@@ -98,7 +98,7 @@ int session_establishment_procedure::run(std::shared_ptr<itti_s5s8_create_sessio
sx_ser->seid = 0;
sx_ser->trxn_id = this->trxn_id;
//sx_ser->l_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(0xC0A8A064), 8805);
sx_ser->r_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(htobe32(up_node_id.u1.ipv4_address.s_addr)), 8805);
sx_ser->r_endpoint = endpoint(up_node_id.u1.ipv4_address, pfcp::default_port);
sx_triggered = std::shared_ptr<itti_sxab_session_establishment_request>(sx_ser);
//-------------------
......@@ -309,7 +309,7 @@ int modify_bearer_procedure::run(std::shared_ptr<itti_s5s8_modify_bearer_request
itti_sxab_session_modification_request *sx_smr = new itti_sxab_session_modification_request(TASK_PGWC_APP, TASK_PGWC_SX);
sx_smr->seid = ppc->up_fseid.seid;
sx_smr->trxn_id = this->trxn_id;
sx_smr->r_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(htobe32(ppc->up_fseid.ipv4_address.s_addr)), pgw_cfg.sx.port);
sx_smr->r_endpoint = endpoint(ppc->up_fseid.ipv4_address, pgw_cfg.sx.port);
sx_triggered = std::shared_ptr<itti_sxab_session_modification_request>(sx_smr);
......@@ -764,7 +764,7 @@ int release_access_bearers_procedure::run(std::shared_ptr<itti_s5s8_release_acce
itti_sxab_session_modification_request *sx_smr = new itti_sxab_session_modification_request(TASK_PGWC_APP, TASK_PGWC_SX);
sx_smr->seid = ppc->up_fseid.seid;
sx_smr->trxn_id = this->trxn_id;
sx_smr->r_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(htobe32(ppc->up_fseid.ipv4_address.s_addr)), pgw_cfg.sx.port);
sx_smr->r_endpoint = endpoint(ppc->up_fseid.ipv4_address, pgw_cfg.sx.port);
sx_triggered = std::shared_ptr<itti_sxab_session_modification_request>(sx_smr);
......@@ -885,7 +885,7 @@ int delete_session_procedure::run(std::shared_ptr<itti_s5s8_delete_session_reque
itti_sxab_session_deletion_request *sx = new itti_sxab_session_deletion_request(TASK_PGWC_APP, TASK_PGWC_SX);
sx->seid = ppc->up_fseid.seid;
sx->trxn_id = this->trxn_id;
sx->r_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(htobe32(ppc->up_fseid.ipv4_address.s_addr)), pgw_cfg.sx.port);
sx->r_endpoint = endpoint(ppc->up_fseid.ipv4_address, pgw_cfg.sx.port);
sx_triggered = std::shared_ptr<itti_sxab_session_deletion_request>(sx);
......@@ -932,5 +932,70 @@ void delete_session_procedure::handle_itti_msg (itti_sxab_session_deletion_respo
if (RETURNok != ret) {
Logger::pgwc_app().error( "Could not send ITTI message %s to task TASK_PGWC_S5S8", s5_triggered_pending->gtp_ies.get_msg_name());
}
// find APN context
pdn_duo_t pdn_duo = {};
if (pc->find_pdn_connection(ppc->pgw_fteid_s5_s8_cp.teid_gre_key, IS_FIND_PDN_WITH_LOCAL_TEID, pdn_duo)) {
pc->delete_pdn_connection(pdn_duo.first, pdn_duo.second);
} else {
Logger::pgwc_app().error("Could not delete PDN connection (APN context not found)");
}
}
//------------------------------------------------------------------------------
int downlink_data_report_procedure::run(std::shared_ptr<pgwc::pgw_context> context,
std::shared_ptr<pgwc::pgw_pdn_connection> pdn, const ebi_t& e)
{
ppc = pdn;
pc = context;
ebi = e;
itti_s5s8_downlink_data_notification *s5 = new itti_s5s8_downlink_data_notification(TASK_PGWC_APP, TASK_PGWC_S5S8);
s5->teid = ppc->sgw_fteid_s5_s8_cp.teid_gre_key;
s5->gtpc_tx_id = this->trxn_id;
s5->r_endpoint = endpoint(ppc->sgw_fteid_s5_s8_cp.ipv4_address, pgw_cfg.s5s8_cp.port);
s5->gtp_ies.set(e);
s5_triggered = std::shared_ptr<itti_s5s8_downlink_data_notification>(s5);
Logger::pgwc_app().info( "Sending ITTI message %s to task TASK_PGWC_S5S8", s5->gtp_ies.get_msg_name());
int ret = itti_inst->send_msg(s5_triggered);
if (RETURNok != ret) {
Logger::pgwc_app().error( "Could not send ITTI message %s to task TASK_PGWC_S5S8", s5->gtp_ies.get_msg_name());
return RETURNerror;
}
return RETURNok;
}
//------------------------------------------------------------------------------
void downlink_data_report_procedure::handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& ack)
{
::cause_t gtp_cause = {};
pfcp::cause_t pfcp_cause = {.cause_value = pfcp::CAUSE_VALUE_REQUEST_ACCEPTED};
if (ack.gtp_ies.get(gtp_cause)) {
switch (gtp_cause.cause_value) {
case REQUEST_ACCEPTED:
break;
default:
pfcp_cause.cause_value = CAUSE_VALUE_REQUEST_REJECTED;
}
} else {
Logger::pgwc_app().error( "downlink_data_report_procedure: Could not get cause from itti_s5s8_downlink_data_notification_acknowledge");
return;
}
itti_sxab_session_report_response *sx = new itti_sxab_session_report_response(TASK_PGWC_APP, TASK_PGWC_SX);
sx->seid = ppc->up_fseid.seid;
sx->trxn_id = this->trxn_id;
sx->r_endpoint = endpoint(ppc->up_fseid.ipv4_address, pgw_cfg.sx.port);
std::shared_ptr<itti_sxab_session_report_response> sx_triggered = std::shared_ptr<itti_sxab_session_report_response>(sx);
sx->pfcp_ies.set(pfcp_cause);
int ret = itti_inst->send_msg(sx_triggered);
if (RETURNok != ret) {
Logger::pgwc_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx->pfcp_ies.get_msg_name());
}
}
......@@ -65,6 +65,7 @@ public:
virtual void handle_itti_msg (itti_sxab_session_establishment_response& resp) {}
virtual void handle_itti_msg (itti_sxab_session_modification_response& resp) {}
virtual void handle_itti_msg (itti_sxab_session_deletion_response& resp) {}
virtual void handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& resp) {}
};
......@@ -105,8 +106,8 @@ public:
std::shared_ptr<itti_s5s8_create_session_request> s5_trigger;
std::shared_ptr<itti_s5s8_create_session_response> s5_triggered_pending;
std::shared_ptr<itti_sxab_session_establishment_request> sx_triggered;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
};
//------------------------------------------------------------------------------
......@@ -124,8 +125,8 @@ public:
std::shared_ptr<itti_s5s8_modify_bearer_request> s5_trigger;
std::shared_ptr<itti_s5s8_modify_bearer_response> s5_triggered_pending;
std::shared_ptr<itti_sxab_session_modification_request> sx_triggered;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
};
//------------------------------------------------------------------------------
class release_access_bearers_procedure : public pgw_procedure {
......@@ -142,14 +143,14 @@ public:
std::shared_ptr<itti_s5s8_release_access_bearers_request> s5_trigger;
std::shared_ptr<itti_s5s8_release_access_bearers_response> s5_triggered_pending;
std::shared_ptr<itti_sxab_session_modification_request> sx_triggered;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
};
//------------------------------------------------------------------------------
class delete_session_procedure : public pgw_procedure {
public:
explicit delete_session_procedure(std::shared_ptr<pgw_pdn_connection>& sppc) : pgw_procedure(), ppc(sppc),
sx_triggered(), s5_triggered_pending(), s5_trigger() {}
explicit delete_session_procedure(std::shared_ptr<pgw_context> spc, std::shared_ptr<pgw_pdn_connection>& sppc) : pgw_procedure(), ppc(sppc),
pc(spc), sx_triggered(), s5_triggered_pending(), s5_trigger() {}
int run(std::shared_ptr<itti_s5s8_delete_session_request>& req,
std::shared_ptr<itti_s5s8_delete_session_response>&resp,
......@@ -161,8 +162,26 @@ public:
std::shared_ptr<itti_s5s8_delete_session_request> s5_trigger;
std::shared_ptr<itti_s5s8_delete_session_response> s5_triggered_pending;
std::shared_ptr<itti_sxab_session_deletion_request> sx_triggered;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
};
//------------------------------------------------------------------------------
class downlink_data_report_procedure : public pgw_procedure {
public:
explicit downlink_data_report_procedure(std::shared_ptr<itti_sxab_session_report_request>& req) : pgw_procedure(req->trxn_id), ppc(),
pc(), sx_trigger(req), s5_triggered(), ebi() {}
int run(std::shared_ptr<pgwc::pgw_context> context,
std::shared_ptr<pgwc::pgw_pdn_connection> pdn, const ebi_t& e);
void handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& resp);
void notify_failure_to_peer(const pfcp::cause_t& cause);
//~downlink_data_report_procedure() {}
std::shared_ptr<itti_s5s8_downlink_data_notification> s5_triggered;
std::shared_ptr<itti_sxab_session_report_request> sx_trigger;
std::shared_ptr<pgw_pdn_connection> ppc;
std::shared_ptr<pgwc::pgw_context> pc;
ebi_t ebi;
};
}
......
......@@ -143,7 +143,7 @@ void pgwc_sxab_task (void *args_p)
case SXAB_SESSION_REPORT_RESPONSE:
if (itti_sxab_session_report_response* m = dynamic_cast<itti_sxab_session_report_response*>(msg)) {
pgwc_sxab_inst->handle_itti_msg(ref(*m));
pgwc_sxab_inst->send_sx_msg(ref(*m));
}
break;
......@@ -168,6 +168,10 @@ void pgwc_sxab_task (void *args_p)
return;
}
break;
case HEALTH_PING:
break;
default:
Logger::pgwc_sx().info( "no handler for msg type %d", msg->msg_type);
}
......@@ -176,7 +180,7 @@ void pgwc_sxab_task (void *args_p)
}
//------------------------------------------------------------------------------
pgwc_sxab::pgwc_sxab() : pfcp_l4_stack(string(inet_ntoa(pgw_cfg.sx.addr4)), pgw_cfg.sx.port)
pgwc_sxab::pgwc_sxab() : pfcp_l4_stack(string(inet_ntoa(pgw_cfg.sx.addr4)), pgw_cfg.sx.port, pgw_cfg.sx.thread_rd_sched_params)
{
Logger::pgwc_sx().startup("Starting...");
// TODO refine this, look at RFC5905
......@@ -204,7 +208,7 @@ pgwc_sxab::pgwc_sxab() : pfcp_l4_stack(string(inet_ntoa(pgw_cfg.sx.addr4)), pgw_
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_pfcp_msg(pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_pfcp_msg(pfcp_msg& msg, const endpoint& remote_endpoint)
{
Logger::pgwc_sx().trace( "handle_receive_pfcp_msg msg type %d length %d", msg.get_message_type(), msg.get_message_length());
switch (msg.get_message_type()) {
......@@ -227,6 +231,9 @@ void pgwc_sxab::handle_receive_pfcp_msg(pfcp_msg& msg, const boost::asio::ip::ud
case PFCP_SESSION_DELETION_RESPONSE:
handle_receive_session_deletion_response(msg, remote_endpoint);
break;
case PFCP_SESSION_REPORT_REQUEST:
handle_receive_session_report_request(msg, remote_endpoint);
break;
case PFCP_PFCP_PFD_MANAGEMENT_REQUEST:
case PFCP_PFCP_PFD_MANAGEMENT_RESPONSE:
case PFCP_ASSOCIATION_SETUP_RESPONSE:
......@@ -242,7 +249,6 @@ void pgwc_sxab::handle_receive_pfcp_msg(pfcp_msg& msg, const boost::asio::ip::ud
case PFCP_SESSION_ESTABLISHMENT_REQUEST:
case PFCP_SESSION_MODIFICATION_REQUEST:
case PFCP_SESSION_DELETION_REQUEST:
case PFCP_SESSION_REPORT_REQUEST:
case PFCP_SESSION_REPORT_RESPONSE:
Logger::pgwc_sx().info( "handle_receive_pfcp_msg msg %d length %d, not handled, discarded!", msg.get_message_type(), msg.get_message_length());
break;
......@@ -251,7 +257,7 @@ void pgwc_sxab::handle_receive_pfcp_msg(pfcp_msg& msg, const boost::asio::ip::ud
}
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -269,7 +275,7 @@ void pgwc_sxab::handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const boos
}
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -287,7 +293,7 @@ void pgwc_sxab::handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const boo
}
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_association_setup_request(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_association_setup_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -346,7 +352,7 @@ void pgwc_sxab::handle_receive_association_setup_request(pfcp::pfcp_msg& msg, co
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_session_establishment_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_session_establishment_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -369,7 +375,7 @@ void pgwc_sxab::handle_receive_session_establishment_response(pfcp::pfcp_msg& ms
// else ignore
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_session_modification_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_session_modification_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -392,7 +398,7 @@ void pgwc_sxab::handle_receive_session_modification_response(pfcp::pfcp_msg& msg
// else ignore
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
......@@ -414,12 +420,41 @@ void pgwc_sxab::handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, co
}
// else ignore
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive_session_report_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
bool error = true;
uint64_t trxn_id = 0;
pfcp_session_report_request msg_ies_container = {};
msg.to_core_type(msg_ies_container);
handle_receive_message_cb(msg, remote_endpoint, TASK_PGWC_SX, error, trxn_id);
if (!error) {
itti_sxab_session_report_request *itti_msg = new itti_sxab_session_report_request(TASK_PGWC_SX, TASK_PGWC_APP);
itti_msg->pfcp_ies = msg_ies_container;
itti_msg->r_endpoint = remote_endpoint;
itti_msg->trxn_id = trxn_id;
itti_msg->seid = msg.get_seid();
std::shared_ptr<itti_sxab_session_report_request> i = std::shared_ptr<itti_sxab_session_report_request>(itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::pgwc_sx().error( "Could not send ITTI message %s to task TASK_PGWC_APP", i->get_msg_name());
}
}
// else ignore
}
//------------------------------------------------------------------------------
void pgwc_sxab::send_sx_msg(itti_sxab_association_setup_response& i)
{
send_response(i.r_endpoint, i.pfcp_ies, i.trxn_id);
}
//------------------------------------------------------------------------------
void pgwc_sxab::send_sx_msg(itti_sxab_session_report_response& i)
{
send_response(i.r_endpoint, i.seid, i.pfcp_ies, i.trxn_id);
}
//------------------------------------------------------------------------------
void pgwc_sxab::send_heartbeat_request(std::shared_ptr<pfcp_association>& a)
{
pfcp::pfcp_heartbeat_request h = {};
......@@ -430,7 +465,7 @@ void pgwc_sxab::send_heartbeat_request(std::shared_ptr<pfcp_association>& a)
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
a->timer_heartbeat = itti_inst->timer_setup(5,0, TASK_PGWC_SX, TASK_PGWC_SX_TIMEOUT_HEARTBEAT_REQUEST, a->hash_node_id);
boost::asio::ip::udp::endpoint r_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(htobe32(node_id.u1.ipv4_address.s_addr)), 8805);
endpoint r_endpoint = endpoint(node_id.u1.ipv4_address, pfcp::default_port);
a->trxn_id_heartbeat = generate_trxn_id();
send_request(r_endpoint, h, TASK_PGWC_SX, a->trxn_id_heartbeat);
......@@ -439,7 +474,7 @@ void pgwc_sxab::send_heartbeat_request(std::shared_ptr<pfcp_association>& a)
}
}
//------------------------------------------------------------------------------
void pgwc_sxab::send_heartbeat_response(const boost::asio::ip::udp::endpoint& r_endpoint, const uint64_t trxn_id)
void pgwc_sxab::send_heartbeat_response(const endpoint& r_endpoint, const uint64_t trxn_id)
{
pfcp::pfcp_heartbeat_response h = {};
pfcp::recovery_time_stamp_t r = {.recovery_time_stamp = (uint32_t)recovery_time_stamp};
......@@ -462,7 +497,7 @@ void pgwc_sxab::send_sx_msg(itti_sxab_session_deletion_request& i)
send_request(i.r_endpoint, i.seid, i.pfcp_ies, TASK_PGWC_SX, i.trxn_id);
}
//------------------------------------------------------------------------------
void pgwc_sxab::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint)
void pgwc_sxab::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& remote_endpoint)
{
Logger::pgwc_sx().info( "handle_receive(%d bytes)", bytes_transferred);
//std::cout << string_to_hex(recv_buffer, bytes_transferred) << std::endl;
......
......@@ -85,21 +85,22 @@ public:
void send_sx_msg (itti_sxab_session_establishment_request& s);
void send_sx_msg (itti_sxab_session_modification_request& s);
void send_sx_msg (itti_sxab_session_deletion_request& s);
void send_sx_msg (itti_sxab_session_report_response& s) {};
void send_sx_msg (itti_sxab_session_report_response& 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 send_heartbeat_response(const endpoint& r_endpoint, const uint64_t trxn_id);
void handle_receive_pfcp_msg( 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);
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);
void handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_association_setup_request(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const endpoint& r_endpoint);
void handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const endpoint& r_endpoint);
void handle_receive_association_setup_request(pfcp::pfcp_msg& msg, const endpoint& r_endpoint);
void handle_receive_session_establishment_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_session_modification_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const boost::asio::ip::udp::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, const endpoint& r_endpoint);
void handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const endpoint& r_endpoint);
void handle_receive_session_report_request(pfcp::pfcp_msg& msg, const endpoint& r_endpoint);
void time_out_itti_event(const uint32_t timer_id);
};
......
......@@ -26,6 +26,7 @@ include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/pgwc)
include_directories(${SRC_TOP_DIR}/sgwc)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_library (SGWC STATIC
......
......@@ -137,6 +137,12 @@ void sgwc_app::set_s5s8sgw_teid_2_sgw_contexts(const teid_t& sgw_teid, shared_pt
{
s5s8lteid2sgw_contexts[sgw_teid] = std::make_pair(sebc, spc);
}
//------------------------------------------------------------------------------
void sgwc_app::delete_s5s8sgw_teid_2_sgw_contexts(const teid_t& sgw_teid)
{
s5s8lteid2sgw_contexts.erase(sgw_teid);
}
//------------------------------------------------------------------------------
void sgwc_app::set_s11sgw_teid_2_sgw_eps_bearer_context(const teid_t& sgw_teid, shared_ptr<sgw_eps_bearer_context> sebc)
{
......@@ -208,6 +214,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));
......@@ -232,6 +244,12 @@ void sgwc_app_task (void *args_p)
}
break;
case S11_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE:
if (itti_s11_downlink_data_notification_acknowledge* m = dynamic_cast<itti_s11_downlink_data_notification_acknowledge*>(msg)) {
sgwc_app_inst->handle_itti_msg(ref(*m));
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::sgwc_app().info( "TIME-OUT event timer id %d", to->timer_id);
......@@ -243,6 +261,10 @@ void sgwc_app_task (void *args_p)
return;
}
break;
case HEALTH_PING:
break;
default:
Logger::sgwc_app().info( "no handler for ITTI msg type %d", msg->msg_type);
}
......@@ -422,6 +444,23 @@ void sgwc_app::handle_itti_msg (itti_s11_release_access_bearers_request& m)
return;
}
}
//------------------------------------------------------------------------------
void sgwc_app::handle_itti_msg (itti_s11_downlink_data_notification_acknowledge& m)
{
Logger::sgwc_app().debug("Received S11 DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE sender teid " TEID_FMT " gtpc_tx_id " PROC_ID_FMT " ", m.teid, m.gtpc_tx_id);
if (m.teid) {
if (is_s11sgw_teid_2_sgw_eps_bearer_context(m.teid)) {
shared_ptr<sgw_eps_bearer_context> ebc = s11sgw_teid_2_sgw_eps_bearer_context(m.teid);
ebc->handle_itti_msg(m);
} else {
Logger::sgwc_app().debug("Discarding S11 DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE sender teid " TEID_FMT " gtpc_tx_id " PROC_ID_FMT ", invalid teid", m.teid, m.gtpc_tx_id);
return;
}
} else {
Logger::sgwc_app().debug("Discarding S11 DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE sender teid " TEID_FMT " gtpc_tx_id " PROC_ID_FMT ", invalid teid", m.teid, m.gtpc_tx_id);
}
}
//------------------------------------------------------------------------------
void sgwc_app::handle_itti_msg (itti_s5s8_create_session_response& m)
{
......@@ -462,10 +501,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 +517,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 +533,28 @@ 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 CSResp", m.teid);
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 DOWNLINK_DATA_NOTIFICATION with dest teid " TEID_FMT " unknown, ignore!", m.teid);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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