nr,gnb,rrc&ngap: implementation of NGAP UE Context Release Request and RRC Release for the case RRC_CONNECTED->RRC_IDLE

This commit is contained in:
Francisco 2021-12-01 16:40:43 +00:00 committed by Francisco Paisana
parent 091877fd2a
commit 11b4a572a0
14 changed files with 117 additions and 30 deletions

View File

@ -44,12 +44,12 @@ public:
srsran::const_byte_span pdu, srsran::const_byte_span pdu,
uint32_t m_tmsi) = 0; uint32_t m_tmsi) = 0;
virtual void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) = 0; virtual void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) = 0;
virtual bool user_exists(uint16_t rnti) = 0; virtual bool user_exists(uint16_t rnti) = 0;
virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0; virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0; virtual void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0;
virtual bool is_amf_connected() = 0; virtual bool is_amf_connected() = 0;
virtual void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0; virtual void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0;
}; };
} // namespace srsenb } // namespace srsenb

View File

@ -26,10 +26,11 @@ public:
virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 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, srsran::unique_byte_buffer_t nas_pdu) = 0; virtual int start_security_mode_procedure(uint16_t rnti, srsran::unique_byte_buffer_t nas_pdu) = 0;
virtual int virtual int
establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0; 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 allocate_lcid(uint16_t rnti) = 0;
virtual int release_bearers(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; virtual void release_user(uint16_t rnti) = 0;
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
}; };
} // namespace srsenb } // namespace srsenb

View File

@ -36,7 +36,7 @@ class ngap_dummy : public ngap_interface_rrc_nr
void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) {} void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) {}
bool user_exists(uint16_t rnti) { return true; } bool user_exists(uint16_t rnti) { return true; }
void user_mod(uint16_t old_rnti, uint16_t new_rnti) {} 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; } void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) {}
bool is_amf_connected() { return true; } bool is_amf_connected() { return true; }
void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) {} void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) {}
}; };

View File

@ -51,27 +51,30 @@ public:
void initial_ue(uint16_t rnti, void initial_ue(uint16_t rnti,
uint32_t gnb_cc_idx, uint32_t gnb_cc_idx,
asn1::ngap_nr::rrcestablishment_cause_e cause, asn1::ngap_nr::rrcestablishment_cause_e cause,
srsran::const_byte_span pdu); srsran::const_byte_span pdu) override;
void initial_ue(uint16_t rnti, void initial_ue(uint16_t rnti,
uint32_t gnb_cc_idx, uint32_t gnb_cc_idx,
asn1::ngap_nr::rrcestablishment_cause_e cause, asn1::ngap_nr::rrcestablishment_cause_e cause,
srsran::const_byte_span pdu, srsran::const_byte_span pdu,
uint32_t s_tmsi); uint32_t s_tmsi) override;
void write_pdu(uint16_t rnti, srsran::const_byte_span pdu); void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) override;
bool user_exists(uint16_t rnti) { return true; }; bool user_exists(uint16_t rnti) override { return true; };
void user_mod(uint16_t old_rnti, uint16_t new_rnti){}; void user_mod(uint16_t old_rnti, uint16_t new_rnti) override {}
bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; };
bool is_amf_connected(); // TS 38.413 - Section 8.3.2 - UE Context Release Request
void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) override;
bool is_amf_connected() override;
bool send_error_indication(const asn1::ngap_nr::cause_c& cause, bool send_error_indication(const asn1::ngap_nr::cause_c& cause,
srsran::optional<uint32_t> ran_ue_ngap_id = {}, srsran::optional<uint32_t> ran_ue_ngap_id = {},
srsran::optional<uint32_t> amf_ue_ngap_id = {}); srsran::optional<uint32_t> amf_ue_ngap_id = {});
void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome); void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) override;
bool send_pdu_session_resource_setup_response(); bool send_pdu_session_resource_setup_response();
// Stack interface // Stack interface
bool bool
handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags);
void get_metrics(ngap_metrics_t& m); void get_metrics(ngap_metrics_t& m);
void get_args(ngap_args_t& args_); void get_args(ngap_args_t& args_);

View File

@ -48,6 +48,8 @@ public:
bool send_ue_ctxt_release_complete(); bool send_ue_ctxt_release_complete();
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request // 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); bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg);
// TS 38.413 - Section 9.2.2.4 - UE Context Release Request
bool send_ue_context_release_request(asn1::ngap_nr::cause_c cause);
// TS 38.413 - Section 9.2.2.5 - UE Context Release Command // 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 handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
// TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request // TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request

View File

@ -56,6 +56,8 @@ public:
int reset_pdu_sessions(uint16_t rnti); int reset_pdu_sessions(uint16_t rnti);
const std::map<uint8_t, pdu_session_t>& pdu_sessions() const { return pdu_session_list; }
private: private:
gtpu_interface_rrc* gtpu = nullptr; gtpu_interface_rrc* gtpu = nullptr;
std::map<uint8_t, pdu_session_t> pdu_session_list; std::map<uint8_t, pdu_session_t> pdu_session_list;

View File

@ -103,6 +103,7 @@ public:
srsran::const_byte_span nas_pdu, srsran::const_byte_span nas_pdu,
uint32_t lcid) final; uint32_t lcid) final;
int release_bearers(uint16_t rnti) final; int release_bearers(uint16_t rnti) final;
void release_user(uint16_t rnti) final;
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final; void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final;
int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final;
int allocate_lcid(uint16_t rnti) final; int allocate_lcid(uint16_t rnti) final;

View File

@ -90,7 +90,7 @@ private:
int send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg); int send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg);
int send_dl_dcch(srsran::nr_srb srb, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg); int send_dl_dcch(srsran::nr_srb srb, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg);
/* TS 38.331 - 5.3.3 RRC connection establishment */ /** TS 38.331 - 5.3.3 RRC connection establishment */
void send_rrc_setup(); void send_rrc_setup();
void send_rrc_reject(uint8_t reject_wait_time_secs); void send_rrc_reject(uint8_t reject_wait_time_secs);

View File

@ -265,6 +265,23 @@ void ngap::write_pdu(uint16_t rnti, srsran::const_byte_span pdu)
u->send_ul_nas_transport(pdu); u->send_ul_nas_transport(pdu);
} }
void ngap::user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio)
{
ue* u = users.find_ue_rnti(rnti);
if (u == nullptr) {
logger.warning("Released UE rnti=0x%x not found.", rnti);
return;
}
cause_c cause;
cause.set_radio_network().value = cause_radio;
if (not u->send_ue_context_release_request(cause)) {
logger.error("Failed to initiate RRC Release for rnti=0x%x. Removing user", rnti);
rrc->release_user(rnti);
users.erase(u);
}
}
/********************************************************* /*********************************************************
* ngap::user_list class * ngap::user_list class
*********************************************************/ *********************************************************/

View File

@ -244,6 +244,43 @@ bool ngap::ue::send_ue_ctxt_release_complete()
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete"); return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete");
} }
bool ngap::ue::send_ue_context_release_request(asn1::ngap_nr::cause_c cause)
{
if (not ngap_ptr->amf_connected) {
logger.warning("AMF not connected");
return false;
}
if (was_uectxtrelease_requested()) {
// let timeout auto-remove user.
return false;
}
release_requested = true;
ngap_pdu_c tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_UE_CONTEXT_RELEASE_REQUEST);
ue_context_release_request_s& container = tx_pdu.init_msg().value.ue_context_release_request();
container.protocol_ies.cause.value = cause;
// PDU Session Resource List
auto& session_lst = container.protocol_ies.pdu_session_res_list_cxt_rel_req.value;
for (const auto& pdu_pair : bearer_manager.pdu_sessions()) {
const ngap_ue_bearer_manager::pdu_session_t& session = pdu_pair.second;
pdu_session_res_item_cxt_rel_req_s obj;
obj.pdu_session_id = session.id;
session_lst.push_back(obj);
}
container.protocol_ies.pdu_session_res_list_cxt_rel_req_present = session_lst.size() > 0;
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();
// TODO: Implement timeout
return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseRequest");
}
/******************************************************************************* /*******************************************************************************
/* NGAP message handler /* NGAP message handler
********************************************************************************/ ********************************************************************************/

View File

@ -81,9 +81,8 @@ ngap_ue_ue_context_release_proc::ngap_ue_ue_context_release_proc(ngap_interface_
proc_outcome_t ngap_ue_ue_context_release_proc::init(const asn1::ngap_nr::ue_context_release_cmd_s& msg) proc_outcome_t ngap_ue_ue_context_release_proc::init(const asn1::ngap_nr::ue_context_release_cmd_s& msg)
{ {
logger.info("Started %s", name()); logger.info("Started %s", name());
// TODO: How to approach erasing users ?
bearer_manager->reset_pdu_sessions(ue_ctxt->rnti); bearer_manager->reset_pdu_sessions(ue_ctxt->rnti);
rrc->release_bearers(ue_ctxt->rnti); rrc->release_user(ue_ctxt->rnti);
parent->send_ue_ctxt_release_complete(); parent->send_ue_ctxt_release_complete();
return proc_outcome_t::success; return proc_outcome_t::success;
} }

View File

@ -115,6 +115,7 @@ public:
} }
int release_bearers(uint16_t rnti) { return SRSRAN_SUCCESS; } int release_bearers(uint16_t rnti) { return SRSRAN_SUCCESS; }
void release_user(uint16_t rnti) {}
int allocate_lcid(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) {} void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {}

View File

@ -629,6 +629,16 @@ int rrc_nr::release_bearers(uint16_t rnti)
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
void rrc_nr::release_user(uint16_t rnti)
{
if (not users.contains(rnti)) {
logger.warning("User rnti=0x%x has already been released", rnti);
return;
}
users[rnti]->send_rrc_release();
}
int rrc_nr::allocate_lcid(uint16_t rnti) int rrc_nr::allocate_lcid(uint16_t rnti)
{ {
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;

View File

@ -96,8 +96,8 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type)
case UE_INACTIVITY_TIMEOUT: { case UE_INACTIVITY_TIMEOUT: {
state = rrc_nr_state_t::RRC_INACTIVE; state = rrc_nr_state_t::RRC_INACTIVE;
if (parent->cfg.is_standalone) { if (parent->cfg.is_standalone) {
// TODO: This procedure needs to be defined // Start NGAP Release UE context
parent->rrc_release(rnti); parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::user_inactivity);
} else { } else {
parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti);
} }
@ -1017,7 +1017,7 @@ void rrc_nr::ue::send_security_mode_command(srsran::unique_byte_buffer_t nas_pdu
ies.security_cfg_smc.security_algorithm_cfg = sec_ctx.get_security_algorithm_cfg(); ies.security_cfg_smc.security_algorithm_cfg = sec_ctx.get_security_algorithm_cfg();
if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) {
send_rrc_release(); parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available);
} }
} }
@ -1061,7 +1061,7 @@ void rrc_nr::ue::send_rrc_reconfiguration()
// Pack masterCellGroup into container // Pack masterCellGroup into container
srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__); srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__);
if (pdu == nullptr) { if (pdu == nullptr) {
send_rrc_release(); parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available);
return; return;
} }
ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes); ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes);
@ -1097,7 +1097,7 @@ void rrc_nr::ue::send_rrc_reconfiguration()
ies.non_crit_ext_present = ies.non_crit_ext.master_cell_group_present or ies.non_crit_ext.ded_nas_msg_list_present; ies.non_crit_ext_present = ies.non_crit_ext.master_cell_group_present or ies.non_crit_ext.ded_nas_msg_list_present;
if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) {
send_rrc_release(); parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available);
} }
} }
@ -1112,7 +1112,21 @@ void rrc_nr::ue::handle_rrc_reconfiguration_complete(const asn1::rrc_nr::rrc_rec
void rrc_nr::ue::send_rrc_release() void rrc_nr::ue::send_rrc_release()
{ {
// TODO static const uint32_t release_delay = 60; // Taken from TS 38.331, 5.3.8.3
dl_dcch_msg_s dl_dcch_msg;
rrc_release_s& release = dl_dcch_msg.msg.set_c1().set_rrc_release();
release.rrc_transaction_id = (uint8_t)((transaction_id++) % 4);
rrc_release_ies_s& ies = release.crit_exts.set_rrc_release();
ies.suspend_cfg_present = false; // goes to RRC_IDLE
send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg);
state = rrc_nr_state_t::RRC_IDLE;
// TODO: Obtain acknowledgment from lower layers that RRC Release was received
parent->task_sched.defer_callback(release_delay, [this]() { parent->rem_user(rnti); });
} }
void rrc_nr::ue::send_dl_information_transfer(srsran::unique_byte_buffer_t sdu) void rrc_nr::ue::send_dl_information_transfer(srsran::unique_byte_buffer_t sdu)
@ -1126,7 +1140,7 @@ void rrc_nr::ue::send_dl_information_transfer(srsran::unique_byte_buffer_t sdu)
memcpy(ies.ded_nas_msg.data(), sdu->data(), ies.ded_nas_msg.size()); memcpy(ies.ded_nas_msg.data(), sdu->data(), ies.ded_nas_msg.size());
if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) {
send_rrc_release(); parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available);
} }
} }