Commit 9aa6f728 authored by gauthier's avatar gauthier

GTPU ECHO_RESPONSE

parent 149aa8b6
......@@ -40,47 +40,20 @@ namespace oai::cn::core::itti {
class itti_s1u_msg : public itti_msg {
public:
itti_s1u_msg(const itti_msg_type_t msg_type, const task_id_t orig, const task_id_t dest):
itti_msg(msg_type, orig, dest) {
l_endpoint = {};
l_endpoint_addr_len = sizeof(l_endpoint);
r_endpoint = {};
r_endpoint_addr_len = sizeof(r_endpoint);
teid = UNASSIGNED_TEID;
gtpu_tx_id = 0;
}
itti_msg(msg_type, orig, dest) {}
itti_s1u_msg& operator=(itti_s1u_msg other)
{
this->itti_msg::operator=(other);
std::swap(l_endpoint, other.l_endpoint);
std::swap(l_endpoint_addr_len, other.l_endpoint_addr_len);
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(gtpu_tx_id, other.gtpu_tx_id);
return *this;
}
itti_s1u_msg(const itti_s1u_msg& i) : itti_msg(i) {
l_endpoint = i.l_endpoint;
l_endpoint_addr_len = i.l_endpoint_addr_len;
r_endpoint = i.r_endpoint;
r_endpoint_addr_len = i.r_endpoint_addr_len;
teid = i.teid;
gtpu_tx_id = i.gtpu_tx_id;
}
itti_s1u_msg(const itti_s1u_msg& i) : itti_msg(i) {}
itti_s1u_msg(const itti_s1u_msg& i, const task_id_t orig, const task_id_t dest) : itti_s1u_msg(i) {
origin = orig;
destination = dest;
}
struct sockaddr_storage l_endpoint;
socklen_t l_endpoint_addr_len;
struct sockaddr_storage r_endpoint;
socklen_t r_endpoint_addr_len;
teid_t teid;
uint64_t gtpu_tx_id;
};
//------------------------------------------------------------------------------
class itti_s1u_echo_request : public itti_s1u_msg {
......@@ -101,7 +74,7 @@ public:
itti_s1u_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s1u_echo_request).name();};
const char* get_msg_name() {return "S1U_ECHO_REQUEST";};
proto::gtpv1u::gtpv1u_echo_request gtp_ies;
};
......@@ -124,7 +97,7 @@ public:
itti_s1u_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s1u_echo_response).name();};
const char* get_msg_name() {return "S1U_ECHO_RESPONSE";};
proto::gtpv1u::gtpv1u_echo_response gtp_ies;
};
......@@ -147,7 +120,7 @@ public:
itti_s1u_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s1u_error_indication).name();};
const char* get_msg_name() {return "S1U_ERROR_INDICATION";};
proto::gtpv1u::gtpv1u_error_indication gtp_ies;
};
......@@ -170,7 +143,7 @@ public:
itti_s1u_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s1u_supported_extension_headers_notification).name();};
const char* get_msg_name() {return "S1U_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION";};
proto::gtpv1u::gtpv1u_supported_extension_headers_notification gtp_ies;
};
......@@ -195,7 +168,7 @@ public:
itti_s1u_msg(i, orig, dest) {
gtp_ies = i.gtp_ies;
}
const char* get_msg_name() {return typeid(itti_s1u_end_marker).name();};
const char* get_msg_name() {return "S1U_END_MARKER";};
proto::gtpv1u::gtpv1u_end_marker gtp_ies;
};
......
/*
* 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 3gpp_29.281.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "3gpp_29.281.hpp"
#include <string>
#include <string.h>
using namespace oai::cn::proto::gtpv1u;
using namespace oai::cn::core;
//------------------------------------------------------------------------------
gtpv1u_ie * gtpv1u_ie::new_gtpv1u_ie_from_stream(std::istream& is) {
gtpv1u_tlv tlv;
tlv.load_from(is);
if (tlv.length) {
switch (tlv.type) {
case GTPU_IE_RECOVERY: {
gtpv1u_recovery_ie *ie = new gtpv1u_recovery_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTPU_IE_TUNNEL_ENDPOINT_IDENTIFIER_DATA_I: {
gtpv1u_tunnel_endpoint_identifier_data_i_ie *ie = new gtpv1u_tunnel_endpoint_identifier_data_i_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTPU_IE_GTP_U_PEER_ADDRESS: {
gtpv1u_gtp_u_peer_address_ie *ie = new gtpv1u_gtp_u_peer_address_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTPU_IE_PRIVATE_EXTENSION: {
gtpv1u_private_extension_ie *ie = new gtpv1u_private_extension_ie(tlv);
ie->load_from(is);
return ie;
}
break;
default:
Logger::gtpv1_u().error("Unknown GTP IE type %d (length %d)", tlv.get_type(), tlv.get_length());
return nullptr;
}
} else {
Logger::gtpv1_u().error("GTP IE type %d length %d", tlv.get_type(), tlv.get_length());
return nullptr;
}
}
//------------------------------------------------------------------------------
gtpv1u_msg::gtpv1u_msg(const gtpv1u_echo_request& gtp_ies) : gtpv1u_msg_header() {
ies = {};
set_message_type(GTPU_ECHO_REQUEST);
if (gtp_ies.private_extension.first) {std::shared_ptr<gtpv1u_private_extension_ie> sie(new gtpv1u_private_extension_ie(gtp_ies.private_extension.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv1u_msg::gtpv1u_msg(const gtpv1u_echo_response& gtp_ies) : gtpv1u_msg_header() {
ies = {};
set_message_type(GTPU_ECHO_RESPONSE);
if (gtp_ies.recovery.first) {std::shared_ptr<gtpv1u_recovery_ie> sie(new gtpv1u_recovery_ie(gtp_ies.recovery.second)); add_ie(sie);}
if (gtp_ies.private_extension.first) {std::shared_ptr<gtpv1u_private_extension_ie> sie(new gtpv1u_private_extension_ie(gtp_ies.private_extension.second)); add_ie(sie);}
}
......@@ -38,6 +38,7 @@
#include <sstream>
#include <string>
#include <vector>
#include <sys/socket.h>
#include "3gpp_29.281.h"
#include "msg_gtpv1u.hpp"
......@@ -194,19 +195,19 @@ private:
// GTP-PDU.
uint8_t next_extension_header_type;
bool has_teid_;
public:
gtpv1u_msg_header() {
u1.b = 0;
message_type = 0;
message_length = GTPV1U_MSG_HEADER_MIN_SIZE; //
message_length = 0; //
teid = 0;
sequence_number = 0;
npdu_number = 0;
next_extension_header_type = 0;
u1.bf.version = 1;
u1.bf.pt = 1;
}
gtpv1u_msg_header(const gtpv1u_msg_header& h) {
......@@ -217,6 +218,7 @@ public:
sequence_number = h.sequence_number;
npdu_number = h.npdu_number;
next_extension_header_type = h.next_extension_header_type;
has_teid_ = h.has_teid_;
}
gtpv1u_msg_header& operator=(gtpv1u_msg_header other)
......@@ -235,11 +237,22 @@ public:
teid = tid;
}
uint32_t get_teid() const {
return teid;
}
bool get_sequence_number(uint16_t& vsequence_number) const {
if (u1.bf.s) { // if inter rat then check in more details
vsequence_number = sequence_number;
return true;
}
// if (...) {
// vsequence_number = 0;
// return true;
// }
return false;
}
void set_message_type(const uint8_t& t) {
message_type = t;
}
......@@ -256,8 +269,19 @@ public:
return message_length;
}
// get payload length without extra header length
uint16_t get_message_length_wo_xheader() const {
uint16_t ml = message_length;
if (u1.bf.s) {
ml -= sizeof(sequence_number);
}
return ml;
}
void set_sequence_number(const uint16_t& s) {
message_length += sizeof(sequence_number);
sequence_number = s;
u1.bf.s = 1;
}
uint16_t get_sequence_number() const {
......@@ -274,9 +298,11 @@ public:
auto be_teid = htobe32(teid);
os.write(reinterpret_cast<const char*>(&be_teid), sizeof(be_teid));
if (u1.b & 0x07) {
if (u1.bf.s) {
auto be_sequence_number = htobe16(sequence_number);
os.write(reinterpret_cast<const char*>(&be_sequence_number), sizeof(be_sequence_number));
}
if (u1.b & 0x05) {
os.write(reinterpret_cast<const char*>(&npdu_number), sizeof(npdu_number));
os.write(reinterpret_cast<const char*>(&next_extension_header_type), sizeof(next_extension_header_type));
}
......@@ -287,9 +313,24 @@ public:
is.read(reinterpret_cast<char*>(&message_type), sizeof(message_type));
is.read(reinterpret_cast<char*>(&message_length), sizeof(message_length));
message_length = be16toh(message_length);
if (u1.b & 0x07) {
is.read(reinterpret_cast<char*>(&teid), sizeof(teid));
teid = be32toh(teid);
// if (message_length >= sizeof(teid)){
// switch (message_type) {
// case GTPU_ECHO_REQUEST:
// case GTPU_ECHO_RESPONSE:
// case GTPU_ERROR_INDICATION:
// case GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION:
// break;
// default:;
// }
// }
if (u1.bf.s) {
is.read(reinterpret_cast<char*>(&sequence_number), sizeof(sequence_number));
sequence_number = be16toh(sequence_number);
}
if (u1.b & 0x05) {
is.read(reinterpret_cast<char*>(&npdu_number), sizeof(npdu_number));
is.read(reinterpret_cast<char*>(&next_extension_header_type), sizeof(next_extension_header_type));
}
......@@ -299,25 +340,27 @@ public:
class gtpv1u_msg : public gtpv1u_msg_header
{
public:
uint16_t remote_port;
struct sockaddr_storage r_endpoint;
socklen_t r_endpoint_addr_len;
std::vector<std::shared_ptr<gtpv1u_ie>> ies;
gtpv1u_msg() : gtpv1u_msg_header(), remote_port(0), ies() {}
gtpv1u_msg() : gtpv1u_msg_header(), r_endpoint(), r_endpoint_addr_len(0), ies() {}
gtpv1u_msg(const gtpv1u_msg& m) : gtpv1u_msg_header(m),
remote_port(m.remote_port),
r_endpoint(m.r_endpoint),
r_endpoint_addr_len(m.r_endpoint_addr_len),
ies(m.ies) {}
gtpv1u_msg& operator=(gtpv1u_msg other)
{
std::swap(remote_port, other.remote_port);
std::swap(r_endpoint, other.r_endpoint);
std::swap(r_endpoint_addr_len, other.r_endpoint_addr_len);
std::swap(ies, other.ies);
return *this;
}
explicit gtpv1u_msg(const gtpv1u_msg_header& hdr) : gtpv1u_msg_header(hdr), remote_port(0), ies() {}
explicit gtpv1u_msg(const gtpv1u_msg_header& hdr) : gtpv1u_msg_header(hdr), r_endpoint(), r_endpoint_addr_len(0), ies() {}
explicit gtpv1u_msg(const gtpv1u_echo_request& gtp_ies);
explicit gtpv1u_msg(const gtpv1u_echo_response& gtp_ies);
explicit gtpv1u_msg(const gtpv1u_error_indication& gtp_ies);
......@@ -369,7 +412,7 @@ public:
void load_from(std::istream& is) {
gtpv1u_msg_header::load_from(is);
uint16_t check_msg_length = get_message_length(); // total length of message - fixed part of the gtpu header (GTPV1U_MSG_HEADER_MIN_SIZE)
uint16_t check_msg_length = get_message_length_wo_xheader(); // total length of message - fixed part of the gtpu header (GTPV1U_MSG_HEADER_MIN_SIZE)
gtpv1u_ie * ie = nullptr;
uint16_t ies_length = 0;
//std::cout << std::dec<< " check_msg_length = " << check_msg_length << std::endl;
......@@ -382,7 +425,7 @@ public:
}
} while((ie) && (ies_length < check_msg_length));
if (ies_length != check_msg_length) {
if (ies_length > check_msg_length) { // should be <= (padding)
//std::cout << " check_msg_length = " << check_msg_length << " ies_length = " << ies_length << std::endl;
throw gtpu_msg_bad_length_exception(get_message_type(), get_message_length());
}
......
......@@ -19,6 +19,7 @@
# contact@openairinterface.org
################################################################################
add_library(GTPV1U STATIC
3gpp_29.281.cpp
gtpv1u.cpp
)
......
......@@ -25,6 +25,7 @@
\email: lionel.gauthier@eurecom.fr
*/
#include "common_root_types.h"
#include "gtpu.h"
#include "gtpv1u.hpp"
......@@ -37,8 +38,6 @@ using namespace std;
extern itti_mw *itti_inst;
uint64_t oai::cn::proto::gtpv1u::gtpu_l4_stack::gtpu_tx_id_generator = 1; //odd in any case.
//------------------------------------------------------------------------------
static std::string string_to_hex(const std::string& input)
{
......@@ -311,4 +310,33 @@ void gtpu_l4_stack::send_g_pdu(const struct sockaddr_in6& peer_addr, const teid_
gtpuhdr->teid = htobe32(teid);
udp_s.async_send_to(reinterpret_cast<const char*>(gtpuhdr), payload_len + sizeof(struct gtpuhdr), peer_addr);
}
//------------------------------------------------------------------------------
void gtpu_l4_stack::send_response(const gtpv1u_echo_response& gtp_ies)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv1u_msg msg(gtp_ies);
uint32_t teid = UNASSIGNED_TEID;
if (gtp_ies.get_teid(teid)) {
msg.set_teid(teid);
}
uint16_t sn = 0;
if (gtp_ies.get_sequence_number(sn)) {
msg.set_sequence_number(sn);
}
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());
}
}
......@@ -144,7 +144,6 @@ class gtpu_l4_stack {
#define GTPV1U_PROC_TIME_OUT_MS ((GTPV1U_T3_RESPONSE_MS) * (GTPV1U_N3_REQUESTS + 1))
protected:
static uint64_t gtpu_tx_id_generator;
uint32_t id;
udp_server udp_s;
......@@ -171,9 +170,7 @@ public:
void send_g_pdu(const struct sockaddr_in& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len);
void send_g_pdu(const struct sockaddr_in6& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len);
//virtual uint32_t send_request(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv1u_create_session_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
//virtual void send_response(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv1u_create_session_response& gtp_ies, const uint64_t gtp_tx_id);
//virtual uint32_t send_gpdu(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv1u_create_session_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
void send_response(const gtpv1u_echo_response& gtp_ies);
};
} // namespace gtpv1u
......
......@@ -35,12 +35,36 @@
#include "common_defs.h"
#include <vector>
#include <sys/socket.h>
namespace oai::cn::proto::gtpv1u {
class gtpv1u_ies_container {
public:
static const uint8_t msg_id = 0;
struct sockaddr_storage r_endpoint;
socklen_t r_endpoint_addr_len;
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(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) {}
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);
return *this;
}
virtual bool get(core::recovery_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_RECOVERY);}
virtual bool get(core::tunnel_endpoint_identifier_data_i_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_TUNNEL_ENDPOINT_IDENTIFIER_DATA_I);}
......@@ -53,7 +77,14 @@ public:
virtual void set(const core::gtp_u_peer_address_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_GTP_U_PEER_ADDRESS);}
virtual void set(const core::extension_header_type_list_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_EXTENSION_HEADER_TYPE_LIST);}
virtual void set(const core::private_extension_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_PRIVATE_EXTENSION);}
virtual ~gtpv1u_ies_container() {};
virtual void set_teid(const uint32_t pteid) {teid.second = pteid; teid.first = true;}
virtual void set_sequence_number(const uint16_t psequence_number) {sequence_number.second = psequence_number; sequence_number.first = true;}
virtual void set_npdu_number(const uint8_t pnpdu_number) {npdu_number.second = pnpdu_number; npdu_number.first = true;}
virtual bool get_teid(uint32_t& v) const {if (teid.first) {v = teid.second;return true;}return false;}
virtual bool get_sequence_number(uint16_t& v) const {if (sequence_number.first) {v = sequence_number.second;return true;}return false;}
virtual bool get_npdu_number(uint8_t& v) const {if (npdu_number.first) {v = npdu_number.second;return true;}return false;}
};
//------------------------------------------------------------------------------
......@@ -63,10 +94,11 @@ public:
std::pair<bool, core::private_extension_t> private_extension;
gtpv1u_echo_request(): private_extension() {}
gtpv1u_echo_request(const gtpv1u_echo_request& i) : private_extension(i.private_extension) {}
gtpv1u_echo_request() : gtpv1u_ies_container(), private_extension() {}
gtpv1u_echo_request(const gtpv1u_echo_request& i) : gtpv1u_ies_container(i), private_extension(i.private_extension) {}
gtpv1u_echo_request& operator=(gtpv1u_echo_request other)
{
this->gtpv1u_ies_container::operator=(other);
std::swap(private_extension, other.private_extension);
return *this;
}
......@@ -85,13 +117,14 @@ public:
std::pair<bool, core::recovery_t> recovery;
std::pair<bool, core::private_extension_t> private_extension;
gtpv1u_echo_response(): recovery(), private_extension() {}
gtpv1u_echo_response(): gtpv1u_ies_container(), recovery(), private_extension() {}
gtpv1u_echo_response(const gtpv1u_echo_response& i): recovery(i.recovery), private_extension(i.private_extension) {}
gtpv1u_echo_response(const gtpv1u_echo_response& i): gtpv1u_ies_container(i), recovery(i.recovery), private_extension(i.private_extension) {}
static const char* get_msg_name() {return "GTPU_ECHO_RESPONSE";};
gtpv1u_echo_response& operator=(gtpv1u_echo_response other)
{
this->gtpv1u_ies_container::operator=(other);
std::swap(recovery, other.recovery);
std::swap(private_extension, other.private_extension);
return *this;
......@@ -114,15 +147,16 @@ public:
std::pair<bool, core::gtp_u_peer_address_t> gtp_u_peer_address;
std::pair<bool, core::private_extension_t> private_extension;
gtpv1u_error_indication(): tunnel_endpoint_identifier_data_i(), gtp_u_peer_address(), private_extension() {}
gtpv1u_error_indication(): gtpv1u_ies_container(), tunnel_endpoint_identifier_data_i(), gtp_u_peer_address(), private_extension() {}
gtpv1u_error_indication(const gtpv1u_error_indication& i) :
gtpv1u_error_indication(const gtpv1u_error_indication& i) : gtpv1u_ies_container(i),
tunnel_endpoint_identifier_data_i(i.tunnel_endpoint_identifier_data_i),
gtp_u_peer_address(i.gtp_u_peer_address),
private_extension(i.private_extension) {}
gtpv1u_error_indication& operator=(gtpv1u_error_indication other)
{
this->gtpv1u_ies_container::operator=(other);
std::swap(tunnel_endpoint_identifier_data_i, other.tunnel_endpoint_identifier_data_i);
std::swap(gtp_u_peer_address, other.gtp_u_peer_address);
std::swap(private_extension, other.private_extension);
......@@ -146,14 +180,16 @@ public:
std::pair<bool, core::extension_header_type_list_t> extension_header_type_list;
gtpv1u_supported_extension_headers_notification() :
gtpv1u_supported_extension_headers_notification() : gtpv1u_ies_container(),
extension_header_type_list() {}
gtpv1u_supported_extension_headers_notification(const gtpv1u_supported_extension_headers_notification& i) :
gtpv1u_ies_container(i),
extension_header_type_list(i.extension_header_type_list) {}
gtpv1u_supported_extension_headers_notification& operator=(gtpv1u_supported_extension_headers_notification other)
{
this->gtpv1u_ies_container::operator=(other);
std::swap(extension_header_type_list, other.extension_header_type_list);
return *this;
}
......@@ -172,14 +208,15 @@ public:
std::pair<bool, core::private_extension_t> private_extension;
gtpv1u_end_marker() :
gtpv1u_end_marker() : gtpv1u_ies_container(),
private_extension() {}
gtpv1u_end_marker(const gtpv1u_end_marker& i) :
gtpv1u_end_marker(const gtpv1u_end_marker& i) : gtpv1u_ies_container(i),
private_extension(i.private_extension) {}
gtpv1u_end_marker& operator=(gtpv1u_end_marker other)
{
this->gtpv1u_ies_container::operator=(other);
std::swap(private_extension, other.private_extension);
return *this;
}
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_s1u.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "common_defs.h"
#include "gtpu.h"
#include "itti.hpp"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_config.hpp"
#include "spgwu_s1u.hpp"
#include <stdexcept>
using namespace oai::cn::core;
using namespace oai::cn::proto::gtpv1u;
using namespace oai::cn::core::itti;
using namespace oai::cn::nf::spgwu;
using namespace std;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_config spgwu_cfg;
extern spgwu_s1u *spgwu_s1u_inst;
void spgwu_s1u_task (void*);
//------------------------------------------------------------------------------
void spgwu_s1u_task (void *args_p)
{
const task_id_t task_id = TASK_SPGWU_S1U;
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case S1U_ECHO_RESPONSE:
spgwu_s1u_inst->handle_itti_msg(std::static_pointer_cast<itti_s1u_echo_response>(shared_msg));
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::spgwu_s1u().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::spgwu_s1u().info( "Received terminate message");
return;
}
break;
default:
Logger::spgwu_s1u().info( "no handler for msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
spgwu_s1u::spgwu_s1u () : gtpu_l4_stack(spgwu_cfg.s1_up.addr4, spgwu_cfg.s1_up.port, spgwu_cfg.s1_up.cpu_id_thread_loop_read)
{
Logger::spgwu_s1u().startup("Starting...");
if (itti_inst->create_task(TASK_SPGWU_S1U, spgwu_s1u_task, nullptr) ) {
Logger::spgwu_s1u().error( "Cannot create task TASK_SPGWU_S1U" );
throw std::runtime_error( "Cannot create task TASK_SPGWU_S1U" );
}
Logger::spgwu_s1u().startup( "Started" );
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len)
{
#define GTPU_MESSAGE_FLAGS_POS_IN_UDP_PAYLOAD 0
struct gtpuhdr* gtpuh = (struct gtpuhdr*)&recv_buffer[0];
if (gtpuh->version == 1) {
// Do it fast, do not go throught handle_receive_gtpv1u_msg()
if (gtpuh->message_type == GTPU_G_PDU) {
uint8_t gtp_flags = recv_buffer[GTPU_MESSAGE_FLAGS_POS_IN_UDP_PAYLOAD];
std::size_t gtp_payload_offset = GTPV1U_MSG_HEADER_MIN_SIZE;
std::size_t gtp_payload_length = be16toh(gtpuh->message_length);
if (gtp_flags & 0x07) {
gtp_payload_offset += 4;
gtp_payload_length -= 4;
}
uint32_t tunnel_id = be32toh(gtpuh->teid);
struct iphdr* iph = (struct iphdr*)&recv_buffer[gtp_payload_offset];
if (iph->version == 4) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access(iph, gtp_payload_length, r_endpoint, r_endpoint_addr_len, tunnel_id);
} else if (iph->version == 6) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access((struct ipv6hdr*)iph, gtp_payload_length, r_endpoint, r_endpoint_addr_len, tunnel_id);
} else {
Logger::spgwu_s1u().trace( "Unknown GTPU_G_PDU packet");
}
} else {
//Logger::spgwu_s1u().info( "handle_receive(%d bytes)", bytes_transferred);
//std::cout << string_to_hex(recv_buffer, bytes_transferred) << std::endl;
std::istringstream iss(std::istringstream::binary);
iss.rdbuf()->pubsetbuf(recv_buffer,bytes_transferred);
gtpv1u_msg msg = {};
try {
msg.load_from(iss);
handle_receive_gtpv1u_msg(msg, r_endpoint, r_endpoint_addr_len);
} catch (gtpu_exception& e) {
Logger::spgwu_s1u().info( "handle_receive exception %s", e.what());
}
}
} else {
struct iphdr* iph = (struct iphdr*)&recv_buffer[0];
if (iph->version == 4) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access(iph, bytes_transferred, r_endpoint, r_endpoint_addr_len);
} else if (iph->version == 6) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access((struct ipv6hdr*)iph, bytes_transferred, r_endpoint, r_endpoint_addr_len);
} else {
Logger::spgwu_s1u().trace( "Unknown IPX packet");
}
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive_gtpv1u_msg(gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len)
{
//Logger::spgwu_s1u().trace( "handle_receive_gtpv1u_msg msg type %d length %d", msg.get_message_type(), msg.get_message_length());
switch (msg.get_message_type()) {
case GTPU_ECHO_REQUEST:
handle_receive_echo_request(msg, r_endpoint, r_endpoint_addr_len);
break;
case GTPU_ECHO_RESPONSE:
case GTPU_ERROR_INDICATION:
case GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION:
case GTPU_END_MARKER:
case GTPU_G_PDU:
break;
default:
Logger::spgwu_s1u().error( "handle_receive_gtpv1u_msg msg length %d", msg.get_message_length());
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::send_g_pdu(const struct in_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes)
{
//Logger::spgwu_s1u().info( "spgwu_s1u::send_g_pdu() TEID " TEID_FMT " %d bytes", num_bytes);
struct sockaddr_in peer_sock_addr;
peer_sock_addr.sin_family = AF_INET;
peer_sock_addr.sin_addr = peer_addr;
peer_sock_addr.sin_port = htobe16(peer_udp_port);
gtpu_l4_stack::send_g_pdu(peer_sock_addr, (teid_t)tunnel_id, send_buffer, num_bytes);
}
//------------------------------------------------------------------------------
void spgwu_s1u::send_g_pdu(const struct in6_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes)
{
struct sockaddr_in6 peer_sock_addr;
peer_sock_addr.sin6_family = AF_INET6;
peer_sock_addr.sin6_addr = peer_addr;
peer_sock_addr.sin6_port = htobe16(peer_udp_port);
peer_sock_addr.sin6_flowinfo = 0;
peer_sock_addr.sin6_scope_id = 0;
gtpu_l4_stack::send_g_pdu(peer_sock_addr, tunnel_id, send_buffer, num_bytes);
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive_echo_request(gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len)
{
itti_s1u_echo_request *echo = new itti_s1u_echo_request(TASK_SPGWU_S1U, TASK_SPGWU_APP);
gtpv1u_echo_request msg_ies_container = {};
msg.to_core_type(echo->gtp_ies);
echo->gtp_ies.r_endpoint = r_endpoint;
echo->gtp_ies.r_endpoint_addr_len = r_endpoint_addr_len;
echo->gtp_ies.set_teid(msg.get_teid());
uint16_t sn = 0;
if (msg.get_sequence_number(sn)) {
echo->gtp_ies.set_sequence_number(sn);
}
std::shared_ptr<itti_s1u_echo_request> secho = std::shared_ptr<itti_s1u_echo_request>(echo);
int ret = itti_inst->send_msg(secho);
if (RETURNok != ret) {
Logger::spgwu_s1u().error( "Could not send ITTI message %s to task TASK_SPGWU_APP", echo->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_itti_msg (std::shared_ptr<core::itti::itti_s1u_echo_response> m)
{
send_response(m->gtp_ies);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_s1u.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SGWU_S1U_HPP_SEEN
#define FILE_SGWU_S1U_HPP_SEEN
#include "gtpv1u.hpp"
#include "itti_msg_s1u.hpp"
#include "msg_gtpv1u.hpp"
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <netinet/in.h>
#include <thread>
namespace oai::cn::nf::spgwu {
class spgwu_s1u : public oai::cn::proto::gtpv1u::gtpu_l4_stack {
private:
std::thread::id thread_id;
std::thread thread;
void handle_receive_gtpv1u_msg(proto::gtpv1u::gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len);
void handle_receive_echo_request(proto::gtpv1u::gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len);
public:
spgwu_s1u();
spgwu_s1u(spgwu_s1u const&) = delete;
void operator=(spgwu_s1u const&) = delete;
//void handle_itti_msg (oai::cn::core::itti::itti_s1u_echo_request& s) {};
void handle_itti_msg (std::shared_ptr<oai::cn::core::itti::itti_s1u_echo_response> m);
//void handle_itti_msg (oai::cn::core::itti::itti_s1u_error_indication& s) {};
//void handle_itti_msg (oai::cn::core::itti::itti_s1u_supported_extension_headers_notification& s) {};
//void handle_itti_msg (oai::cn::core::itti::itti_s1u_end_marker& s) {};
//void send_msg (oai::cn::core::itti::itti_s1u_echo_request& s) {};
//void send_msg (oai::cn::core::itti::itti_s1u_echo_response& s);
//void send_msg (oai::cn::core::itti::itti_s1u_error_indication& s) {};
//void send_msg (oai::cn::core::itti::itti_s1u_supported_extension_headers_notification& s) {};
//void send_msg (oai::cn::core::itti::itti_s1u_end_marker& s) {};
void handle_receive_s1u_msg( proto::gtpv1u::gtpv1u_msg& msg, const struct sockaddr_storage& r_endpoint, const socklen_t& r_endpoint_addr_len);
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);
void send_g_pdu(const struct in_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes);
void send_g_pdu(const struct in6_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes);
void time_out_itti_event(const uint32_t timer_id);
};
}
#endif /* FILE_SGWU_S1U_HPP_SEEN */
......@@ -65,6 +65,10 @@ void spgwu_app_task (void *args_p)
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case S1U_ECHO_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_s1u_echo_request>(shared_msg));
break;
case SXAB_SESSION_ESTABLISHMENT_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_establishment_request>(shared_msg));
break;
......@@ -111,13 +115,6 @@ spgwu_app::spgwu_app (const std::string& config_file)
spgwu_cfg.execute();
spgwu_cfg.display();
// teid_s11_cp = 0;
// teid_s5s8_cp = 0;
// teid_s5s8_up = 0;
// imsi2sgwu_eps_bearer_context = {};
// s11lteid2sgwu_eps_bearer_context = {};
// s5s8lteid2sgwu_contexts = {};
// s5s8uplteid = {};
if (itti_inst->create_task(TASK_SPGWU_APP, spgwu_app_task, nullptr) ) {
Logger::spgwu_app().error( "Cannot create task TASK_SPGWU_APP" );
throw std::runtime_error( "Cannot create task TASK_SPGWU_APP" );
......@@ -149,9 +146,27 @@ spgwu_app::~spgwu_app()
if (spgwu_sx_inst) delete spgwu_sx_inst;
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_s1u_echo_request> m)
{
Logger::spgwu_app().debug("Received %s ", m->get_msg_name());
itti_s1u_echo_response *s1u_resp = new itti_s1u_echo_response(TASK_SPGWU_APP, TASK_SPGWU_S1U);
// May insert a call to a function here(throttle for example)
s1u_resp->gtp_ies.r_endpoint = m->gtp_ies.r_endpoint;
s1u_resp->gtp_ies.r_endpoint_addr_len = m->gtp_ies.r_endpoint_addr_len;
s1u_resp->gtp_ies.teid = m->gtp_ies.teid;
s1u_resp->gtp_ies.sequence_number = m->gtp_ies.sequence_number;
std::shared_ptr<itti_s1u_echo_response> msg = std::shared_ptr<itti_s1u_echo_response>(s1u_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_SPGWU_S1U", s1u_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_establishment_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_ESTABLISHMENT_REQUEST seid " SEID_FMT " ", m->seid);
Logger::spgwu_app().info("Received SXAB_SESSION_ESTABLISHMENT_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_establishment_response *sx_resp = new itti_sxab_session_establishment_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_establishment_request(m, sx_resp);
......@@ -172,7 +187,7 @@ void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_e
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_modification_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_MODIFICATION_REQUEST seid " SEID_FMT " ", m->seid);
Logger::spgwu_app().info("Received SXAB_SESSION_MODIFICATION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_modification_response *sx_resp = new itti_sxab_session_modification_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_modification_request(m, sx_resp);
......@@ -188,7 +203,7 @@ void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_m
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_deletion_request> m)
{
Logger::spgwu_sx().info("Received SXAB_SESSION_DELETION_REQUEST seid " SEID_FMT " ", m->seid);
Logger::spgwu_app().info("Received SXAB_SESSION_DELETION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_deletion_response *sx_resp = new itti_sxab_session_deletion_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_deletion_request(m, sx_resp);
......
......@@ -31,6 +31,7 @@
#include "common_root_types.h"
#include "itti_msg_sxab.hpp"
#include "itti_msg_s1u.hpp"
#include <boost/atomic.hpp>
......@@ -48,52 +49,7 @@ private:
std::thread::id thread_id;
std::thread thread;
// teid generators (linear)
// boost::atomic<teid_t> teid_sxab_cp;
// boost::atomic<teid_t> teid_s5s8_up;
// /* There shall be only one pair of TEID-C per UE over the S11 and the S4 interfaces. The same tunnel shall be
// shared for the control messages related to the same UE operation. A TEID-C on the S11/S4 interface shall be
// released after all its associated EPS bearers are deleted.*/
// std::map<imsi64_t, std::shared_ptr<sgwu_eps_bearer_context>> imsi2sgwu_eps_bearer_context;
// std::map<teid_t, std::shared_ptr<sgwu_eps_bearer_context>> s11lteid2sgwu_eps_bearer_context;
//
// std::map<teid_t, std::pair<std::shared_ptr<sgwu_eps_bearer_context>, std::shared_ptr<sgwu_pdn_connection>>> s5s8lteid2sgwu_contexts;
// std::set<teid_t> s5s8uplteid; // In case of overflow of generator of teid_t
//
// teid_t generate_s11_cp_teid();
// bool is_s11c_teid_exist(const teid_t& teid_s11_cp) const;
//
// bool is_s5s8sgwu_teid_2_sgwu_contexts(const teid_t& sgwu_teid) const;
//
// // s11lteid2sgwu_eps_bearer_context collection
// bool is_s11sgwu_teid_2_sgwu_eps_bearer_context(const teid_t& sgwu_teid) const;
//
// bool is_imsi64_2_sgwu_eps_bearer_context(const imsi64_t& imsi64) const;
// void set_imsi64_2_sgwu_eps_bearer_context(const imsi64_t& imsi64, std::shared_ptr<sgwu_eps_bearer_context> sebc);
//
// teid_t generate_s5s8_cp_teid();
// bool is_s5s8c_teid_exist(const teid_t& teid_s5s8_cp)const;
//
// bool is_s5s8u_teid_exist(const teid_t& teid_s5s8_up) const;
public:
// key is S11 S-GW local teid, value is S11 tunnel id pair
// map<teid_t, int> s11teid2mme_hashtable;
// key is paa, value is S11 s-gw local teid
//obj_hash_table_uint64_t *ip2s11teid;
// key is S1-U S-GW local teid
////hash_table_t *s1uteid2enb_hashtable;
// the key of this hashtable is the S11 s-gw local teid.
//hash_table_ts_t *s11_bearer_context_information_hashtable;
/* The TEID-C shall be unique per PDN-Connection on GTP based S2a, S2b, S5 and S8 interfaces. The same
tunnel shall be shared for the control messages related to all bearers associated to
the PDN-Connection. A TEID-C on the S2a/S2b/S5/S8 interface shall be released after all its associated EPS bearers are deleted. */
//gtpv1u_data_t gtpv1u_data;
explicit spgwu_app(const std::string& config_file);
~spgwu_app();
......@@ -102,6 +58,7 @@ public:
teid_t generate_s5s8_up_teid();
void handle_itti_msg (std::shared_ptr<oai::cn::core::itti::itti_s1u_echo_request> m);
// void handle_itti_msg core::(itti::itti_sxab_heartbeat_request& m);
......@@ -117,9 +74,9 @@ public:
// void handle_itti_msg (core::itti::itti_sxab_pfcp_version_not_supported_response& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_node_report_request& m);
// void handle_itti_msg (core::itti::itti_sxab_pfcp_node_report_response& m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_establishment_request> m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_modification_request> m);
void handle_itti_msg (std::shared_ptr<core::itti::itti_sxab_session_deletion_request> m);
void handle_itti_msg (std::shared_ptr<oai::cn::core::itti::itti_sxab_session_establishment_request> m);
void handle_itti_msg (std::shared_ptr<oai::cn::core::itti::itti_sxab_session_modification_request> m);
void handle_itti_msg (std::shared_ptr<oai::cn::core::itti::itti_sxab_session_deletion_request> m);
// void handle_itti_msg (core::itti::itti_sxab_session_deletion_response& m);
// void handle_itti_msg (core::itti::itti_sxab_session_report_request& m);
// void handle_itti_msg (core::itti::itti_sxab_session_report_response& m);
......
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