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

master
Francisco 3 years ago committed by Francisco Paisana
parent 091877fd2a
commit 11b4a572a0

@ -47,7 +47,7 @@ public:
virtual void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) = 0;
virtual bool user_exists(uint16_t 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 void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0;
};

@ -29,6 +29,7 @@ public:
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 release_user(uint16_t rnti) = 0;
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
};

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

@ -51,22 +51,25 @@ public:
void initial_ue(uint16_t rnti,
uint32_t gnb_cc_idx,
asn1::ngap_nr::rrcestablishment_cause_e cause,
srsran::const_byte_span pdu);
srsran::const_byte_span pdu) override;
void initial_ue(uint16_t rnti,
uint32_t gnb_cc_idx,
asn1::ngap_nr::rrcestablishment_cause_e cause,
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);
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; };
bool is_amf_connected();
void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) override;
bool user_exists(uint16_t rnti) override { return true; };
void user_mod(uint16_t old_rnti, uint16_t new_rnti) override {}
// 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,
srsran::optional<uint32_t> ran_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();
// Stack interface

@ -48,6 +48,8 @@ public:
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.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
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

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

@ -103,6 +103,7 @@ public:
srsran::const_byte_span nas_pdu,
uint32_t lcid) 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;
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;

@ -90,7 +90,7 @@ private:
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);
/* 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_reject(uint8_t reject_wait_time_secs);

@ -265,6 +265,23 @@ void ngap::write_pdu(uint16_t rnti, srsran::const_byte_span 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
*********************************************************/

@ -244,6 +244,43 @@ bool ngap::ue::send_ue_ctxt_release_complete()
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
********************************************************************************/

@ -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)
{
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);
rrc->release_user(ue_ctxt->rnti);
parent->send_ue_ctxt_release_complete();
return proc_outcome_t::success;
}

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

@ -629,6 +629,16 @@ int rrc_nr::release_bearers(uint16_t rnti)
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)
{
return SRSRAN_SUCCESS;

@ -96,8 +96,8 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type)
case UE_INACTIVITY_TIMEOUT: {
state = rrc_nr_state_t::RRC_INACTIVE;
if (parent->cfg.is_standalone) {
// TODO: This procedure needs to be defined
parent->rrc_release(rnti);
// Start NGAP Release UE context
parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::user_inactivity);
} else {
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();
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
srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__);
if (pdu == nullptr) {
send_rrc_release();
parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available);
return;
}
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;
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()
{
// 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)
@ -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());
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);
}
}

Loading…
Cancel
Save