Added deregistration (UE terminating)

master
Bedran Karakoc 3 years ago committed by Bedran Karakoc
parent b0430ebfe2
commit 850606f20b

@ -29,6 +29,7 @@ public:
virtual int
establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0;
virtual int allocate_lcid(uint16_t rnti) = 0;
virtual int release_bearers(uint16_t rnti) = 0;
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
};

@ -21,9 +21,10 @@ class ngap_interface_ngap_proc
public:
virtual bool send_initial_ctxt_setup_response() = 0;
virtual bool
send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_out,
asn1::bounded_bitstring<1, 160, true, true> transport_layer_address) = 0;
send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_out,
asn1::bounded_bitstring<1, 160, true, true> transport_layer_address) = 0;
virtual bool send_ue_ctxt_release_complete() = 0;
};
} // namespace srsenb

@ -44,6 +44,8 @@ public:
bool send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_in,
asn1::bounded_bitstring<1, 160, true, true> addr_in);
// TS 38.413 - Section 9.2.1.2 - UE Context Release Complete
bool send_ue_ctxt_release_complete();
// 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

@ -54,6 +54,8 @@ public:
uint32_t& teid_in,
asn1::ngap_nr::cause_c& cause);
int reset_pdu_sessions(uint16_t rnti);
private:
gtpu_interface_rrc* gtpu = nullptr;
rrc_interface_ngap_nr* rrc = nullptr;

@ -16,12 +16,12 @@
#include "ngap_interfaces.h"
#include "ngap_ue_utils.h"
#include "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.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 "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h"
#include <map>
#include <string>
@ -57,6 +57,7 @@ public:
explicit ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_,
rrc_interface_ngap_nr* rrc_,
ngap_ue_ctxt_t* ue_ctxt,
ngap_ue_bearer_manager* bearer_manager,
srslog::basic_logger& logger_);
srsran::proc_outcome_t init(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
srsran::proc_outcome_t step();
@ -64,8 +65,9 @@ public:
private:
ngap_ue_ctxt_t* ue_ctxt;
ngap_interface_ngap_proc* parent = nullptr;
rrc_interface_ngap_nr* rrc = nullptr;
ngap_interface_ngap_proc* parent = nullptr;
rrc_interface_ngap_nr* rrc = nullptr;
ngap_ue_bearer_manager* bearer_manager = nullptr;
srslog::basic_logger& logger;
};

@ -95,6 +95,7 @@ public:
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);
int establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid);
int release_bearers(uint16_t rnti);
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu);
int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates);
int allocate_lcid(uint16_t rnti);

@ -112,7 +112,7 @@ ngap::ngap(srsran::task_sched_handle task_sched_,
ngap::~ngap() {}
int ngap::init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc * gtpu_)
int ngap::init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc* gtpu_)
{
rrc = rrc_;
args = args_;
@ -537,14 +537,21 @@ bool ngap::handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_s
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
const asn1::ngap_nr::ue_ngap_id_pair_s& ue_ngap_id_pair = msg.protocol_ies.ue_ngap_ids.value.ue_ngap_id_pair();
ue* u = handle_ngapmsg_ue_id(ue_ngap_id_pair.ran_ue_ngap_id, ue_ngap_id_pair.amf_ue_ngap_id);
if (u == nullptr) {
logger.warning("Can not find UE");
return false;
}
u->handle_ue_ctxt_release_cmd(msg);
return true;
}
bool ngap::handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_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) {

@ -31,7 +31,7 @@ ngap::ue::ue(ngap* ngap_ptr_,
ngap_ptr(ngap_ptr_),
bearer_manager(rrc_ptr_, gtpu_ptr_, logger_),
initial_context_setup_proc(this, rrc_ptr_, &ctxt, logger_),
ue_context_release_proc(this, rrc_ptr_, &ctxt, logger_),
ue_context_release_proc(this, rrc_ptr_, &ctxt, &bearer_manager, logger_),
ue_pdu_session_res_setup_proc(this, rrc_ptr_, &ctxt, &bearer_manager, logger_)
{
ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++;
@ -223,6 +223,30 @@ bool ngap::ue::send_pdu_session_resource_setup_response(uint16_t
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "PDUSessionResourceSetupResponse");
}
bool ngap::ue::send_ue_ctxt_release_complete()
{
if (not ngap_ptr->amf_connected) {
logger.warning("AMF not connected");
return false;
}
ngap_pdu_c tx_pdu;
tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_UE_CONTEXT_RELEASE);
ue_context_release_complete_s& container = tx_pdu.successful_outcome().value.ue_context_release_complete();
// userLocationInformationNR
container.protocol_ies.user_location_info.value.set_user_location_info_nr();
container.protocol_ies.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id;
container.protocol_ies.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id;
container.protocol_ies.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id;
container.protocol_ies.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac;
container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id;
container.protocol_ies.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value();
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete");
}
/*******************************************************************************
/* NGAP message handler
********************************************************************************/

@ -61,6 +61,15 @@ int ngap_ue_bearer_manager::add_pdu_session(uint16_t
return SRSRAN_SUCCESS;
}
int ngap_ue_bearer_manager::reset_pdu_sessions(uint16_t rnti)
{
for (auto iter = pdu_session_list.begin(); iter != pdu_session_list.end(); iter++) {
auto pdu_session_id = iter->first;
rem_gtpu_bearer(pdu_session_id, rnti);
}
return true;
}
int ngap_ue_bearer_manager::add_gtpu_bearer(uint16_t rnti,
uint32_t lcid,
uint32_t pdu_session_id,

@ -66,19 +66,23 @@ proc_outcome_t ngap_ue_initial_context_setup_proc::step()
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_,
ngap_ue_bearer_manager* bearer_manager_,
srslog::basic_logger& logger_) :
logger(logger_)
{
parent = parent_;
rrc = rrc_;
ue_ctxt = ue_ctxt_;
parent = parent_;
rrc = rrc_;
ue_ctxt = ue_ctxt_;
bearer_manager = bearer_manager_;
};
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;
logger.info("Started %s", name());
// TODO: How to approach erasing users ?
bearer_manager->reset_pdu_sessions(ue_ctxt->rnti);
rrc->release_bearers(ue_ctxt->rnti);
parent->send_initial_ctxt_setup_response();
return proc_outcome_t::success;
}

@ -450,6 +450,11 @@ int rrc_nr::establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran:
return SRSRAN_SUCCESS;
}
int rrc_nr::release_bearers(uint16_t rnti)
{
return SRSRAN_SUCCESS;
}
int rrc_nr::allocate_lcid(uint16_t rnti)
{
return SRSRAN_SUCCESS;

@ -86,6 +86,7 @@ public:
{
return SRSRAN_SUCCESS;
}
int release_bearers(uint16_t rnti) { return SRSRAN_SUCCESS; }
int allocate_lcid(uint16_t rnti) { return SRSRAN_SUCCESS; }
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {}
};

@ -80,7 +80,7 @@ private:
srsran::nas_5g::nas_5gs_msg initial_registration_request_stored;
nas_args_t cfg = {};
nas_args_t cfg = {};
mm5g_state_t state;
// Security
@ -132,10 +132,12 @@ private:
int send_pdu_session_establishment_request(uint32_t transaction_identity,
uint16_t pdu_session_id,
const pdu_session_cfg_t& pdu_session);
int send_deregistration_request_ue_originating();
void fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps);
int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type);
int handle_deregistration_accept_ue_originating(
srsran::nas_5g::deregistration_accept_ue_originating_t& deregistration_accept_ue_originating);
// message handler
int handle_registration_accept(srsran::nas_5g::registration_accept_t& registration_accept);
int handle_registration_reject(srsran::nas_5g::registration_reject_t& registration_reject);
@ -168,6 +170,7 @@ private:
int configure_pdu_session(uint16_t pdu_session_id);
bool unestablished_pdu_sessions();
int get_unestablished_pdu_session(uint16_t& pdu_session_id, pdu_session_cfg_t& pdu_session_cfg);
int reset_pdu_sessions();
struct pdu_session_t {
bool configured;

@ -136,6 +136,7 @@ void nas_5g::run_tti()
break;
case mm5g_state_t::state_t::deregistered_initiated:
logger.debug("UE detaching...");
send_deregistration_request_ue_originating();
break;
default:
break;
@ -222,6 +223,9 @@ int nas_5g::write_pdu(srsran::unique_byte_buffer_t pdu)
case msg_opts::options::dl_nas_transport:
handle_dl_nas_transport(nas_msg.dl_nas_transport());
break;
case msg_opts::options::deregistration_accept_ue_originating:
handle_deregistration_accept_ue_originating(nas_msg.deregistration_accept_ue_originating());
break;
default:
logger.error(
"Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type);
@ -587,6 +591,51 @@ int nas_5g::send_pdu_session_establishment_request(uint32_t tran
return SRSRAN_SUCCESS;
}
int nas_5g::send_deregistration_request_ue_originating()
{
unique_byte_buffer_t pdu = srsran::make_byte_buffer();
if (!pdu) {
logger.error("Couldn't allocate PDU in %s().", __FUNCTION__);
return SRSRAN_ERROR;
}
logger.info("Generating Deregistration Request (UE Originating)");
nas_5gs_msg nas_msg;
deregistration_request_ue_originating_t& deregistration_request = nas_msg.set_deregistration_request_ue_originating();
// Note 5.5.2.2.2 : AMF does not send a Deregistration Accept NAS message if De-registration type IE indicates "switch
// off"
deregistration_request.de_registration_type.switch_off.value =
de_registration_type_t::switch_off_type_::options::normal_de_registration;
mobile_identity_5gs_t::suci_s& suci = deregistration_request.mobile_identity_5gs.set_suci();
suci.supi_format = mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi;
usim->get_home_mcc_bytes(suci.mcc.data(), suci.mcc.size());
usim->get_home_mnc_bytes(suci.mnc.data(), suci.mnc.size());
deregistration_request.ng_ksi.nas_key_set_identifier.value =
key_set_identifier_t::nas_key_set_identifier_type_::options::no_key_is_available_or_reserved;
if (nas_msg.pack(pdu) != SRSASN_SUCCESS) {
logger.error("Failed to pack Deregistration Request (UE Originating).");
return SRSRAN_ERROR;
}
if (pcap != nullptr) {
pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes);
}
logger.info("Sending Deregistration Request (UE Originating)");
rrc_nr->write_sdu(std::move(pdu));
reset_pdu_sessions();
// TODO: Delete / Reset context (ctxt & ctxt_5g)
return SRSASN_SUCCESS;
}
// Message handler
int nas_5g::handle_registration_accept(registration_accept_t& registration_accept)
{
@ -797,6 +846,13 @@ int nas_5g::handle_n1_sm_information(std::vector<uint8_t> payload_container_cont
return SRSRAN_SUCCESS;
}
int nas_5g::handle_deregistration_accept_ue_originating(
srsran::nas_5g::deregistration_accept_ue_originating_t& deregistration_accept_ue_originating)
{
logger.info("Received Deregistration Request (UE Originating)");
return SRSASN_SUCCESS;
}
/*******************************************************************************
* NAS Timers
******************************************************************************/
@ -823,7 +879,7 @@ int nas_5g::switch_on()
int nas_5g::switch_off()
{
logger.info("Switching off");
// TODO
state.set_deregistered_initiated();
return SRSRAN_SUCCESS;
}
@ -847,6 +903,16 @@ int nas_5g::start_service_request()
return SRSRAN_SUCCESS;
}
int nas_5g::reset_pdu_sessions()
{
for (auto pdu_session : pdu_sessions) {
pdu_session.established = false;
pdu_session.pdu_session_id = 0;
}
return SRSRAN_SUCCESS;
}
/*******************************************************************************
* Helpers
******************************************************************************/
@ -905,7 +971,7 @@ void nas_5g::fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_ca
}
/*******************************************************************************
* Helpers for Session Management
* Helpers for Session Management
******************************************************************************/
int nas_5g::trigger_pdu_session_est()

Loading…
Cancel
Save