Skip to content
Snippets Groups Projects
Commit a94a7bce authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

Merge branch 'pdu_session_release_v1.0' into 'develop'

Add PDU Session Release procedure (UE-Initiated)

See merge request oai/oai-cn5g-smf!4
parents 8f42b093 7375681c
No related branches found
No related tags found
1 merge request!4Add PDU Session Release procedure (UE-Initiated)
Showing
with 469 additions and 1712 deletions
...@@ -75,7 +75,7 @@ mkdir build ...@@ -75,7 +75,7 @@ mkdir build
cd build cd build
cmake .. cmake ..
make make
sudo ./udm-server sudo ./udm-server -i 172.16.1.103
## Build and launch AMF server ## Build and launch AMF server
cd /oai-cn5g-smf/src/test/amf cd /oai-cn5g-smf/src/test/amf
...@@ -83,7 +83,7 @@ mkdir build ...@@ -83,7 +83,7 @@ mkdir build
cd build cd build
cmake .. cmake ..
make make
sudo ./amf-server sudo ./amf-server -i 172.16.1.102
## Build and launch AMF client ## Build and launch AMF client
cd /oai-cn5g-smf/src/test/amf_client cd /oai-cn5g-smf/src/test/amf_client
...@@ -91,6 +91,6 @@ mkdir build ...@@ -91,6 +91,6 @@ mkdir build
cd build cd build
cmake .. cmake ..
make make
./amf-client ./amf-client -i 172.16.1.101
...@@ -82,47 +82,6 @@ typedef struct s_nssai // section 28.4, TS23.003 ...@@ -82,47 +82,6 @@ typedef struct s_nssai // section 28.4, TS23.003
typedef uint8_t pdu_session_id; typedef uint8_t pdu_session_id;
//should move to 24.501
enum pdu_session_type_e {
PDU_SESSION_TYPE_E_UNKNOWN = 0,
PDU_SESSION_TYPE_E_IPV4 = 1,
PDU_SESSION_TYPE_E_IPV6 = 2,
PDU_SESSION_TYPE_E_IPV4V6 = 3,
PDU_SESSION_TYPE_E_UNSTRUCTURED = 4,
PDU_SESSION_TYPE_E_ETHERNET = 5,
PDU_SESSION_TYPE_E_RESERVED = 7,
};
static const std::vector<std::string> pdu_session_type_e2str = { "Error",
"IPV4", "IPV6", "IPV4V6", "UNSTRUCTURED", "ETHERNET", "IPV4V6", "RESERVED" };
typedef struct pdu_session_type_s {
uint8_t pdu_session_type;
pdu_session_type_s()
:
pdu_session_type(PDU_SESSION_TYPE_E_IPV4) {
}
pdu_session_type_s(const uint8_t &p)
:
pdu_session_type(p) {
}
pdu_session_type_s(const struct pdu_session_type_s &p)
:
pdu_session_type(p.pdu_session_type) {
}
bool operator==(const struct pdu_session_type_s &p) const {
return (p.pdu_session_type == pdu_session_type);
}
//------------------------------------------------------------------------------
bool operator==(const pdu_session_type_e &p) const {
return (p == pdu_session_type);
}
//------------------------------------------------------------------------------
const std::string& toString() const {
return pdu_session_type_e2str.at(pdu_session_type);
}
} pdu_session_type_t;
//SMF + AMF + 3GPP TS 29.571 (Common data) //SMF + AMF + 3GPP TS 29.571 (Common data)
enum class http_response_codes_e { enum class http_response_codes_e {
HTTP_RESPONSE_CODE_OK = 200, HTTP_RESPONSE_CODE_OK = 200,
......
/*
* 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 gtpv1u;
//------------------------------------------------------------------------------
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);}
}
//------------------------------------------------------------------------------
gtpv1u_msg::gtpv1u_msg(const gtpv1u_error_indication& gtp_ies) : gtpv1u_msg_header() {
ies = {};
set_message_type(GTPU_ERROR_INDICATION);
if (gtp_ies.tunnel_endpoint_identifier_data_i.first) {std::shared_ptr<gtpv1u_tunnel_endpoint_identifier_data_i_ie> sie(new gtpv1u_tunnel_endpoint_identifier_data_i_ie(gtp_ies.tunnel_endpoint_identifier_data_i.second)); add_ie(sie);}
if (gtp_ies.gtp_u_peer_address.first) {std::shared_ptr<gtpv1u_gtp_u_peer_address_ie> sie(new gtpv1u_gtp_u_peer_address_ie(gtp_ies.gtp_u_peer_address.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);}
}
This diff is collapsed.
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
add_library(GTPV1U STATIC
3gpp_29.281.cpp
gtpv1u.cpp
)
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}/gtpv1u)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
/*
* 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 gtpu.h
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_GTPU_SEEN
#define FILE_GTPU_SEEN
#include <endian.h>
#include <stdint.h>
struct gtpuhdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int pn:1;
unsigned int s:1;
unsigned int e:1;
unsigned int spare:1;
unsigned int pt:1;
unsigned int version:3;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:3;
unsigned int pt:1;
unsigned int spare:1;
unsigned int e:1;
unsigned int s:1;
unsigned int pn:1;
#else
# error "Please fix <bits/endian.h>"
#endif
// Message Type: This field indicates the type of GTP-U message.
uint8_t message_type;
// Length: This field indicates the length in octets of the payload, i.e. the rest of the packet following the mandatory
// part of the GTP header (that is the first 8 octets). The Sequence Number, the N-PDU Number or any Extension
// headers shall be considered to be part of the payload, i.e. included in the length count.
uint16_t message_length;
// Tunnel Endpoint Identifier (TEID): This field unambiguously identifies a tunnel endpoint in the receiving
// GTP-U protocol entity. The receiving end side of a GTP tunnel locally assigns the TEID value the transmitting
// side has to use. The TEID value shall be assigned in a non-predictable manner for PGW S5/S8/S2a/S2b
// interfaces (see 3GPP TS 33.250 [32]). The TEID shall be used by the receiving entity to find the PDP context,
// except for the following cases:
// -) The Echo Request/Response and Supported Extension Headers notification messages, where the Tunnel
// Endpoint Identifier shall be set to all zeroes
// -) The Error Indication message where the Tunnel Endpoint Identifier shall be set to all zeros.
uint32_t teid;
/*The options start here. */
};
#endif
/*
* 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 gtpv1u.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "common_root_types.h"
#include "conversions.hpp"
#include "gtpu.h"
#include "gtpv1u.hpp"
#include <cstdlib>
#include <sched.h>
using namespace gtpv1u;
using namespace std;
extern itti_mw *itti_inst;
////------------------------------------------------------------------------------
//void udp_server::handle_receive(const int& error, std::size_t bytes_transferred)
//{
// if (!error) {
// Logger::udp().trace( "udp_server::handle_receive on %s:%d from %s:%d",
// socket_.local_endpoint().address().to_string().c_str(), socket_.local_endpoint().port(),
// remote_endpoint_.address().to_string().c_str(), remote_endpoint_.port());
// if (app_) {
// app_->handle_receive(recv_buffer_.data(), bytes_transferred, remote_endpoint_);
// } else {
// Logger::udp().error( "No upper layer configured for handling UDP packet");
// }
// start_receive(app_);
// } else {
// Logger::udp().error( "udp_server::handle_receive err=%s/%d: %s", error.category().name(), error.value(), error.message());
// }
//}
//------------------------------------------------------------------------------
gtpu_l4_stack::gtpu_l4_stack(const struct in_addr& address, const uint16_t port_num, const util::thread_sched_params& sched_params) :
udp_s(udp_server(address, port_num))
{
Logger::gtpv1_u().info( "gtpu_l4_stack created listening to %s:%d", conv::toString(address).c_str(), port_num);
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
restart_counter = 0;
udp_s.start_receive(this, sched_params);
}
//------------------------------------------------------------------------------
gtpu_l4_stack::gtpu_l4_stack(const struct in6_addr& address, const uint16_t port_num, const util::thread_sched_params& sched_params) :
udp_s(udp_server(address, port_num))
{
Logger::gtpv1_u().info( "gtpu_l4_stack created listening to %s:%d", conv::toString(address).c_str(), port_num);
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
restart_counter = 0;
udp_s.start_receive(this, sched_params);
}
//------------------------------------------------------------------------------
gtpu_l4_stack::gtpu_l4_stack(char * address, const uint16_t port_num, const util::thread_sched_params& sched_params) :
udp_s(udp_server(address, port_num))
{
Logger::gtpv1_u().info( "gtpu_l4_stack created listening to %s:%d", address, port_num);
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
restart_counter = 0;
udp_s.start_receive(this, sched_params);
}
//------------------------------------------------------------------------------
uint32_t gtpu_l4_stack::get_next_seq_num() {
seq_num++;
if (seq_num & 0x80000000) {
seq_num = 0;
}
return seq_num;
}
//------------------------------------------------------------------------------
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");
}
//------------------------------------------------------------------------------
bool gtpu_l4_stack::check_initial_message_type(const uint8_t initial)
{
switch (initial) {
case GTPU_ECHO_REQUEST:
case GTPU_END_MARKER:
return true;
break;
default:
return false;
}
}
//------------------------------------------------------------------------------
bool gtpu_l4_stack::check_triggered_message_type(const uint8_t initial, const uint8_t triggered)
{
Logger::gtpv1_u().info( "check_triggered_message_type GTPV1-U msg type %d/%d", (int)initial, (int)triggered);
switch (initial) {
case GTPU_ECHO_REQUEST:
if (triggered == GTPU_ECHO_RESPONSE) return true;
return false;
break;
case GTPU_ERROR_INDICATION:
case GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION:
return true;
break;
default:
return false;
}
}
//------------------------------------------------------------------------------
void gtpu_l4_stack::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 gtpu_l4_stack::send_g_pdu(const struct sockaddr_in& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len)
{
struct gtpuhdr *gtpuhdr = reinterpret_cast<struct gtpuhdr *>(reinterpret_cast<uintptr_t>(payload) - (uintptr_t)sizeof(struct gtpuhdr));
gtpuhdr->spare = 0;
gtpuhdr->e = 0;
gtpuhdr->s = 0;
gtpuhdr->pn = 0;
gtpuhdr->pt = 1;
gtpuhdr->version = 1;
gtpuhdr->message_type = GTPU_G_PDU;
gtpuhdr->message_length = htobe16(payload_len);
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_g_pdu(const struct sockaddr_in6& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len)
{
struct gtpuhdr *gtpuhdr = reinterpret_cast<struct gtpuhdr *>(reinterpret_cast<uintptr_t>(payload) - (uintptr_t)sizeof(struct gtpuhdr));
gtpuhdr->spare = 0;
gtpuhdr->e = 0;
gtpuhdr->s = 0;
gtpuhdr->pn = 0;
gtpuhdr->pt = 1;
gtpuhdr->version = 1;
gtpuhdr->message_type = GTPU_G_PDU;
gtpuhdr->message_length = htobe16(payload_len);
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();
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)
{
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();
udp_s.async_send_to(reinterpret_cast<const char*>(bstream.c_str()), bstream.length(), gtp_ies.r_endpoint);
}
/*
* 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 gtpv1u.hpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_GTPV1U_HPP_SEEN
#define FILE_GTPV1U_HPP_SEEN
#include "3gpp_29.281.hpp"
#include "itti.hpp"
#include "msg_gtpv1u.hpp"
#include "thread_sched.hpp"
#include "udp.hpp"
#include <iostream>
#include <map>
#include <memory>
#include <stdint.h>
#include <string>
#include <system_error>
#include <thread>
#include <utility>
#include <vector>
namespace gtpv1u {
static const uint16_t default_port = 2152;
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))
protected:
uint32_t id;
udp_server udp_s;
// seems no need for std::atomic_uint32_t
uint32_t seq_num;
uint32_t restart_counter;
static bool check_initial_message_type(const uint8_t initial);
static bool check_triggered_message_type(const uint8_t initial, const uint8_t triggered);
uint32_t get_next_seq_num();
public:
static const uint8_t version = 1;
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 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);
void send_g_pdu(const struct sockaddr_in6& peer_addr, const teid_t teid, const char* payload, const ssize_t payload_len);
void send_response(const gtpv1u_echo_response& gtp_ies);
void send_indication(const gtpv1u_error_indication& gtp_ies);
};
} // namespace gtpv1u
#endif /* FILE_GTPV1U_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file msg_gtpv1u.hpp
\brief
\author Sebastien ROUX, Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef MSG_GTPV1U_HPP_INCLUDED_
#define MSG_GTPV1U_HPP_INCLUDED_
#include "3gpp_29.274.h"
#include "3gpp_29.281.h"
#include "endpoint.hpp"
#include "common_defs.h"
#include <utility>
#include <vector>
#include <sys/socket.h>
namespace gtpv1u {
class gtpv1u_ies_container {
public:
static const uint8_t msg_id = 0;
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(), teid(), sequence_number(), npdu_number() {}
gtpv1u_ies_container(const gtpv1u_ies_container& i) :
r_endpoint(i.r_endpoint),
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(teid, other.teid);
std::swap(sequence_number, other.sequence_number);
std::swap(npdu_number, other.npdu_number);
return *this;
}
virtual bool get(recovery_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_RECOVERY);}
virtual bool get(tunnel_endpoint_identifier_data_i_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_TUNNEL_ENDPOINT_IDENTIFIER_DATA_I);}
virtual bool get(gtp_u_peer_address_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_GTP_U_PEER_ADDRESS);}
virtual bool get(extension_header_type_list_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_EXTENSION_HEADER_TYPE_LIST);}
virtual bool get(private_extension_t& v) const {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_PRIVATE_EXTENSION);}
virtual void set(const recovery_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_RECOVERY);}
virtual void set(const tunnel_endpoint_identifier_data_i_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_TUNNEL_ENDPOINT_IDENTIFIER_DATA_I);}
virtual void set(const gtp_u_peer_address_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_GTP_U_PEER_ADDRESS);}
virtual void set(const extension_header_type_list_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_EXTENSION_HEADER_TYPE_LIST);}
virtual void set(const private_extension_t& v) {throw gtpu_msg_illegal_ie_exception(0, GTPU_IE_PRIVATE_EXTENSION);}
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;}
};
//------------------------------------------------------------------------------
class gtpv1u_echo_request : public gtpv1u_ies_container {
public:
static const uint8_t msg_id = GTPU_ECHO_REQUEST;
std::pair<bool, private_extension_t> 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;
}
static const char* get_msg_name() {return "GTPU_ECHO_REQUEST";};
bool get(private_extension_t& v) const {if (private_extension.first) {v = private_extension.second;return true;}return false;}
void set(const private_extension_t& v) {private_extension.first = true; private_extension.second = v;}
};
//------------------------------------------------------------------------------
class gtpv1u_echo_response : public gtpv1u_ies_container {
public:
static const uint8_t msg_id = GTPU_ECHO_RESPONSE;
std::pair<bool, recovery_t> recovery;
std::pair<bool, private_extension_t> private_extension;
gtpv1u_echo_response(): gtpv1u_ies_container(), recovery(), 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;
}
bool get(recovery_t& v) const {if (recovery.first) {v = recovery.second;return true;}return false;}
bool get(private_extension_t& v) const {if (private_extension.first) {v = private_extension.second;return true;}return false;}
void set(const recovery_t& v) {recovery.first = true; recovery.second = v;}
void set(const private_extension_t& v) {private_extension.first = true; private_extension.second = v;}
};
//------------------------------------------------------------------------------
class gtpv1u_error_indication : public gtpv1u_ies_container {
public:
static const uint8_t msg_id = GTPU_ERROR_INDICATION;
std::pair<bool, tunnel_endpoint_identifier_data_i_t> tunnel_endpoint_identifier_data_i;
std::pair<bool, gtp_u_peer_address_t> gtp_u_peer_address;
std::pair<bool, private_extension_t> 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_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);
return *this;
}
static const char* get_msg_name() {return "GTPU_ERROR_INDICATION";};
bool get(tunnel_endpoint_identifier_data_i_t& v) const {if (tunnel_endpoint_identifier_data_i.first) {v = tunnel_endpoint_identifier_data_i.second;return true;}return false;}
bool get(gtp_u_peer_address_t& v) const {if (gtp_u_peer_address.first) {v = gtp_u_peer_address.second;return true;}return false;}
bool get(private_extension_t& v) const {if (private_extension.first) {v = private_extension.second;return true;}return false;}
void set(const tunnel_endpoint_identifier_data_i_t& v) {tunnel_endpoint_identifier_data_i.first = true; tunnel_endpoint_identifier_data_i.second = v;}
void set(const gtp_u_peer_address_t& v) {gtp_u_peer_address.first = true; gtp_u_peer_address.second = v;}
void set(const private_extension_t& v) {private_extension.first = true; private_extension.second = v;}
};
//------------------------------------------------------------------------------
class gtpv1u_supported_extension_headers_notification : public gtpv1u_ies_container {
public:
static const uint8_t msg_id = GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION;
std::pair<bool, extension_header_type_list_t> extension_header_type_list;
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;
}
static const char* get_msg_name() {return "GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION";};
bool get(extension_header_type_list_t& v) const {if (extension_header_type_list.first) {v = extension_header_type_list.second;return true;}return false;}
void set(const extension_header_type_list_t& v) {extension_header_type_list.first = true; extension_header_type_list.second = v;}
};
//------------------------------------------------------------------------------
class gtpv1u_end_marker : public gtpv1u_ies_container {
public:
static const uint8_t msg_id = GTPU_END_MARKER;
std::pair<bool, private_extension_t> private_extension;
gtpv1u_end_marker() : gtpv1u_ies_container(),
private_extension() {}
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;
}
static const char* get_msg_name() {return "GTPU_END_MARKER";};
bool get(private_extension_t& v) const {if (private_extension.first) {v = private_extension.second;return true;}return false;}
void set(const private_extension_t& v) {private_extension.first = true; private_extension.second = v;}
};
} // namespace gtpv1u
#endif /* MSG_GTPV1U_HPP_INCLUDED_ */
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
/* /*
* This file contains NAS header bits format * This file contains NAS header bits format
* Refer TS24.007 TS24.501 * Refer TS24.007 TS24.501
* Auther: Puzyu Dukl * Author: Puzyu Dukl (BUPT), Tien-Thinh NGUYEN (EURECOM)
* Time: * Time:
* Email: * Email:
*/ */
...@@ -246,64 +246,6 @@ enum class cause_value_5gsm_e { ...@@ -246,64 +246,6 @@ enum class cause_value_5gsm_e {
CAUSE_100_CONDITIONAL_IE_ERROR = 100, CAUSE_100_CONDITIONAL_IE_ERROR = 100,
CAUSE_101_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101, CAUSE_101_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
CAUSE_111_PROTOCOL_ERROR_UNSPECIFIED = 111 CAUSE_111_PROTOCOL_ERROR_UNSPECIFIED = 111
/*
Cause #8 – Operator Determined Barring
Cause #26 – Insufficient resources
Cause #27 – Missing or unknown DNN
Cause #28 – Unknown PDU session type
Cause #29 – User authentication or authorization failed
Cause #31 – Request rejected, unspecified
Cause #32 – Service option not supported
Cause #33 – Requested service option not subscribed
Cause #35 – PTI already in use
Cause #36 – Regular deactivation
Cause #38 – Network failure
Cause #39 – Reactivation requested
Cause #41 – Semantic error in the TFT operation
Cause #42 – Syntactical error in the TFT operation
Cause #43 –Invalid PDU session identity
Cause #44 – Semantic errors in packet filter(s)
Cause #45 – Syntactical error in packet filter(s)
Cause #46 –Out of LADN service area
Cause #47 –PTI mismatch
Cause #50 – PDU session type IPv4 only allowed
Cause #51 – PDU session type IPv6 only allowed
Cause #54 –PDU session does not exist
Cause #67 – Insufficient resources for specific slice and DNN
Cause #68 – Not supported SSC mode
Cause #69 –Insufficient resources for specific slice
Cause #70 – Missing or unknown DNN in a slice
Cause #81 – Invalid PTI value
Cause #82 – Maximum data rate per UE for user-plane integrity protection is too low
Cause #83 – Semantic error in the QoS operation
Cause #84 – Syntactical error in the QoS operation
Cause #85 – Invalid mapped EPS bearer identity
//Protocol errors
Cause #95 – Semantically incorrect message
Cause #96 – Invalid mandatory information
Cause #97 – Message type non-existent or not implemented
Cause #98 – Message type not compatible with protocol state
Cause #99 – Information element non-existent or not implemented
Cause #100 – Conditional IE error
Cause #101 – Message not compatible with protocol state
Cause #111 – Protocol error, unspecified
*/
};
enum cause_value_protocol_errors_e {
CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE = 95
/*
Cause #95 – Semantically incorrect message
Cause #96 – Invalid mandatory information
Cause #97 – Message type non-existent or not implemented
Cause #98 – Message type not compatible with protocol state
Cause #99 – Information element non-existent or not implemented
Cause #100 – Conditional IE error
Cause #101 – Message not compatible with protocol state
Cause #111 – Protocol error, unspecified
*/
}; };
//The 5GSM sublayer states for PDU session handling in the network //The 5GSM sublayer states for PDU session handling in the network
...@@ -348,6 +290,49 @@ enum notification_control_e { ...@@ -348,6 +290,49 @@ enum notification_control_e {
static const std::vector<std::string> notification_control_e2str = { "ERROR", static const std::vector<std::string> notification_control_e2str = { "ERROR",
"REQUESTED", "NOT_REQUESTED" }; "REQUESTED", "NOT_REQUESTED" };
//PDU Session Type value
enum pdu_session_type_e {
PDU_SESSION_TYPE_E_UNKNOWN = 0,
PDU_SESSION_TYPE_E_IPV4 = 1,
PDU_SESSION_TYPE_E_IPV6 = 2,
PDU_SESSION_TYPE_E_IPV4V6 = 3,
PDU_SESSION_TYPE_E_UNSTRUCTURED = 4,
PDU_SESSION_TYPE_E_ETHERNET = 5,
PDU_SESSION_TYPE_E_RESERVED = 7,
};
static const std::vector<std::string> pdu_session_type_e2str = { "Error",
"IPV4", "IPV6", "IPV4V6", "UNSTRUCTURED", "ETHERNET", "IPV4V6", "RESERVED" };
typedef struct pdu_session_type_s {
uint8_t pdu_session_type;
pdu_session_type_s()
:
pdu_session_type(PDU_SESSION_TYPE_E_IPV4) {
}
pdu_session_type_s(const uint8_t &p)
:
pdu_session_type(p) {
}
pdu_session_type_s(const struct pdu_session_type_s &p)
:
pdu_session_type(p.pdu_session_type) {
}
bool operator==(const struct pdu_session_type_s &p) const {
return (p.pdu_session_type == pdu_session_type);
}
//------------------------------------------------------------------------------
bool operator==(const pdu_session_type_e &p) const {
return (p == pdu_session_type);
}
//------------------------------------------------------------------------------
const std::string& toString() const {
return pdu_session_type_e2str.at(pdu_session_type);
}
} pdu_session_type_t;
#endif #endif
#endif #endif
...@@ -6,104 +6,105 @@ ...@@ -6,104 +6,105 @@
#include "TLVDecoder.h" #include "TLVDecoder.h"
#include "SNSSAI.h" #include "SNSSAI.h"
int encode_snssai ( SNSSAI snssai, uint8_t iei, uint8_t * buffer, uint32_t len ) int encode_snssai(SNSSAI snssai, uint8_t iei, uint8_t *buffer, uint32_t len) {
{ uint32_t encoded = 0;
uint32_t encoded = 0; uint8_t ielen = 0;
uint8_t ielen = 0; uint8_t bitStream = 0;
uint8_t bitStream = 0; uint32_t bit32Stream = 0;
uint32_t bit32Stream = 0;
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(
CHECK_PDU_POINTER_AND_LENGTH_ENCODER (buffer,((iei > 0) ? SNSSAI_MINIMUM_LENGTH_TLV : SNSSAI_MINIMUM_LENGTH_TLV-1) , len); buffer,
((iei > 0) ? SNSSAI_MINIMUM_LENGTH_TLV : SNSSAI_MINIMUM_LENGTH_TLV-1),
if( iei >0 ) len);
{
*buffer=iei; if (iei > 0) {
encoded++; *buffer = iei;
}
ielen = snssai.len;
*(buffer + encoded) = ielen;
encoded++; encoded++;
}
bitStream = snssai.sst; ielen = snssai.len;
ENCODE_U8(buffer+encoded,bitStream,encoded);
*(buffer + encoded) = ielen;
if((ielen == SST_AND_SD_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT)) encoded++;
{
bit32Stream = snssai.sd;
ENCODE_U8(buffer+encoded,(uint8_t)bit32Stream,encoded);
ENCODE_U8(buffer+encoded,(uint8_t)(bit32Stream>>8),encoded);
ENCODE_U8(buffer+encoded,(uint8_t)(bit32Stream>>16),encoded);
}
if((ielen == SST_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT))
{
bitStream = snssai.mappedhplmnsst;
ENCODE_U8(buffer+encoded,bitStream,encoded);
}
if(ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT)
{
bit32Stream = snssai.mappedhplmnsd;
ENCODE_U8(buffer+encoded,(uint8_t)bit32Stream,encoded);
ENCODE_U8(buffer+encoded,(uint8_t)(bit32Stream>>8),encoded);
ENCODE_U8(buffer+encoded,(uint8_t)(bit32Stream>>16),encoded);
}
return encoded;
}
int decode_snssai ( SNSSAI * snssai, uint8_t iei, uint8_t * buffer, uint32_t len ) bitStream = snssai.sst;
{ ENCODE_U8(buffer + encoded, bitStream, encoded);
int decoded=0;
uint8_t ielen=0; if ((ielen == SST_AND_SD_LENGTH)
uint8_t bitStream = 0; || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGTH)
uint32_t bit32Stream = 0; || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH)) {
bit32Stream = snssai.sd;
ENCODE_U8(buffer + encoded, (uint8_t )bit32Stream, encoded);
ENCODE_U8(buffer + encoded, (uint8_t )(bit32Stream >> 8), encoded);
ENCODE_U8(buffer + encoded, (uint8_t )(bit32Stream >> 16), encoded);
}
if ((ielen == SST_AND_MAPPEDHPLMNSST_LENGTH)
|| (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGTH)
|| (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH)) {
bitStream = snssai.mappedhplmnsst;
ENCODE_U8(buffer + encoded, bitStream, encoded);
}
if (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH) {
bit32Stream = snssai.mappedhplmnsd;
ENCODE_U8(buffer + encoded, (uint8_t )bit32Stream, encoded);
ENCODE_U8(buffer + encoded, (uint8_t )(bit32Stream >> 8), encoded);
ENCODE_U8(buffer + encoded, (uint8_t )(bit32Stream >> 16), encoded);
}
return encoded;
}
if (iei > 0) int decode_snssai(SNSSAI *snssai, uint8_t iei, uint8_t *buffer, uint32_t len) {
{ int decoded = 0;
CHECK_IEI_DECODER (iei, *buffer); uint8_t ielen = 0;
decoded++; uint8_t bitStream = 0;
} uint32_t bit32Stream = 0;
ielen = *(buffer + decoded); if (iei > 0) {
CHECK_IEI_DECODER(iei, *buffer);
decoded++; decoded++;
CHECK_LENGTH_DECODER (len - decoded, ielen); }
snssai->len = ielen; ielen = *(buffer + decoded);
decoded++;
DECODE_U8(buffer+decoded,bitStream,decoded); CHECK_LENGTH_DECODER(len - decoded, ielen);
snssai->sst = bitStream;
snssai->len = ielen;
if((ielen == SST_AND_SD_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT))
{ DECODE_U8(buffer + decoded, bitStream, decoded);
DECODE_U8(buffer+decoded,bitStream,decoded); snssai->sst = bitStream;
bit32Stream = (uint32_t)(bitStream&0Xff);
DECODE_U8(buffer+decoded,bitStream,decoded); if ((ielen == SST_AND_SD_LENGTH)
bit32Stream |= (uint32_t)((bitStream<<8)&0xff00); || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGTH)
DECODE_U8(buffer+decoded,bitStream,decoded); || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH)) {
bit32Stream |= (uint32_t)((bitStream<<16)&0xff0000); DECODE_U8(buffer + decoded, bitStream, decoded);
bit32Stream = (uint32_t) (bitStream & 0Xff);
snssai->sd = bit32Stream; DECODE_U8(buffer + decoded, bitStream, decoded);
} bit32Stream |= (uint32_t) ((bitStream << 8) & 0xff00);
DECODE_U8(buffer + decoded, bitStream, decoded);
if((ielen == SST_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGHT) || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT)) bit32Stream |= (uint32_t) ((bitStream << 16) & 0xff0000);
{
DECODE_U8(buffer+decoded,bitStream,decoded); snssai->sd = bit32Stream;
snssai->mappedhplmnsst = bitStream; }
}
if(ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT) if ((ielen == SST_AND_MAPPEDHPLMNSST_LENGTH)
{ || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_LENGTH)
DECODE_U8(buffer+decoded,bitStream,decoded); || (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH)) {
bit32Stream = (uint32_t)(bitStream&0Xff); DECODE_U8(buffer + decoded, bitStream, decoded);
DECODE_U8(buffer+decoded,bitStream,decoded); snssai->mappedhplmnsst = bitStream;
bit32Stream |= (uint32_t)((bitStream<<8)&0xff00); }
DECODE_U8(buffer+decoded,bitStream,decoded); if (ielen == SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH) {
bit32Stream |= (uint32_t)((bitStream<<16)&0xff0000); DECODE_U8(buffer + decoded, bitStream, decoded);
bit32Stream = (uint32_t) (bitStream & 0Xff);
snssai->mappedhplmnsd = bit32Stream; DECODE_U8(buffer + decoded, bitStream, decoded);
} bit32Stream |= (uint32_t) ((bitStream << 8) & 0xff00);
DECODE_U8(buffer + decoded, bitStream, decoded);
return decoded; bit32Stream |= (uint32_t) ((bitStream << 16) & 0xff0000);
snssai->mappedhplmnsd = bit32Stream;
}
return decoded;
} }
...@@ -10,24 +10,23 @@ ...@@ -10,24 +10,23 @@
#define SNSSAI_MINIMUM_LENGTH_TLV 3 #define SNSSAI_MINIMUM_LENGTH_TLV 3
#define SNSSAI_MAXIMUM_LENGTH_TLV 10 #define SNSSAI_MAXIMUM_LENGTH_TLV 10
typedef enum{ typedef enum {
SST_LENGHT = 0b00000001, SST_LENGTH = 0b00000001,
SST_AND_MAPPEDHPLMNSST_LENGHT = 0b00000010, SST_AND_MAPPEDHPLMNSST_LENGTH = 0b00000010,
SST_AND_SD_LENGHT = 0b00000100, SST_AND_SD_LENGTH = 0b00000100,
SST_AND_SD_AND_MAPPEDHPLMNSST_LENGHT = 0b00000101, SST_AND_SD_AND_MAPPEDHPLMNSST_LENGTH = 0b00000101,
SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGHT = 0b00001000 SST_AND_SD_AND_MAPPEDHPLMNSST_AND_MAPPEDHPLMNSD_LENGTH = 0b00001000
}length_of_snssai_contents; } length_of_snssai_contents;
typedef struct {
typedef struct{ length_of_snssai_contents len;
length_of_snssai_contents len; uint8_t sst;
uint8_t sst; uint32_t sd :24;
uint32_t sd:24; uint8_t mappedhplmnsst;
uint8_t mappedhplmnsst; uint32_t mappedhplmnsd;
uint32_t mappedhplmnsd;
} SNSSAI; } SNSSAI;
int encode_snssai ( SNSSAI snssai, uint8_t iei, uint8_t * buffer, uint32_t len ) ; int encode_snssai(SNSSAI snssai, uint8_t iei, uint8_t *buffer, uint32_t len);
int decode_snssai ( SNSSAI * snssai, uint8_t iei, uint8_t * buffer, uint32_t len ) ; int decode_snssai(SNSSAI *snssai, uint8_t iei, uint8_t *buffer, uint32_t len);
#endif #endif
...@@ -271,9 +271,6 @@ ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv2c ${CMAKE_CURRENT_BI ...@@ -271,9 +271,6 @@ ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv2c ${CMAKE_CURRENT_BI
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pfcp ${CMAKE_CURRENT_BINARY_DIR}/pfcp) 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) ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/udp ${CMAKE_CURRENT_BINARY_DIR}/udp)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/api-server ${CMAKE_CURRENT_BINARY_DIR}/api-server) ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/api-server ${CMAKE_CURRENT_BINARY_DIR}/api-server)
if(${SGW_AUTOTEST})
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/gtpv1u ${CMAKE_CURRENT_BINARY_DIR}/gtpv1u)
endif(${SGW_AUTOTEST})
#ENABLE_TESTING() #ENABLE_TESTING()
#ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/test ${CMAKE_CURRENT_BINARY_DIR}/test) #ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/test ${CMAKE_CURRENT_BINARY_DIR}/test)
...@@ -381,9 +378,6 @@ IF(STATIC_LINKING) ...@@ -381,9 +378,6 @@ IF(STATIC_LINKING)
SET(ASAN) SET(ASAN)
ENDIF(STATIC_LINKING) ENDIF(STATIC_LINKING)
if(${SGW_AUTOTEST})
SET(GTPV1U_LIB GTPV1U)
endif(${SGW_AUTOTEST})
target_link_libraries (smf ${ASAN} -Wl,--start-group CN_UTILS SMF UDP ${GTPV1U_LIB} GTPV2C PFCP 3GPP_COMMON_TYPES SMF_API -lnettle ${NETTLE_LIBRARIES} ${CRYPTO_LIBRARIES} NAS gflags glog dl double-conversion folly -Wl,--end-group pthread m rt config++ event boost_system pistache curl) target_link_libraries (smf ${ASAN} -Wl,--start-group CN_UTILS SMF UDP GTPV2C PFCP 3GPP_COMMON_TYPES SMF_API -lnettle ${NETTLE_LIBRARIES} ${CRYPTO_LIBRARIES} NAS gflags glog dl double-conversion folly -Wl,--end-group pthread m rt config++ event boost_system pistache curl)
...@@ -516,7 +516,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -516,7 +516,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
"NAS, pdu_session_type %d", "NAS, pdu_session_type %d",
decoded_nas_msg.plain.sm.pdu_session_establishment_request decoded_nas_msg.plain.sm.pdu_session_establishment_request
._pdusessiontype.pdu_session_type_value); ._pdusessiontype.pdu_session_type_value);
smreq->req.set_pdu_session_type(decoded_nas_msg.plain.sm.pdu_session_establishment_request._pdusessiontype.pdu_session_type_value); smreq->req.set_pdu_session_type(
decoded_nas_msg.plain.sm.pdu_session_establishment_request
._pdusessiontype.pdu_session_type_value);
} }
//Get necessary information //Get necessary information
...@@ -564,6 +566,8 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -564,6 +566,8 @@ void smf_app::handle_pdu_session_create_sm_context_request(
Pistache::Http::Code::Forbidden, n1_sm_message_hex); Pistache::Http::Code::Forbidden, n1_sm_message_hex);
} }
context_req_msg.set_pti(pti);
//check pdu session id //check pdu session id
if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED ) if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED )
|| (pdu_session_id > PDU_SESSION_IDENTITY_LAST )) { || (pdu_session_id > PDU_SESSION_IDENTITY_LAST )) {
......
...@@ -56,10 +56,15 @@ namespace smf { ...@@ -56,10 +56,15 @@ namespace smf {
#define TASK_SMF_APP_TRIGGER_T3591 (0) #define TASK_SMF_APP_TRIGGER_T3591 (0)
#define TASK_SMF_APP_TIMEOUT_T3591 (1) #define TASK_SMF_APP_TIMEOUT_T3591 (1)
#define TASK_SMF_APP_TRIGGER_T3592 (2)
#define TASK_SMF_APP_TIMEOUT_T3592 (3)
//Table 10.3.2 @3GPP TS 24.501 V16.1.0 (2019-06) //Table 10.3.2 @3GPP TS 24.501 V16.1.0 (2019-06)
#define T3591_TIMER_VALUE_SEC 16 #define T3591_TIMER_VALUE_SEC 16
#define T3591_TIMER_MAX_RETRIES 4 #define T3591_TIMER_MAX_RETRIES 4
#define T3592_TIMER_VALUE_SEC 16
#define T3592_TIMER_MAX_RETRIES 4
typedef enum { typedef enum {
PDU_SESSION_ESTABLISHMENT = 1, PDU_SESSION_ESTABLISHMENT = 1,
......
...@@ -61,6 +61,42 @@ extern smf::smf_app *smf_app_inst; ...@@ -61,6 +61,42 @@ extern smf::smf_app *smf_app_inst;
extern smf::smf_n11 *smf_n11_inst; extern smf::smf_n11 *smf_n11_inst;
extern smf::smf_config smf_cfg; extern smf::smf_config smf_cfg;
//------------------------------------------------------------------------------
void smf_qos_flow::release_qos_flow() {
released = true;
}
//------------------------------------------------------------------------------
std::string smf_qos_flow::toString() const {
std::string s = { };
s.append("QoS Flow:\n");
s.append("\tFQI:\t\t\t\t").append(std::to_string((uint8_t) qfi.qfi)).append(
"\n");
s.append("\tUL FTEID:\t\t").append(ul_fteid.toString()).append("\n");
s.append("\tPDR ID UL:\t\t\t").append(std::to_string(pdr_id_ul.rule_id))
.append("\n");
s.append("\tPDR ID DL:\t\t\t").append(std::to_string(pdr_id_dl.rule_id))
.append("\n");
s.append("\tPRECEDENCE:\t\t\t").append(std::to_string(precedence.precedence))
.append("\n");
if (far_id_ul.first) {
s.append("\tFAR ID UL:\t\t\t").append(
std::to_string(far_id_ul.second.far_id)).append("\n");
}
if (far_id_dl.first) {
s.append("\tFAR ID DL:\t\t\t").append(
std::to_string(far_id_dl.second.far_id)).append("\n");
}
return s;
}
//------------------------------------------------------------------------------
void smf_qos_flow::deallocate_ressources() {
clear();
Logger::smf_app().info(
"Resources associated with this QoS Flow (%d) have been released",
(uint8_t) qfi.qfi);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_pdu_session::set(const paa_t &paa) { void smf_pdu_session::set(const paa_t &paa) {
switch (paa.pdn_type.pdn_type) { switch (paa.pdn_type.pdn_type) {
...@@ -68,21 +104,25 @@ void smf_pdu_session::set(const paa_t &paa) { ...@@ -68,21 +104,25 @@ void smf_pdu_session::set(const paa_t &paa) {
ipv4 = true; ipv4 = true;
ipv6 = false; ipv6 = false;
ipv4_address = paa.ipv4_address; ipv4_address = paa.ipv4_address;
pdn_type.pdn_type = paa.pdn_type.pdn_type;
break; break;
case PDN_TYPE_E_IPV6: case PDN_TYPE_E_IPV6:
ipv4 = false; ipv4 = false;
ipv6 = true; ipv6 = true;
ipv6_address = paa.ipv6_address; ipv6_address = paa.ipv6_address;
pdn_type.pdn_type = paa.pdn_type.pdn_type;
break; break;
case PDN_TYPE_E_IPV4V6: case PDN_TYPE_E_IPV4V6:
ipv4 = true; ipv4 = true;
ipv6 = true; ipv6 = true;
ipv4_address = paa.ipv4_address; ipv4_address = paa.ipv4_address;
ipv6_address = paa.ipv6_address; ipv6_address = paa.ipv6_address;
pdn_type.pdn_type = paa.pdn_type.pdn_type;
break; break;
case PDN_TYPE_E_NON_IP: case PDN_TYPE_E_NON_IP:
ipv4 = false; ipv4 = false;
ipv6 = false; ipv6 = false;
pdn_type.pdn_type = paa.pdn_type.pdn_type;
break; break;
default: default:
Logger::smf_app().error("smf_pdu_session::set(paa_t) Unknown PDN type %d", Logger::smf_app().error("smf_pdu_session::set(paa_t) Unknown PDN type %d",
...@@ -90,6 +130,37 @@ void smf_pdu_session::set(const paa_t &paa) { ...@@ -90,6 +130,37 @@ void smf_pdu_session::set(const paa_t &paa) {
} }
} }
//------------------------------------------------------------------------------
void smf_pdu_session::get_paa(paa_t &paa) {
switch (pdn_type.pdn_type) {
case PDN_TYPE_E_IPV4:
ipv4 = true;
ipv6 = false;
paa.ipv4_address = ipv4_address;
break;
case PDN_TYPE_E_IPV6:
ipv4 = false;
ipv6 = true;
paa.ipv6_address = ipv6_address;
break;
case PDN_TYPE_E_IPV4V6:
ipv4 = true;
ipv6 = true;
paa.ipv4_address = ipv4_address;
paa.ipv6_address = ipv6_address;
break;
case PDN_TYPE_E_NON_IP:
ipv4 = false;
ipv6 = false;
break;
default:
Logger::smf_app().error(
"smf_pdu_session::get_paa (paa_t) Unknown PDN type %d",
pdn_type.pdn_type);
}
paa.pdn_type.pdn_type = pdn_type.pdn_type;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_pdu_session::add_qos_flow(smf_qos_flow &flow) { void smf_pdu_session::add_qos_flow(smf_qos_flow &flow) {
if ((flow.qfi.qfi >= QOS_FLOW_IDENTIFIER_FIRST ) if ((flow.qfi.qfi >= QOS_FLOW_IDENTIFIER_FIRST )
...@@ -208,14 +279,19 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) { ...@@ -208,14 +279,19 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) {
for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin(); for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin();
it != qos_flows.end(); ++it) { it != qos_flows.end(); ++it) {
//TODO: release FAR_ID, PDR_ID
//release_pdr_id(it->second.pdr_id_dl);
//release_pdr_id(it->second.pdr_id_ul);
//release_far_id(it->second.far_id_dl.second);
//release_far_id(it->second.far_id_ul.second);
it->second.deallocate_ressources(); it->second.deallocate_ressources();
} }
qos_flows.clear();
if (ipv4) { if (ipv4) {
paa_dynamic::get_instance().release_paa(apn, ipv4_address); paa_dynamic::get_instance().release_paa(apn, ipv4_address);
} }
//smf_app_inst->free_s5s8_cp_fteid(pgw_fteid_s5_s8_cp); clear(); //including qos_flows.clear()
clear(); Logger::smf_app().info(
"Resources associated with this PDU Session have been released");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -283,6 +359,10 @@ std::string smf_pdu_session::toString() const { ...@@ -283,6 +359,10 @@ std::string smf_pdu_session::toString() const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_pdu_session::set_pdu_session_status( void smf_pdu_session::set_pdu_session_status(
const pdu_session_status_e &status) { const pdu_session_status_e &status) {
//TODO: Should consider congestion handling
Logger::smf_app().info(
"Set PDU Session Status to %s",
pdu_session_status_e2str[static_cast<int>(status)].c_str());
pdu_session_status = status; pdu_session_status = status;
} }
...@@ -301,6 +381,28 @@ upCnx_state_e smf_pdu_session::get_upCnx_state() const { ...@@ -301,6 +381,28 @@ upCnx_state_e smf_pdu_session::get_upCnx_state() const {
return upCnx_state; return upCnx_state;
} }
//------------------------------------------------------------------------------
pdn_type_t smf_pdu_session::get_pdn_type() const {
return pdn_type;
}
//------------------------------------------------------------------------------
void session_management_subscription::insert_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
dnn_configurations.insert(
std::pair<std::string, std::shared_ptr<dnn_configuration_t>>(
dnn, dnn_configuration));
}
//------------------------------------------------------------------------------
void session_management_subscription::find_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
Logger::smf_app().info("find_dnn_configuration with dnn %s", dnn.c_str());
if (dnn_configurations.count(dnn) > 0) {
dnn_configuration = dnn_configurations.at(dnn);
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_context::insert_procedure(std::shared_ptr<smf_procedure> &sproc) { void smf_context::insert_procedure(std::shared_ptr<smf_procedure> &sproc) {
std::unique_lock<std::recursive_mutex> lock(m_context); std::unique_lock<std::recursive_mutex> lock(m_context);
...@@ -1219,7 +1321,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1219,7 +1321,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
// qos_rules_ie[0].segregation ; // qos_rules_ie[0].segregation ;
// qos_rules_ie[0].qosflowidentifer ; // qos_rules_ie[0].qosflowidentifer ;
} }
free_wrapper((void **) &qos_rules_ie); free_wrapper((void**) &qos_rules_ie);
//verify the PDU session ID //verify the PDU session ID
if (smreq->req.get_pdu_session_id() if (smreq->req.get_pdu_session_id()
...@@ -1298,6 +1400,10 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1298,6 +1400,10 @@ void smf_context::handle_pdu_session_update_sm_context_request(
case PDU_SESSION_MODIFICATION_COMPLETE: { case PDU_SESSION_MODIFICATION_COMPLETE: {
//PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502) //PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502)
//TODO: should be verified since mentioned PDU_SESSION_MODIFICATION_COMMAND ACK in spec (see Step 11, section 4.3.3.2@3GPP TS 23.502) //TODO: should be verified since mentioned PDU_SESSION_MODIFICATION_COMMAND ACK in spec (see Step 11, section 4.3.3.2@3GPP TS 23.502)
Logger::smf_app().debug("PDU_SESSION_MODIFICATION_COMPLETE");
procedure_type =
session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3;
//send response //send response
/* see section 6.3.2.3@3GPP TS 24.501 V16.1.0 /* see section 6.3.2.3@3GPP TS 24.501 V16.1.0
...@@ -1320,6 +1426,63 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1320,6 +1426,63 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Release UE-Initiated (Step 1) //PDU Session Release UE-Initiated (Step 1)
case PDU_SESSION_RELEASE_REQUEST: { case PDU_SESSION_RELEASE_REQUEST: {
//PDU Session Release procedure (Section 4.3.4@3GPP TS 23.502) //PDU Session Release procedure (Section 4.3.4@3GPP TS 23.502)
Logger::smf_app().debug("PDU_SESSION_RELEASE_REQUEST");
Logger::smf_app().info(
"PDU Session Release (UE-Initiated), processing N1 SM Information");
procedure_type =
session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1;
//verify PDU Session ID
if (sm_context_req_msg.get_pdu_session_id()
!= decoded_nas_msg.plain.sm.header.pdu_session_identity) {
//TODO: PDU Session ID mismatch
}
//PTI
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = { .procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity };
n1_sm_context_resp->res.set_pti(pti);
//Message Type
//Presence
//5GSM Cause
//Extended Protocol Configuration Options
//Release the resources related to this PDU Session
//The SMF releases the IP address / Prefix(es) that were allocated to the PDU Session and releases the
//corresponding User Plane resources
//SMF releases the IP address / Prefix(es) that were allocated to the PDU Session
//find DNN context
std::shared_ptr<dnn_context> sd = { };
if ((!find_dnn_context(sm_context_req_msg.get_snssai(),
sm_context_req_msg.get_dnn(), sd))
or (nullptr == sd.get())) {
//TODO: error cannot find the associated DNN context
return;
}
//find PDU Session
std::shared_ptr<smf_pdu_session> ss;
if ((!sd.get()->find_pdu_session(
sm_context_req_msg.get_pdu_session_id(), ss))
or (nullptr == ss.get())) {
//TODO: error cannot find the corresponding PDU Session
}
//get the associated QoS flows: to be used for PFCP Session Modification procedure
std::vector<smf_qos_flow> qos_flows;
ss.get()->get_qos_flows(qos_flows);
for (auto i : qos_flows) {
sm_context_req_msg.add_qfi(i.qfi.qfi);
}
//need to update UPF accordingly
update_upf = true;
//TODO: //TODO:
} }
break; break;
...@@ -1327,7 +1490,64 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1327,7 +1490,64 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Release UE-Initiated (Step 3) //PDU Session Release UE-Initiated (Step 3)
case PDU_SESSION_RELEASE_COMPLETE: { case PDU_SESSION_RELEASE_COMPLETE: {
//PDU Session Release procedure //PDU Session Release procedure
//TODO: Logger::smf_app().debug("PDU_SESSION_RELEASE_COMPLETE");
Logger::smf_app().info(
"PDU Session Release Complete (UE-Initiated), processing N1 SM Information");
procedure_type =
session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP3;
//verify PDU Session ID
if (sm_context_req_msg.get_pdu_session_id()
!= decoded_nas_msg.plain.sm.header.pdu_session_identity) {
//TODO: PDU Session ID mismatch
}
//PTI
Logger::smf_app().info(
"PTI %d",
decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = { .procedure_transaction_id =
decoded_nas_msg.plain.sm.header.procedure_transaction_identity };
//Message Type
if (decoded_nas_msg.plain.sm.header.message_type
!= PDU_SESSION_RELEASE_COMPLETE) {
//TODO: Message Type mismatch
}
//5GSM Cause
//Extended Protocol Configuration Options
//Update PDU Session status -> INACTIVE
sp.get()->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_INACTIVE);
//Stop timer T3592
itti_inst->timer_remove(sp.get()->timer_T3592);
//send response to AMF
//Verify, do we need this?
oai::smf_server::model::SmContextCreatedData smContextCreatedData;
smf_n11_inst->send_pdu_session_create_sm_context_response(
smreq->http_response, smContextCreatedData,
Pistache::Http::Code::Ok);
//TODO: SMF invokes Nsmf_PDUSession_SMContextStatusNotify to notify AMF that the SM context for this PDU Session is released
//TODO: if dynamic PCC applied, SMF invokes an SM Policy Association Termination
//TODO: SMF unsubscribes from Session Management Subscription data changes notification from UDM by invoking Numd_SDM_Unsubscribe
//find dnn context
std::shared_ptr<dnn_context> sd = { };
bool find_dnn = find_dnn_context(sm_context_req_msg.get_snssai(),
sm_context_req_msg.get_dnn(), sd);
//At this step, this context should be existed
if (nullptr == sd.get()) {
Logger::smf_app().debug(
"DNN context (dnn_in_use %s) is not existed yet!",
sm_context_req_msg.get_dnn().c_str());
//TODO:
}
if (sd.get()->get_number_pdu_sessions() == 0) {
Logger::smf_app().debug(
"Unsubscribe from Session Management Subscription data changes notification from UDM");
//TODO: unsubscribes from Session Management Subscription data changes notification from UDM
}
//TODO: Invoke Nudm_UECM_Deregistration
} }
break; break;
...@@ -1362,6 +1582,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1362,6 +1582,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//UE-Requested PDU Session Establishment procedure (Section 4.3.2.2.1@3GPP TS 23.502) //UE-Requested PDU Session Establishment procedure (Section 4.3.2.2.1@3GPP TS 23.502)
//or UE Triggered Service Request Procedure (step 2) //or UE Triggered Service Request Procedure (step 2)
case n2_sm_info_type_e::PDU_RES_SETUP_RSP: { case n2_sm_info_type_e::PDU_RES_SETUP_RSP: {
Logger::smf_app().info("PDU_RES_SETUP_RSP");
Logger::smf_app().info( Logger::smf_app().info(
"PDU Session Establishment Request, processing N2 SM Information"); "PDU Session Establishment Request, processing N2 SM Information");
...@@ -1453,6 +1674,10 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1453,6 +1674,10 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Modification procedure (UE-initiated, Section 4.3.3.2@3GPP TS 23.502 or SMF-Requested)(Step 2) //PDU Session Modification procedure (UE-initiated, Section 4.3.3.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_MOD_RSP: { case n2_sm_info_type_e::PDU_RES_MOD_RSP: {
Logger::smf_app().info("PDU_RES_MOD_RSP");
Logger::smf_app().info(
"PDU Session Modification, processing N2 SM Information");
procedure_type = procedure_type =
session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2; session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2;
...@@ -1516,13 +1741,29 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1516,13 +1741,29 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Modification procedure //PDU Session Modification procedure
case n2_sm_info_type_e::PDU_RES_MOD_FAIL: { case n2_sm_info_type_e::PDU_RES_MOD_FAIL: {
Logger::smf_app().info("PDU_RES_MOD_FAIL");
//TODO: //TODO:
} }
break; break;
//PDU Session Release procedure (UE-initiated, Section 4.3.4.2@3GPP TS 23.502 or SMF-Requested)(Step 2) //PDU Session Release procedure (UE-initiated, Section 4.3.4.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_REL_RSP: { case n2_sm_info_type_e::PDU_RES_REL_RSP: {
//TODO: Logger::smf_app().info("PDU_RES_REL_RSP");
Logger::smf_app().info(
"PDU Session Release (UE-initiated), processing N2 SM Information");
procedure_type =
session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2;
//TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502)
//SMF send response to AMF
//Verify, do we need this?
oai::smf_server::model::SmContextCreatedData smContextCreatedData;
smf_n11_inst->send_pdu_session_create_sm_context_response(
smreq->http_response, smContextCreatedData,
Pistache::Http::Code::Ok);
} }
break; break;
...@@ -1702,6 +1943,10 @@ void dnn_context::insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp) { ...@@ -1702,6 +1943,10 @@ void dnn_context::insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp) {
pdu_sessions.push_back(sp); pdu_sessions.push_back(sp);
} }
size_t dnn_context::get_number_pdu_sessions() {
return pdu_sessions.size();
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::string dnn_context::toString() const { std::string dnn_context::toString() const {
std::string s = { }; std::string s = { };
...@@ -1716,55 +1961,3 @@ std::string dnn_context::toString() const { ...@@ -1716,55 +1961,3 @@ std::string dnn_context::toString() const {
return s; return s;
} }
//------------------------------------------------------------------------------
void session_management_subscription::insert_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
dnn_configurations.insert(
std::pair<std::string, std::shared_ptr<dnn_configuration_t>>(
dnn, dnn_configuration));
}
//------------------------------------------------------------------------------
void session_management_subscription::find_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
Logger::smf_app().info("find_dnn_configuration with dnn %s", dnn.c_str());
if (dnn_configurations.count(dnn) > 0) {
dnn_configuration = dnn_configurations.at(dnn);
}
}
//------------------------------------------------------------------------------
void smf_qos_flow::release_qos_flow() {
released = true;
}
//------------------------------------------------------------------------------
std::string smf_qos_flow::toString() const {
std::string s = { };
s.append("QoS Flow:\n");
s.append("\tFQI:\t\t\t\t").append(std::to_string((uint8_t) qfi.qfi)).append(
"\n");
s.append("\tUL FTEID:\t\t").append(ul_fteid.toString()).append("\n");
s.append("\tPDR ID UL:\t\t\t").append(std::to_string(pdr_id_ul.rule_id))
.append("\n");
s.append("\tPDR ID DL:\t\t\t").append(std::to_string(pdr_id_dl.rule_id))
.append("\n");
s.append("\tPRECEDENCE:\t\t\t").append(std::to_string(precedence.precedence))
.append("\n");
if (far_id_ul.first) {
s.append("\tFAR ID UL:\t\t\t").append(
std::to_string(far_id_ul.second.far_id)).append("\n");
}
if (far_id_dl.first) {
s.append("\tFAR ID DL:\t\t\t").append(
std::to_string(far_id_dl.second.far_id)).append("\n");
}
return s;
}
//------------------------------------------------------------------------------
void smf_qos_flow::deallocate_ressources() {
Logger::smf_app().info("smf_qos_flow::deallocate_ressources(%d)",
(uint8_t) qfi.qfi);
clear();
}
...@@ -131,11 +131,13 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> { ...@@ -131,11 +131,13 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
pdu_session_status = pdu_session_status_e::PDU_SESSION_INACTIVE; pdu_session_status = pdu_session_status_e::PDU_SESSION_INACTIVE;
timer_T3590 = ITTI_INVALID_TIMER_ID; timer_T3590 = ITTI_INVALID_TIMER_ID;
timer_T3591 = ITTI_INVALID_TIMER_ID; timer_T3591 = ITTI_INVALID_TIMER_ID;
timer_T3592 = ITTI_INVALID_TIMER_ID;
} }
smf_pdu_session(smf_pdu_session &b) = delete; smf_pdu_session(smf_pdu_session &b) = delete;
void set(const paa_t &paa); void set(const paa_t &paa);
void get_paa(paa_t &paa);
bool get_qos_flow(const pfcp::pdr_id_t &pdr_id, smf_qos_flow &q); bool get_qos_flow(const pfcp::pdr_id_t &pdr_id, smf_qos_flow &q);
bool get_qos_flow(const pfcp::far_id_t &far_id, smf_qos_flow &q); bool get_qos_flow(const pfcp::far_id_t &far_id, smf_qos_flow &q);
...@@ -184,6 +186,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> { ...@@ -184,6 +186,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
void generate_qos_rule_id(uint8_t &rule_id); void generate_qos_rule_id(uint8_t &rule_id);
void release_qos_rule_id(const uint8_t &rule_id); void release_qos_rule_id(const uint8_t &rule_id);
pdn_type_t get_pdn_type() const;
bool ipv4; // IP Address(es): IPv4 address and/or IPv6 prefix bool ipv4; // IP Address(es): IPv4 address and/or IPv6 prefix
bool ipv6; // IP Address(es): IPv4 address and/or IPv6 prefix bool ipv6; // IP Address(es): IPv4 address and/or IPv6 prefix
...@@ -212,6 +215,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> { ...@@ -212,6 +215,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
pdu_session_status_e pdu_session_status; pdu_session_status_e pdu_session_status;
timer_id_t timer_T3590; timer_id_t timer_T3590;
timer_id_t timer_T3591; timer_id_t timer_T3591;
timer_id_t timer_T3592;
//N3 tunnel status (ACTIVATED, DEACTIVATED, ACTIVATING) //N3 tunnel status (ACTIVATED, DEACTIVATED, ACTIVATING)
upCnx_state_e upCnx_state; upCnx_state_e upCnx_state;
//5GSM parameters and capabilities //5GSM parameters and capabilities
...@@ -272,6 +276,8 @@ class dnn_context { ...@@ -272,6 +276,8 @@ class dnn_context {
/* Insert a PDU Session into the DNN context */ /* Insert a PDU Session into the DNN context */
void insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp); void insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp);
/* get number of pdu sessions associated with this context (dnn and Nssai) */
size_t get_number_pdu_sessions();
std::string toString() const; std::string toString() const;
......
...@@ -146,25 +146,26 @@ void pdu_session_msg::set_pdu_session_type(uint8_t const &pdu_session_type) { ...@@ -146,25 +146,26 @@ void pdu_session_msg::set_pdu_session_type(uint8_t const &pdu_session_type) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
extended_protocol_discriminator_t pdu_session_create_sm_context::get_epd() const { procedure_transaction_id_t pdu_session_msg::get_pti() const {
return m_epd; return m_pti;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_create_sm_context::set_epd( void pdu_session_msg::set_pti(
extended_protocol_discriminator_t const &epd) { procedure_transaction_id_t const &pti) {
m_epd = epd; m_pti = pti;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
procedure_transaction_id_t pdu_session_create_sm_context::get_pti() const { extended_protocol_discriminator_t pdu_session_create_sm_context::get_epd() const {
return m_pti; return m_epd;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_create_sm_context::set_pti( void pdu_session_create_sm_context::set_epd(
procedure_transaction_id_t const &pti) { extended_protocol_discriminator_t const &epd) {
m_pti = pti; m_epd = epd;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -370,6 +371,12 @@ void pdu_session_update_sm_context_request::add_qfi(pfcp::qfi_t const &qfi) { ...@@ -370,6 +371,12 @@ void pdu_session_update_sm_context_request::add_qfi(pfcp::qfi_t const &qfi) {
qfis.push_back(qfi); qfis.push_back(qfi);
} }
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::add_qfi(uint8_t const &q) {
pfcp::qfi_t qfi(q);
qfis.push_back(qfi);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::get_qfis( void pdu_session_update_sm_context_request::get_qfis(
std::vector<pfcp::qfi_t> &q) { std::vector<pfcp::qfi_t> &q) {
...@@ -412,17 +419,6 @@ void pdu_session_update_sm_context_request::set_an_type( ...@@ -412,17 +419,6 @@ void pdu_session_update_sm_context_request::set_an_type(
m_an_type = value; m_an_type = value;
} }
//-----------------------------------------------------------------------------
procedure_transaction_id_t pdu_session_update_sm_context_response::get_pti() const {
return m_pti;
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_response::set_pti(
procedure_transaction_id_t const &pti) {
m_pti = pti;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void pdu_session_update_sm_context_response::set_cause(uint8_t cause) { void pdu_session_update_sm_context_response::set_cause(uint8_t cause) {
m_cause = cause; m_cause = cause;
......
...@@ -133,6 +133,9 @@ class pdu_session_msg { ...@@ -133,6 +133,9 @@ class pdu_session_msg {
uint8_t get_pdu_session_type() const; uint8_t get_pdu_session_type() const;
void set_pdu_session_type(uint8_t const &pdu_session_type); void set_pdu_session_type(uint8_t const &pdu_session_type);
procedure_transaction_id_t get_pti() const;
void set_pti(procedure_transaction_id_t const &pti);
private: private:
pdu_session_msg_type_t m_msg_type; pdu_session_msg_type_t m_msg_type;
std::string m_api_root; std::string m_api_root;
...@@ -142,6 +145,7 @@ class pdu_session_msg { ...@@ -142,6 +145,7 @@ class pdu_session_msg {
std::string m_dnn; std::string m_dnn;
snssai_t m_snssai; snssai_t m_snssai;
uint8_t m_pdu_session_type; uint8_t m_pdu_session_type;
procedure_transaction_id_t m_pti;
}; };
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
...@@ -174,15 +178,11 @@ class pdu_session_create_sm_context : public pdu_session_msg { ...@@ -174,15 +178,11 @@ class pdu_session_create_sm_context : public pdu_session_msg {
extended_protocol_discriminator_t get_epd() const; extended_protocol_discriminator_t get_epd() const;
void set_epd(extended_protocol_discriminator_t const &epd); void set_epd(extended_protocol_discriminator_t const &epd);
procedure_transaction_id_t get_pti() const;
void set_pti(procedure_transaction_id_t const &pti);
uint8_t get_message_type() const; uint8_t get_message_type() const;
void set_message_type(uint8_t const &message_type); void set_message_type(uint8_t const &message_type);
private: private:
extended_protocol_discriminator_t m_epd; extended_protocol_discriminator_t m_epd;
procedure_transaction_id_t m_pti;
uint8_t m_message_type; uint8_t m_message_type;
}; };
...@@ -420,6 +420,7 @@ class pdu_session_update_sm_context_request : public pdu_session_msg { ...@@ -420,6 +420,7 @@ class pdu_session_update_sm_context_request : public pdu_session_msg {
bool n1_sm_msg_is_set() const; bool n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const; bool n2_sm_info_is_set() const;
void add_qfi(pfcp::qfi_t const &qfi); void add_qfi(pfcp::qfi_t const &qfi);
void add_qfi(uint8_t const &qfi);
void get_qfis(std::vector<pfcp::qfi_t> &q); void get_qfis(std::vector<pfcp::qfi_t> &q);
void set_dl_fteid(fteid_t const &t); void set_dl_fteid(fteid_t const &t);
void get_dl_fteid(fteid_t &t); void get_dl_fteid(fteid_t &t);
...@@ -487,7 +488,6 @@ class pdu_session_update_sm_context_response : public pdu_session_msg { ...@@ -487,7 +488,6 @@ class pdu_session_update_sm_context_response : public pdu_session_msg {
pdu_session_update_sm_context_response() pdu_session_update_sm_context_response()
: :
pdu_session_msg(PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE) { pdu_session_msg(PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE) {
m_pti = { };
m_cause = 0; m_cause = 0;
m_n1_sm_msg_is_set = false; m_n1_sm_msg_is_set = false;
m_n2_sm_info_is_set = false; m_n2_sm_info_is_set = false;
...@@ -514,11 +514,8 @@ class pdu_session_update_sm_context_response : public pdu_session_msg { ...@@ -514,11 +514,8 @@ class pdu_session_update_sm_context_response : public pdu_session_msg {
std::map<uint8_t, qos_flow_context_updated> &all_flows); std::map<uint8_t, qos_flow_context_updated> &all_flows);
void remove_all_qos_flow_context_updateds(); void remove_all_qos_flow_context_updateds();
nlohmann::json sm_context_updated_data; //N1N2MessageTransferReqData from oai::amf::model nlohmann::json sm_context_updated_data; //N1N2MessageTransferReqData from oai::amf::model
procedure_transaction_id_t get_pti() const;
void set_pti(procedure_transaction_id_t const &pti);
private: private:
procedure_transaction_id_t m_pti;
uint8_t m_cause; uint8_t m_cause;
std::string m_n1_sm_message; //N1 SM after decoding std::string m_n1_sm_message; //N1 SM after decoding
bool m_n1_sm_msg_is_set; bool m_n1_sm_msg_is_set;
......
...@@ -341,7 +341,7 @@ void smf_n11::send_pdu_session_update_sm_context_response( ...@@ -341,7 +341,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
break; break;
case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: { case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: {
Logger::smf_n11().debug("PDU_SESSION_ESTABLISHMENT_UE_REQUESTED"); Logger::smf_n11().info("PDU_SESSION_ESTABLISHMENT_UE_REQUESTED");
std::string json_part = std::string json_part =
sm_context_res->res.sm_context_updated_data.dump(); sm_context_res->res.sm_context_updated_data.dump();
sm_context_res->http_response.headers() sm_context_res->http_response.headers()
...@@ -353,7 +353,7 @@ void smf_n11::send_pdu_session_update_sm_context_response( ...@@ -353,7 +353,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
break; break;
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1: { case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1: {
Logger::smf_n11().debug("PDU_SESSION_MODIFICATION_UE_INITIATED"); Logger::smf_n11().info("PDU_SESSION_MODIFICATION_UE_INITIATED");
std::string boundary = "----Boundary"; std::string boundary = "----Boundary";
std::string json_part = std::string json_part =
...@@ -406,6 +406,26 @@ void smf_n11::send_pdu_session_update_sm_context_response( ...@@ -406,6 +406,26 @@ void smf_n11::send_pdu_session_update_sm_context_response(
} }
break; break;
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1: {
Logger::smf_n11().debug("PDU_SESSION_RELEASE_UE_REQUESTED_STEP1");
std::string boundary = "----Boundary";
std::string json_part =
sm_context_res->res.sm_context_updated_data.dump();
std::string n1_message = sm_context_res->res.get_n1_sm_message();
std::string n2_message = sm_context_res->res.get_n2_sm_information();
std::string body;
create_multipart_related_content(body, json_part, boundary, n1_message,
n2_message);
sm_context_res->http_response.headers()
.add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
}
break;
default: { default: {
Logger::smf_n11().debug("Session management procedure: unknown!"); Logger::smf_n11().debug("Session management procedure: unknown!");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment