mirror of https://github.com/PentHertz/srsLTE.git
Introducing NGAP UE context procedures
This commit is contained in:
parent
a896e32cf4
commit
a6226379b4
|
@ -50,6 +50,7 @@ public:
|
|||
virtual bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0;
|
||||
virtual bool is_amf_connected() = 0;
|
||||
virtual void ue_ctxt_setup_complete(uint16_t rnti) = 0;
|
||||
virtual void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -12,11 +12,18 @@
|
|||
#ifndef SRSRAN_GNB_RRC_NR_INTERFACES_H
|
||||
#define SRSRAN_GNB_RRC_NR_INTERFACES_H
|
||||
|
||||
#include "srsran/asn1/ngap.h"
|
||||
#include "srsran/common/byte_buffer.h"
|
||||
namespace srsenb {
|
||||
|
||||
class rrc_interface_ngap_nr
|
||||
{
|
||||
public:
|
||||
virtual int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) = 0;
|
||||
virtual int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0;
|
||||
virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0;
|
||||
virtual int start_security_mode_procedure(uint16_t rnti) = 0;
|
||||
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -37,9 +37,11 @@ namespace srsenb {
|
|||
class ngap : public ngap_interface_rrc_nr
|
||||
{
|
||||
public:
|
||||
class ue;
|
||||
ngap(srsran::task_sched_handle task_sched_,
|
||||
srslog::basic_logger& logger,
|
||||
srsran::socket_manager_itf* rx_socket_handler);
|
||||
~ngap();
|
||||
int init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_);
|
||||
void stop();
|
||||
|
||||
|
@ -54,7 +56,7 @@ public:
|
|||
srsran::unique_byte_buffer_t pdu,
|
||||
uint32_t s_tmsi);
|
||||
|
||||
void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu){};
|
||||
void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu);
|
||||
bool user_exists(uint16_t rnti) { return true; };
|
||||
void user_mod(uint16_t old_rnti, uint16_t new_rnti){};
|
||||
bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; };
|
||||
|
@ -63,6 +65,8 @@ public:
|
|||
srsran::optional<uint32_t> ran_ue_ngap_id = {},
|
||||
srsran::optional<uint32_t> amf_ue_ngap_id = {});
|
||||
void ue_ctxt_setup_complete(uint16_t rnti);
|
||||
void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome);
|
||||
bool send_pdu_session_resource_setup_response();
|
||||
|
||||
// Stack interface
|
||||
bool
|
||||
|
@ -79,7 +83,7 @@ private:
|
|||
static const int NONUE_STREAM_ID = 0;
|
||||
|
||||
// args
|
||||
rrc_interface_ngap_nr* rrc = nullptr;
|
||||
rrc_interface_ngap_nr* rrc = nullptr;
|
||||
ngap_args_t args = {};
|
||||
srslog::basic_logger& logger;
|
||||
srsran::task_sched_handle task_sched;
|
||||
|
@ -98,22 +102,6 @@ private:
|
|||
asn1::ngap_nr::tai_s tai;
|
||||
asn1::ngap_nr::nr_cgi_s nr_cgi;
|
||||
|
||||
// Moved into NGAP class to avoid redifinition (Introduce new namespace?)
|
||||
struct ue_ctxt_t {
|
||||
static const uint32_t invalid_gnb_id = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||
uint32_t ran_ue_ngap_id = invalid_gnb_id;
|
||||
srsran::optional<uint32_t> amf_ue_ngap_id;
|
||||
uint32_t gnb_cc_idx = 0;
|
||||
struct timeval init_timestamp = {};
|
||||
|
||||
// AMF identifier
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
uint8_t amf_region_id;
|
||||
};
|
||||
|
||||
asn1::ngap_nr::ng_setup_resp_s ngsetupresponse;
|
||||
|
||||
int build_tai_cgi();
|
||||
|
@ -122,34 +110,23 @@ private:
|
|||
bool sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name);
|
||||
|
||||
bool handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu);
|
||||
bool handle_successfuloutcome(const asn1::ngap_nr::successful_outcome_s& msg);
|
||||
bool handle_unsuccessfuloutcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg);
|
||||
bool handle_initiatingmessage(const asn1::ngap_nr::init_msg_s& msg);
|
||||
bool handle_successful_outcome(const asn1::ngap_nr::successful_outcome_s& msg);
|
||||
bool handle_unsuccessful_outcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg);
|
||||
bool handle_initiating_message(const asn1::ngap_nr::init_msg_s& msg);
|
||||
|
||||
bool handle_dlnastransport(const asn1::ngap_nr::dl_nas_transport_s& msg);
|
||||
bool handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg);
|
||||
bool handle_ngsetupfailure(const asn1::ngap_nr::ng_setup_fail_s& msg);
|
||||
bool handle_initialctxtsetuprequest(const asn1::ngap_nr::init_context_setup_request_s& msg);
|
||||
struct ue {
|
||||
explicit ue(ngap* ngap_ptr_);
|
||||
bool send_initialuemessage(asn1::ngap_nr::rrcestablishment_cause_e cause,
|
||||
srsran::unique_byte_buffer_t pdu,
|
||||
bool has_tmsi,
|
||||
uint32_t s_tmsi = 0);
|
||||
bool send_ulnastransport(srsran::unique_byte_buffer_t pdu);
|
||||
bool was_uectxtrelease_requested() const { return release_requested; }
|
||||
void ue_ctxt_setup_complete();
|
||||
// TS 38.413 - Section 8.6.2 - Downlink NAS Transport
|
||||
bool handle_dl_nas_transport(const asn1::ngap_nr::dl_nas_transport_s& msg);
|
||||
// TS 38.413 - Section 9.2.6.2 - NG Setup Response
|
||||
bool handle_ng_setup_response(const asn1::ngap_nr::ng_setup_resp_s& msg);
|
||||
// TS 38.413 - Section 9.2.6.3 - NG Setup Failure
|
||||
bool handle_ng_setup_failure(const asn1::ngap_nr::ng_setup_fail_s& msg);
|
||||
// TS 38.413 - Section 9.2.2.5 - UE Context Release Command
|
||||
bool handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
|
||||
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request
|
||||
bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg);
|
||||
// TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request
|
||||
bool handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
|
||||
|
||||
ue_ctxt_t ctxt = {};
|
||||
uint16_t stream_id = 1;
|
||||
|
||||
private:
|
||||
// args
|
||||
ngap* ngap_ptr;
|
||||
|
||||
// state
|
||||
bool release_requested = false;
|
||||
};
|
||||
class user_list
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSENB_NGAP_INTERFACES_H
|
||||
#define SRSENB_NGAP_INTERFACES_H
|
||||
|
||||
namespace srsenb {
|
||||
class ngap_interface_ngap_proc
|
||||
{
|
||||
public:
|
||||
virtual bool send_initial_ctxt_setup_response() = 0;
|
||||
};
|
||||
} // namespace srsenb
|
||||
|
||||
#endif
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSENB_NGAP_UE_H
|
||||
#define SRSENB_NGAP_UE_H
|
||||
|
||||
#include "ngap.h"
|
||||
#include "ngap_ue_proc.h"
|
||||
#include "ngap_ue_utils.h"
|
||||
#include "srsran/asn1/asn1_utils.h"
|
||||
#include "srsran/asn1/ngap.h"
|
||||
namespace srsenb {
|
||||
|
||||
class ngap::ue : public ngap_interface_ngap_proc
|
||||
{
|
||||
public:
|
||||
explicit ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_logger& logger_);
|
||||
virtual ~ue();
|
||||
// TS 38.413 - Section 9.2.5.1 - Initial UE Message
|
||||
bool send_initial_ue_message(asn1::ngap_nr::rrcestablishment_cause_e cause,
|
||||
srsran::unique_byte_buffer_t pdu,
|
||||
bool has_tmsi,
|
||||
uint32_t s_tmsi = 0);
|
||||
// TS 38.413 - Section 9.2.5.3 - Uplink NAS Transport
|
||||
bool send_ul_nas_transport(srsran::unique_byte_buffer_t pdu);
|
||||
// TS 38.413 - Section 9.2.2.2 - Initial Context Setup Response
|
||||
bool send_initial_ctxt_setup_response();
|
||||
// TS 38.413 - Section 9.2.2.3 - Initial Context Setup Failure
|
||||
bool send_initial_ctxt_setup_failure(asn1::ngap_nr::cause_c cause);
|
||||
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request
|
||||
bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg);
|
||||
// TS 38.413 - Section 9.2.2.5 - UE Context Release Command
|
||||
bool handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
|
||||
|
||||
bool was_uectxtrelease_requested() const { return release_requested; }
|
||||
void ue_ctxt_setup_complete();
|
||||
void notify_rrc_reconf_complete(const bool reconf_complete_outcome);
|
||||
|
||||
srsran::proc_t<ngap_ue_initial_context_setup_proc> initial_context_setup_proc;
|
||||
srsran::proc_t<ngap_ue_ue_context_release_proc> ue_context_release_proc;
|
||||
|
||||
ngap_ue_ctxt_t ctxt = {};
|
||||
uint16_t stream_id = 1;
|
||||
|
||||
private:
|
||||
// args
|
||||
ngap* ngap_ptr;
|
||||
rrc_interface_ngap_nr* rrc_ptr;
|
||||
|
||||
// state
|
||||
bool release_requested = false;
|
||||
|
||||
// logger
|
||||
srslog::basic_logger& logger;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
#endif
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSENB_NGAP_UE_PROC_H
|
||||
#define SRSENB_NGAP_UE_PROC_H
|
||||
|
||||
#include "ngap_interfaces.h"
|
||||
#include "ngap_ue_utils.h"
|
||||
|
||||
#include "srsran/asn1/asn1_utils.h"
|
||||
#include "srsran/asn1/ngap.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/stack_procedure.h"
|
||||
#include "srsran/interfaces/gnb_rrc_nr_interfaces.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
// TS 38.413 - Section 8.3 - UE Context Management Procedures
|
||||
|
||||
// TS 38.413 - Section 8.3.1 - Initial Context Setup
|
||||
class ngap_ue_initial_context_setup_proc
|
||||
{
|
||||
public:
|
||||
explicit ngap_ue_initial_context_setup_proc(ngap_interface_ngap_proc* parent_,
|
||||
rrc_interface_ngap_nr* rrc_,
|
||||
ngap_ue_ctxt_t* ue_ctxt);
|
||||
srsran::proc_outcome_t init(const asn1::ngap_nr::init_context_setup_request_s& msg);
|
||||
srsran::proc_outcome_t react(const bool security_mode_command_outcome);
|
||||
srsran::proc_outcome_t step();
|
||||
static const char* name() { return "Initial Context Setup"; }
|
||||
|
||||
private:
|
||||
ngap_ue_ctxt_t* ue_ctxt;
|
||||
ngap_interface_ngap_proc* parent = nullptr;
|
||||
rrc_interface_ngap_nr* rrc = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
};
|
||||
|
||||
// TS 38.413 - Section 8.3.2 - UE Context Release Request (NG-RAN node initiated)
|
||||
class ngap_ue_ue_context_release_proc
|
||||
{
|
||||
public:
|
||||
explicit ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_,
|
||||
rrc_interface_ngap_nr* rrc_,
|
||||
ngap_ue_ctxt_t* ue_ctxt);
|
||||
srsran::proc_outcome_t init(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
|
||||
srsran::proc_outcome_t step();
|
||||
static const char* name() { return "UE Context Release"; }
|
||||
|
||||
private:
|
||||
ngap_ue_ctxt_t* ue_ctxt;
|
||||
ngap_interface_ngap_proc* parent = nullptr;
|
||||
rrc_interface_ngap_nr* rrc = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
};
|
||||
|
||||
// TS 38.413 - Section 8.3.4 - UE Context Modification
|
||||
class ngap_ue_ue_context_modification_proc
|
||||
{
|
||||
public:
|
||||
explicit ngap_ue_ue_context_modification_proc(ngap_interface_ngap_proc* parent_);
|
||||
srsran::proc_outcome_t init();
|
||||
srsran::proc_outcome_t step();
|
||||
static const char* name() { return "UE Context Modification"; }
|
||||
|
||||
private:
|
||||
ngap_interface_ngap_proc* parent;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSENB_NGAP_UE_UTILS_H
|
||||
#define SRSENB_NGAP_UE_UTILS_H
|
||||
|
||||
#include "srsenb/hdr/common/common_enb.h"
|
||||
#include "srsran/adt/optional.h"
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/phy/common/phy_common.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
struct ngap_ue_ctxt_t {
|
||||
static const uint32_t invalid_gnb_id = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||
uint32_t ran_ue_ngap_id = invalid_gnb_id;
|
||||
srsran::optional<uint32_t> amf_ue_ngap_id;
|
||||
uint32_t gnb_cc_idx = 0;
|
||||
struct timeval init_timestamp = {};
|
||||
|
||||
// AMF identifier
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
uint8_t amf_region_id;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
#endif
|
|
@ -82,6 +82,13 @@ public:
|
|||
int sgnb_addition_request(uint16_t rnti);
|
||||
int sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response);
|
||||
|
||||
// Interfaces for NGAP
|
||||
int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key);
|
||||
int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates);
|
||||
int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps);
|
||||
int start_security_mode_procedure(uint16_t rnti);
|
||||
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu);
|
||||
|
||||
class ue
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
# the distribution.
|
||||
#
|
||||
|
||||
set(SOURCES ngap.cc)
|
||||
set(SOURCES ngap.cc ngap_ue.cc ngap_ue_proc.cc)
|
||||
add_library(srsgnb_ngap STATIC ${SOURCES})
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/ngap/ngap.h"
|
||||
#include "srsenb/hdr/stack/ngap/ngap_ue.h"
|
||||
#include "srsran/common/int_helpers.h"
|
||||
|
||||
using srsran::s1ap_mccmnc_to_plmn;
|
||||
|
@ -102,6 +103,8 @@ ngap::ngap(srsran::task_sched_handle task_sched_,
|
|||
amf_task_queue = task_sched.make_task_queue();
|
||||
}
|
||||
|
||||
ngap::~ngap() {}
|
||||
|
||||
int ngap::init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_)
|
||||
{
|
||||
rrc = rrc_;
|
||||
|
@ -204,7 +207,7 @@ void ngap::initial_ue(uint16_t rnti,
|
|||
asn1::ngap_nr::rrcestablishment_cause_e cause,
|
||||
srsran::unique_byte_buffer_t pdu)
|
||||
{
|
||||
std::unique_ptr<ue> ue_ptr{new ue{this}};
|
||||
std::unique_ptr<ue> ue_ptr{new ue{this, rrc, logger}};
|
||||
ue_ptr->ctxt.rnti = rnti;
|
||||
ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx;
|
||||
ue* u = users.add_user(std::move(ue_ptr));
|
||||
|
@ -212,7 +215,7 @@ void ngap::initial_ue(uint16_t rnti,
|
|||
logger.error("Failed to add rnti=0x%x", rnti);
|
||||
return;
|
||||
}
|
||||
u->send_initialuemessage(cause, std::move(pdu), false);
|
||||
u->send_initial_ue_message(cause, std::move(pdu), false);
|
||||
}
|
||||
|
||||
void ngap::initial_ue(uint16_t rnti,
|
||||
|
@ -221,7 +224,7 @@ void ngap::initial_ue(uint16_t rnti,
|
|||
srsran::unique_byte_buffer_t pdu,
|
||||
uint32_t s_tmsi)
|
||||
{
|
||||
std::unique_ptr<ue> ue_ptr{new ue{this}};
|
||||
std::unique_ptr<ue> ue_ptr{new ue{this, rrc, logger}};
|
||||
ue_ptr->ctxt.rnti = rnti;
|
||||
ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx;
|
||||
ue* u = users.add_user(std::move(ue_ptr));
|
||||
|
@ -229,7 +232,7 @@ void ngap::initial_ue(uint16_t rnti,
|
|||
logger.error("Failed to add rnti=0x%x", rnti);
|
||||
return;
|
||||
}
|
||||
u->send_initialuemessage(cause, std::move(pdu), true, s_tmsi);
|
||||
u->send_initial_ue_message(cause, std::move(pdu), true, s_tmsi);
|
||||
}
|
||||
|
||||
void ngap::ue_ctxt_setup_complete(uint16_t rnti)
|
||||
|
@ -241,6 +244,27 @@ void ngap::ue_ctxt_setup_complete(uint16_t rnti)
|
|||
u->ue_ctxt_setup_complete();
|
||||
}
|
||||
|
||||
void ngap::ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome)
|
||||
{
|
||||
ue* u = users.find_ue_rnti(rnti);
|
||||
if (u == nullptr) {
|
||||
return;
|
||||
}
|
||||
u->notify_rrc_reconf_complete(outcome);
|
||||
}
|
||||
|
||||
void ngap::write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu)
|
||||
{
|
||||
logger.info(pdu->msg, pdu->N_bytes, "Received RRC SDU");
|
||||
|
||||
ue* u = users.find_ue_rnti(rnti);
|
||||
if (u == nullptr) {
|
||||
logger.info("The rnti=0x%x does not exist", rnti);
|
||||
return;
|
||||
}
|
||||
u->send_ul_nas_transport(std::move(pdu));
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* ngap::user_list class
|
||||
*********************************************************/
|
||||
|
@ -368,11 +392,11 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu)
|
|||
|
||||
switch (rx_pdu.type().value) {
|
||||
case ngap_pdu_c::types_opts::init_msg:
|
||||
return handle_initiatingmessage(rx_pdu.init_msg());
|
||||
return handle_initiating_message(rx_pdu.init_msg());
|
||||
case ngap_pdu_c::types_opts::successful_outcome:
|
||||
return handle_successfuloutcome(rx_pdu.successful_outcome());
|
||||
return handle_successful_outcome(rx_pdu.successful_outcome());
|
||||
case ngap_pdu_c::types_opts::unsuccessful_outcome:
|
||||
return handle_unsuccessfuloutcome(rx_pdu.unsuccessful_outcome());
|
||||
return handle_unsuccessful_outcome(rx_pdu.unsuccessful_outcome());
|
||||
default:
|
||||
logger.error("Unhandled PDU type %d", rx_pdu.type().value);
|
||||
return false;
|
||||
|
@ -381,42 +405,44 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_initiatingmessage(const asn1::ngap_nr::init_msg_s& msg)
|
||||
bool ngap::handle_initiating_message(const asn1::ngap_nr::init_msg_s& msg)
|
||||
{
|
||||
switch (msg.value.type().value) {
|
||||
case ngap_elem_procs_o::init_msg_c::types_opts::dl_nas_transport:
|
||||
return handle_dlnastransport(msg.value.dl_nas_transport());
|
||||
return handle_dl_nas_transport(msg.value.dl_nas_transport());
|
||||
case ngap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request:
|
||||
return handle_initialctxtsetuprequest(msg.value.init_context_setup_request());
|
||||
return handle_initial_ctxt_setup_request(msg.value.init_context_setup_request());
|
||||
case ngap_elem_procs_o::init_msg_c::types_opts::ue_context_release_cmd:
|
||||
return handle_ue_ctxt_release_cmd(msg.value.ue_context_release_cmd());
|
||||
default:
|
||||
logger.error("Unhandled initiating message: %s", msg.value.type().to_string());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_successfuloutcome(const successful_outcome_s& msg)
|
||||
bool ngap::handle_successful_outcome(const successful_outcome_s& msg)
|
||||
{
|
||||
switch (msg.value.type().value) {
|
||||
case ngap_elem_procs_o::successful_outcome_c::types_opts::ng_setup_resp:
|
||||
return handle_ngsetupresponse(msg.value.ng_setup_resp());
|
||||
return handle_ng_setup_response(msg.value.ng_setup_resp());
|
||||
default:
|
||||
logger.error("Unhandled successful outcome message: %s", msg.value.type().to_string());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_unsuccessfuloutcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg)
|
||||
bool ngap::handle_unsuccessful_outcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg)
|
||||
{
|
||||
switch (msg.value.type().value) {
|
||||
case ngap_elem_procs_o::unsuccessful_outcome_c::types_opts::ng_setup_fail:
|
||||
return handle_ngsetupfailure(msg.value.ng_setup_fail());
|
||||
return handle_ng_setup_failure(msg.value.ng_setup_fail());
|
||||
default:
|
||||
logger.error("Unhandled unsuccessful outcome message: %s", msg.value.type().to_string());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg)
|
||||
bool ngap::handle_ng_setup_response(const asn1::ngap_nr::ng_setup_resp_s& msg)
|
||||
{
|
||||
ngsetupresponse = msg;
|
||||
amf_connected = true;
|
||||
|
@ -427,7 +453,7 @@ bool ngap::handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_ngsetupfailure(const asn1::ngap_nr::ng_setup_fail_s& msg)
|
||||
bool ngap::handle_ng_setup_failure(const asn1::ngap_nr::ng_setup_fail_s& msg)
|
||||
{
|
||||
std::string cause = get_cause(msg.protocol_ies.cause.value);
|
||||
logger.error("NG Setup Failure. Cause: %s", cause.c_str());
|
||||
|
@ -435,14 +461,18 @@ bool ngap::handle_ngsetupfailure(const asn1::ngap_nr::ng_setup_fail_s& msg)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_dlnastransport(const asn1::ngap_nr::dl_nas_transport_s& msg)
|
||||
bool ngap::handle_dl_nas_transport(const asn1::ngap_nr::dl_nas_transport_s& msg)
|
||||
{
|
||||
if (msg.ext) {
|
||||
logger.warning("Not handling NGAP message extension");
|
||||
}
|
||||
ue* u =
|
||||
handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value);
|
||||
|
||||
if (u == nullptr) {
|
||||
logger.warning("Couldn't find user with ran_ue_ngap_id %d and %d",
|
||||
msg.protocol_ies.ran_ue_ngap_id.value.value,
|
||||
msg.protocol_ies.amf_ue_ngap_id.value.value);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -470,49 +500,79 @@ bool ngap::handle_dlnastransport(const asn1::ngap_nr::dl_nas_transport_s& msg)
|
|||
logger.warning("Not handling AllowedNSSAI");
|
||||
}
|
||||
|
||||
// TODO: Pass NAS PDU once RRC interface is ready
|
||||
/* srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
|
||||
srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
|
||||
if (pdu == nullptr) {
|
||||
logger.error("Fatal Error: Couldn't allocate buffer in ngap::run_thread().");
|
||||
return false;
|
||||
}
|
||||
memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size());
|
||||
pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size();
|
||||
rrc->write_dl_info(u->ctxt.rnti, std::move(pdu)); */
|
||||
rrc->write_dl_info(u->ctxt.rnti, std::move(pdu));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_initialctxtsetuprequest(const asn1::ngap_nr::init_context_setup_request_s& msg)
|
||||
bool ngap::handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg)
|
||||
{
|
||||
ue* u =
|
||||
handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value);
|
||||
if (u == nullptr) {
|
||||
logger.warning("Can not find UE");
|
||||
return false;
|
||||
}
|
||||
|
||||
u->ctxt.amf_pointer = msg.protocol_ies.guami.value.amf_pointer.to_number();
|
||||
u->ctxt.amf_set_id = msg.protocol_ies.guami.value.amf_set_id.to_number();
|
||||
u->ctxt.amf_region_id = msg.protocol_ies.guami.value.amf_region_id.to_number();
|
||||
|
||||
// Setup UE ctxt in RRC once interface is ready
|
||||
/* if (not rrc->setup_ue_ctxt(u->ctxt.rnti, msg)) {
|
||||
return false;
|
||||
} */
|
||||
|
||||
/* if (msg.protocol_ies.nas_pdu_present) {
|
||||
srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
|
||||
if (pdu == nullptr) {
|
||||
logger.error("Fatal Error: Couldn't allocate buffer in ngap::run_thread().");
|
||||
return false;
|
||||
}
|
||||
memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size());
|
||||
pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size();
|
||||
rrc->write_dl_info(u->ctxt.rnti, std::move(pdu));
|
||||
} */
|
||||
u->handle_initial_ctxt_setup_request(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg)
|
||||
{
|
||||
// TODO: UE Context Release Command contains a list of ue_ngap_ids
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg)
|
||||
{
|
||||
// TODO
|
||||
logger.warning("Not implemented yet");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/* NGAP message senders
|
||||
********************************************************************************/
|
||||
|
||||
bool ngap::send_error_indication(const asn1::ngap_nr::cause_c& cause,
|
||||
srsran::optional<uint32_t> ran_ue_ngap_id,
|
||||
srsran::optional<uint32_t> amf_ue_ngap_id)
|
||||
{
|
||||
if (amf_connected == false) {
|
||||
logger.warning("AMF not connected.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_ERROR_IND);
|
||||
auto& container = tx_pdu.init_msg().value.error_ind().protocol_ies;
|
||||
|
||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||
container.ran_ue_ngap_id_present = ran_ue_ngap_id.has_value();
|
||||
if (ran_ue_ngap_id.has_value()) {
|
||||
container.ran_ue_ngap_id.value = ran_ue_ngap_id.value();
|
||||
ue* user_ptr = users.find_ue_gnbid(ran_ue_ngap_id.value());
|
||||
rnti = user_ptr != nullptr ? user_ptr->ctxt.rnti : SRSRAN_INVALID_RNTI;
|
||||
}
|
||||
container.amf_ue_ngap_id_present = amf_ue_ngap_id.has_value();
|
||||
if (amf_ue_ngap_id.has_value()) {
|
||||
container.amf_ue_ngap_id.value = amf_ue_ngap_id.value();
|
||||
}
|
||||
|
||||
container.cause_present = true;
|
||||
container.cause.value = cause;
|
||||
|
||||
return sctp_send_ngap_pdu(tx_pdu, rnti, "Error Indication");
|
||||
}
|
||||
/*******************************************************************************
|
||||
/* NGAP connection helpers
|
||||
********************************************************************************/
|
||||
|
@ -596,134 +656,6 @@ bool ngap::setup_ng()
|
|||
return sctp_send_ngap_pdu(pdu, 0, "ngSetupRequest");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/* NGAP message senders
|
||||
********************************************************************************/
|
||||
|
||||
bool ngap::ue::send_initialuemessage(asn1::ngap_nr::rrcestablishment_cause_e cause,
|
||||
srsran::unique_byte_buffer_t pdu,
|
||||
bool has_tmsi,
|
||||
uint32_t s_tmsi)
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_UE_MSG);
|
||||
init_ue_msg_ies_container& container = tx_pdu.init_msg().value.init_ue_msg().protocol_ies;
|
||||
|
||||
// 5G-S-TMSI
|
||||
if (has_tmsi) {
|
||||
container.five_g_s_tmsi_present = true;
|
||||
srsran::uint32_to_uint8(s_tmsi, container.five_g_s_tmsi.value.five_g_tmsi.data());
|
||||
container.five_g_s_tmsi.value.amf_set_id.from_number(ctxt.amf_set_id);
|
||||
container.five_g_s_tmsi.value.amf_pointer.from_number(ctxt.amf_pointer);
|
||||
}
|
||||
|
||||
// RAN_UE_NGAP_ID
|
||||
container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
// NAS_PDU
|
||||
container.nas_pdu.value.resize(pdu->N_bytes);
|
||||
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
|
||||
|
||||
// RRC Establishment Cause
|
||||
container.rrcestablishment_cause.value = cause;
|
||||
|
||||
// User Location Info
|
||||
|
||||
// userLocationInformationNR
|
||||
container.user_location_info.value.set_user_location_info_nr();
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id;
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac;
|
||||
|
||||
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "InitialUEMessage");
|
||||
}
|
||||
|
||||
bool ngap::ue::send_ulnastransport(srsran::unique_byte_buffer_t pdu)
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_UL_NAS_TRANSPORT);
|
||||
asn1::ngap_nr::ul_nas_transport_ies_container& container = tx_pdu.init_msg().value.ul_nas_transport().protocol_ies;
|
||||
|
||||
// AMF UE NGAP ID
|
||||
container.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value();
|
||||
|
||||
// RAN UE NGAP ID
|
||||
container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
// NAS PDU
|
||||
container.nas_pdu.value.resize(pdu->N_bytes);
|
||||
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
|
||||
|
||||
// User Location Info
|
||||
// userLocationInformationNR
|
||||
container.user_location_info.value.set_user_location_info_nr();
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id;
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac;
|
||||
|
||||
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UplinkNASTransport");
|
||||
}
|
||||
|
||||
void ngap::ue::ue_ctxt_setup_complete()
|
||||
{
|
||||
ngap_pdu_c tx_pdu;
|
||||
// Handle PDU Session List once RRC interface is ready
|
||||
tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP);
|
||||
auto& container = tx_pdu.successful_outcome().value.init_context_setup_resp().protocol_ies;
|
||||
}
|
||||
|
||||
bool ngap::send_error_indication(const asn1::ngap_nr::cause_c& cause,
|
||||
srsran::optional<uint32_t> ran_ue_ngap_id,
|
||||
srsran::optional<uint32_t> amf_ue_ngap_id)
|
||||
{
|
||||
if (not amf_connected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_ERROR_IND);
|
||||
auto& container = tx_pdu.init_msg().value.error_ind().protocol_ies;
|
||||
|
||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||
container.ran_ue_ngap_id_present = ran_ue_ngap_id.has_value();
|
||||
if (ran_ue_ngap_id.has_value()) {
|
||||
container.ran_ue_ngap_id.value = ran_ue_ngap_id.value();
|
||||
ue* user_ptr = users.find_ue_gnbid(ran_ue_ngap_id.value());
|
||||
rnti = user_ptr != nullptr ? user_ptr->ctxt.rnti : SRSRAN_INVALID_RNTI;
|
||||
}
|
||||
container.amf_ue_ngap_id_present = amf_ue_ngap_id.has_value();
|
||||
if (amf_ue_ngap_id.has_value()) {
|
||||
container.amf_ue_ngap_id.value = amf_ue_ngap_id.value();
|
||||
}
|
||||
|
||||
container.cause_present = true;
|
||||
container.cause.value = cause;
|
||||
|
||||
return sctp_send_ngap_pdu(tx_pdu, rnti, "Error Indication");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/* ngap::ue Class
|
||||
********************************************************************************/
|
||||
|
||||
ngap::ue::ue(ngap* ngap_ptr_) : ngap_ptr(ngap_ptr_)
|
||||
{
|
||||
ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++;
|
||||
gettimeofday(&ctxt.init_timestamp, nullptr);
|
||||
|
||||
stream_id = ngap_ptr->next_ue_stream_id;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/* General helpers
|
||||
********************************************************************************/
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/ngap/ngap_ue.h"
|
||||
#include "srsenb/hdr/stack/ngap/ngap.h"
|
||||
#include "srsenb/hdr/stack/ngap/ngap_ue_proc.h"
|
||||
#include "srsran/common/int_helpers.h"
|
||||
|
||||
using namespace asn1::ngap_nr;
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/*******************************************************************************
|
||||
/* ngap_ptr::ue Class
|
||||
********************************************************************************/
|
||||
|
||||
ngap::ue::ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_logger& logger_) :
|
||||
logger(logger_),
|
||||
ngap_ptr(ngap_ptr_),
|
||||
rrc_ptr(rrc_ptr_),
|
||||
initial_context_setup_proc(this, rrc_ptr, &ctxt),
|
||||
ue_context_release_proc(this, rrc_ptr, &ctxt)
|
||||
{
|
||||
ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++;
|
||||
gettimeofday(&ctxt.init_timestamp, nullptr);
|
||||
stream_id = ngap_ptr->next_ue_stream_id;
|
||||
}
|
||||
|
||||
ngap::ue::~ue() {}
|
||||
|
||||
/*******************************************************************************
|
||||
/* NGAP message senders
|
||||
********************************************************************************/
|
||||
|
||||
bool ngap::ue::send_initial_ue_message(asn1::ngap_nr::rrcestablishment_cause_e cause,
|
||||
srsran::unique_byte_buffer_t pdu,
|
||||
bool has_tmsi,
|
||||
uint32_t s_tmsi)
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
logger.warning("AMF not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_UE_MSG);
|
||||
init_ue_msg_ies_container& container = tx_pdu.init_msg().value.init_ue_msg().protocol_ies;
|
||||
|
||||
// 5G-S-TMSI
|
||||
if (has_tmsi) {
|
||||
container.five_g_s_tmsi_present = true;
|
||||
srsran::uint32_to_uint8(s_tmsi, container.five_g_s_tmsi.value.five_g_tmsi.data());
|
||||
container.five_g_s_tmsi.value.amf_set_id.from_number(ctxt.amf_set_id);
|
||||
container.five_g_s_tmsi.value.amf_pointer.from_number(ctxt.amf_pointer);
|
||||
}
|
||||
|
||||
// RAN_UE_NGAP_ID
|
||||
container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
// NAS_PDU
|
||||
container.nas_pdu.value.resize(pdu->N_bytes);
|
||||
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
|
||||
|
||||
// RRC Establishment Cause
|
||||
container.rrcestablishment_cause.value = cause;
|
||||
|
||||
// User Location Info
|
||||
|
||||
// userLocationInformationNR
|
||||
container.user_location_info.value.set_user_location_info_nr();
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id;
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac;
|
||||
|
||||
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "InitialUEMessage");
|
||||
}
|
||||
|
||||
bool ngap::ue::send_ul_nas_transport(srsran::unique_byte_buffer_t pdu)
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
logger.warning("AMF not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_UL_NAS_TRANSPORT);
|
||||
asn1::ngap_nr::ul_nas_transport_ies_container& container = tx_pdu.init_msg().value.ul_nas_transport().protocol_ies;
|
||||
|
||||
// AMF UE NGAP ID
|
||||
container.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value();
|
||||
|
||||
// RAN UE NGAP ID
|
||||
container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
// NAS PDU
|
||||
container.nas_pdu.value.resize(pdu->N_bytes);
|
||||
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
|
||||
|
||||
// User Location Info
|
||||
// userLocationInformationNR
|
||||
container.user_location_info.value.set_user_location_info_nr();
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id;
|
||||
container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id;
|
||||
container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac;
|
||||
|
||||
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UplinkNASTransport");
|
||||
}
|
||||
|
||||
void ngap::ue::ue_ctxt_setup_complete()
|
||||
{
|
||||
ngap_pdu_c tx_pdu;
|
||||
// Handle PDU Session List once RRC interface is ready
|
||||
tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP);
|
||||
auto& container = tx_pdu.successful_outcome().value.init_context_setup_resp().protocol_ies;
|
||||
}
|
||||
|
||||
void ngap::ue::notify_rrc_reconf_complete(const bool outcome)
|
||||
{
|
||||
initial_context_setup_proc.trigger(outcome);
|
||||
}
|
||||
|
||||
bool ngap::ue::send_initial_ctxt_setup_response()
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
logger.warning("AMF not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP);
|
||||
init_context_setup_resp_s& container = tx_pdu.successful_outcome().value.init_context_setup_resp();
|
||||
|
||||
// AMF UE NGAP ID
|
||||
container.protocol_ies.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value();
|
||||
|
||||
// RAN UE NGAP ID
|
||||
container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
/* // TODO: PDU Session Resource Setup Response List - Integrate PDU Session and Bearer management into NGAP
|
||||
container.protocol_ies.pdu_session_res_setup_list_cxt_res_present = true;
|
||||
|
||||
// Case PDU Session Resource Failed to Setup List
|
||||
container.protocol_ies.pdu_session_res_failed_to_setup_list_cxt_res_present = true; */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::ue::send_initial_ctxt_setup_failure(cause_c cause)
|
||||
{
|
||||
if (not ngap_ptr->amf_connected) {
|
||||
logger.warning("AMF not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
ngap_pdu_c tx_pdu;
|
||||
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP);
|
||||
init_context_setup_fail_s& container = tx_pdu.unsuccessful_outcome().value.init_context_setup_fail();
|
||||
|
||||
// AMF UE NGAP ID
|
||||
container.protocol_ies.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value();
|
||||
|
||||
// RAN UE NGAP ID
|
||||
container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
|
||||
|
||||
/* // TODO: PDU Session Resource Setup Response List - Integrate PDU Session and Bearer management into NGAP
|
||||
container.protocol_ies.pdu_session_res_setup_list_cxt_res_present = true;
|
||||
|
||||
// Case PDU Session Resource Failed to Setup List
|
||||
container.protocol_ies.pdu_session_res_failed_to_setup_list_cxt_res_present = true; */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/* NGAP message handler
|
||||
********************************************************************************/
|
||||
|
||||
bool ngap::ue::handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg)
|
||||
{
|
||||
if (not initial_context_setup_proc.launch(msg)) {
|
||||
logger.error("Failed to start Initial Context Setup Procedure");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ngap::ue::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg)
|
||||
{
|
||||
// TODO: Release UE context
|
||||
if (not ue_context_release_proc.launch(msg)) {
|
||||
logger.error("Failed to start UE Context Release Procedure");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/ngap/ngap_ue_proc.h"
|
||||
|
||||
using namespace srsran;
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
ngap_ue_initial_context_setup_proc::ngap_ue_initial_context_setup_proc(ngap_interface_ngap_proc* parent_,
|
||||
rrc_interface_ngap_nr* rrc_,
|
||||
ngap_ue_ctxt_t* ue_ctxt_) :
|
||||
logger(srslog::fetch_basic_logger("NGAP UE"))
|
||||
{
|
||||
parent = parent_;
|
||||
rrc = rrc_;
|
||||
ue_ctxt = ue_ctxt_;
|
||||
};
|
||||
|
||||
proc_outcome_t ngap_ue_initial_context_setup_proc::init(const asn1::ngap_nr::init_context_setup_request_s& msg)
|
||||
{
|
||||
ue_ctxt->amf_pointer = msg.protocol_ies.guami.value.amf_pointer.to_number();
|
||||
ue_ctxt->amf_set_id = msg.protocol_ies.guami.value.amf_set_id.to_number();
|
||||
ue_ctxt->amf_region_id = msg.protocol_ies.guami.value.amf_region_id.to_number();
|
||||
|
||||
if (msg.protocol_ies.ue_aggregate_maximum_bit_rate_present == true) {
|
||||
rrc->ue_set_bitrates(ue_ctxt->rnti, msg.protocol_ies.ue_aggregate_maximum_bit_rate.value);
|
||||
}
|
||||
rrc->ue_set_security_cfg_capabilities(ue_ctxt->rnti, msg.protocol_ies.ue_security_cap.value);
|
||||
rrc->ue_set_security_cfg_key(ue_ctxt->rnti, msg.protocol_ies.security_key.value);
|
||||
rrc->start_security_mode_procedure(ue_ctxt->rnti);
|
||||
|
||||
if (msg.protocol_ies.nas_pdu_present) {
|
||||
srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
|
||||
if (pdu == nullptr) {
|
||||
logger.error("Fatal Error: Couldn't allocate buffer in ngap_ue_initial_context_setup_proc::init().");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size());
|
||||
pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size();
|
||||
rrc->write_dl_info(ue_ctxt->rnti, std::move(pdu));
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
};
|
||||
|
||||
proc_outcome_t ngap_ue_initial_context_setup_proc::react(bool security_mode_command_outcome)
|
||||
{
|
||||
if(security_mode_command_outcome == true) {
|
||||
parent->send_initial_ctxt_setup_response();
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
// TODO: error handling if security mode command fails
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
proc_outcome_t ngap_ue_initial_context_setup_proc::step()
|
||||
{
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
ngap_ue_ue_context_release_proc::ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_,
|
||||
rrc_interface_ngap_nr* rrc_,
|
||||
ngap_ue_ctxt_t* ue_ctxt_) :
|
||||
logger(srslog::fetch_basic_logger("NGAP UE"))
|
||||
{
|
||||
parent = parent_;
|
||||
rrc = rrc_;
|
||||
ue_ctxt = ue_ctxt_;
|
||||
};
|
||||
|
||||
proc_outcome_t ngap_ue_ue_context_release_proc::init(const asn1::ngap_nr::ue_context_release_cmd_s& msg)
|
||||
{
|
||||
// ue_ngap_ids_c ue_ngap_ids = msg.protocol_ies.ue_ngap_ids.value;
|
||||
// cause_c cause = msg.protocol_ies.cause.value;
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
|
||||
proc_outcome_t ngap_ue_ue_context_release_proc::step()
|
||||
{
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
|
@ -366,6 +366,28 @@ void rrc_nr::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_
|
|||
|
||||
void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {}
|
||||
|
||||
/*******************************************************************************
|
||||
NGAP interface
|
||||
*******************************************************************************/
|
||||
|
||||
int rrc_nr::ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int rrc_nr::ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int rrc_nr::ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int rrc_nr::start_security_mode_procedure(uint16_t rnti)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
void rrc_nr::write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {}
|
||||
|
||||
/*******************************************************************************
|
||||
Interface for EUTRA RRC
|
||||
*******************************************************************************/
|
||||
|
|
|
@ -62,6 +62,24 @@ struct amf_dummy {
|
|||
srsran::unique_byte_buffer_t last_sdu;
|
||||
};
|
||||
|
||||
class rrc_nr_dummy : public rrc_interface_ngap_nr
|
||||
{
|
||||
public:
|
||||
int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps)
|
||||
{
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int start_security_mode_procedure(uint16_t rnti) { return SRSRAN_SUCCESS; }
|
||||
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {}
|
||||
};
|
||||
struct dummy_socket_manager : public srsran::socket_manager_itf {
|
||||
dummy_socket_manager() : srsran::socket_manager_itf(srslog::fetch_basic_logger("TEST")) {}
|
||||
|
||||
|
@ -143,7 +161,8 @@ int main(int argc, char** argv)
|
|||
args.gtp_bind_addr = "127.0.0.100";
|
||||
args.amf_addr = "127.0.0.1";
|
||||
args.gnb_name = "srsgnb01";
|
||||
rrc_interface_ngap_nr rrc;
|
||||
|
||||
rrc_nr_dummy rrc;
|
||||
ngap_obj.init(args, &rrc);
|
||||
|
||||
// Start the log backend.
|
||||
|
|
Loading…
Reference in New Issue