mirror of https://github.com/PentHertz/srsLTE.git
enb,gnb: add basic support for sgnb release procedure
the procedure is currently started when the EUTRA UE object is deleted (after RRC release) in order to clean-up the ENDC resources on the gNB.
This commit is contained in:
parent
908c469f30
commit
255ddb1329
|
@ -40,6 +40,9 @@ public:
|
|||
|
||||
/// Provide information whether the requested configuration was applied successfully by the UE
|
||||
virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0;
|
||||
|
||||
/// Trigger release for specific UE
|
||||
virtual int sgnb_release_request(uint16_t nr_rnti) = 0;
|
||||
};
|
||||
|
||||
/// X2AP inspired interface for response from NR RRC to EUTRA RRC
|
||||
|
@ -82,6 +85,13 @@ public:
|
|||
*/
|
||||
virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0;
|
||||
|
||||
/**
|
||||
* @brief Signal release of all UE resources on the NR cell
|
||||
*
|
||||
* @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition
|
||||
*/
|
||||
virtual void sgnb_release_ack(uint16_t eutra_rnti) = 0;
|
||||
|
||||
/**
|
||||
* @brief Signal user activity (i.e. DL/UL traffic) for given RNTI
|
||||
*
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
// Note: RRC processes activity asynchronously, so there is no need to use x2_task_queue
|
||||
rrc.set_activity_user(eutra_rnti);
|
||||
}
|
||||
void sgnb_release_ack(uint16_t eutra_rnti) final { rrc.sgnb_release_ack(eutra_rnti); }
|
||||
|
||||
// gtpu_interface_pdcp
|
||||
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu);
|
||||
|
|
|
@ -89,6 +89,7 @@ public:
|
|||
{
|
||||
return rrc.sgnb_reconfiguration_complete(eutra_rnti, reconfig_response);
|
||||
};
|
||||
int sgnb_release_request(uint16_t nr_rnti) final { return rrc.sgnb_release_request(nr_rnti); };
|
||||
// X2 data interface
|
||||
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) final
|
||||
{
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
void sgnb_addition_ack(uint16_t eutra_rnti, const sgnb_addition_ack_params_t params) override;
|
||||
void sgnb_addition_reject(uint16_t eutra_rnti) override;
|
||||
void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) override;
|
||||
void sgnb_release_ack(uint16_t eutra_rnti) override;
|
||||
|
||||
// rrc_interface_pdcp
|
||||
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override;
|
||||
|
|
|
@ -49,12 +49,30 @@ public:
|
|||
uint16_t nr_rnti; /// RNTI assigned to UE on NR carrier
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Called from EUTRA-RRC when EN-DC (for UE) shall be removed/released
|
||||
*
|
||||
*/
|
||||
struct sgnb_rel_req_ev {
|
||||
uint16_t nr_rnti; /// RNTI assigned to UE on NR carrier
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event sent from NR-RRC to EUTRA when UE has been removed from SgNB
|
||||
*
|
||||
* sent in response to SgNB Release Request
|
||||
*/
|
||||
struct sgnb_rel_req_ack_ev {};
|
||||
|
||||
rrc_endc(srsenb::rrc::ue* outer_ue, const rrc_endc_cfg_t& endc_cfg_);
|
||||
~rrc_endc();
|
||||
|
||||
bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg);
|
||||
void handle_eutra_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps);
|
||||
void handle_ue_meas_report(const asn1::rrc::meas_report_s& msg);
|
||||
|
||||
void start_sgnb_release();
|
||||
|
||||
bool is_endc_supported();
|
||||
|
||||
private:
|
||||
|
@ -70,6 +88,7 @@ private:
|
|||
// vars
|
||||
bool endc_supported = false;
|
||||
rrc_endc_cfg_t endc_cfg = {};
|
||||
uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // C-RNTI assigned to UE on NR side
|
||||
asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete;
|
||||
|
||||
// fixed ENDC variables
|
||||
|
@ -94,22 +113,30 @@ private:
|
|||
};
|
||||
struct wait_add_complete_st {}; // user needs to complete RA procedure and send C-RNTI CE
|
||||
struct endc_activated_st {}; // user has enabled EN-DC successfully and is currently served
|
||||
struct wait_sgnb_rel_req_resp_st {}; // release EN-DC
|
||||
|
||||
// FSM guards
|
||||
|
||||
// FSM transition handlers
|
||||
void handle_sgnb_add_req_ack(wait_sgnb_add_req_resp_st& s, const sgnb_add_req_ack_ev& ev);
|
||||
void handle_sgnb_rel_req(endc_activated_st& s, const sgnb_rel_req_ev& ev);
|
||||
void handle_rrc_reest(wait_add_complete_st& s, const rrc_reest_rx_ev& ev);
|
||||
|
||||
protected:
|
||||
// states
|
||||
state_list<endc_deactivated_st, wait_sgnb_add_req_resp_st, prepare_recfg_st, wait_add_complete_st, endc_activated_st>
|
||||
state_list<endc_deactivated_st,
|
||||
wait_sgnb_add_req_resp_st,
|
||||
prepare_recfg_st,
|
||||
wait_add_complete_st,
|
||||
endc_activated_st,
|
||||
wait_sgnb_rel_req_resp_st>
|
||||
states{this,
|
||||
endc_deactivated_st{},
|
||||
wait_sgnb_add_req_resp_st{},
|
||||
prepare_recfg_st{this},
|
||||
wait_add_complete_st{},
|
||||
endc_activated_st{}};
|
||||
endc_activated_st{},
|
||||
wait_sgnb_rel_req_resp_st{}};
|
||||
|
||||
// transitions
|
||||
using fsm = rrc_endc;
|
||||
|
@ -123,8 +150,11 @@ protected:
|
|||
row< wait_sgnb_add_req_resp_st, endc_deactivated_st, sgnb_add_req_reject_ev >,
|
||||
row< prepare_recfg_st, wait_add_complete_st, rrc_recfg_sent_ev >,
|
||||
row< wait_add_complete_st, endc_activated_st, sgnb_add_complete_ev >,
|
||||
row< wait_add_complete_st, endc_deactivated_st, rrc_reest_rx_ev, &fsm::handle_rrc_reest >
|
||||
row< wait_add_complete_st, endc_deactivated_st, rrc_reest_rx_ev, &fsm::handle_rrc_reest >,
|
||||
// +---------------------------+--------------------------+------------------------+------------------------------+-------------------------+
|
||||
row< endc_activated_st, wait_sgnb_rel_req_resp_st, sgnb_rel_req_ev, &fsm::handle_sgnb_rel_req >,
|
||||
row< wait_sgnb_rel_req_resp_st, endc_deactivated_st, sgnb_rel_req_ack_ev >
|
||||
|
||||
>;
|
||||
// clang-format on
|
||||
};
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
// Interface for EUTRA RRC
|
||||
int sgnb_addition_request(uint16_t rnti, const sgnb_addition_req_params_t& params);
|
||||
int sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response);
|
||||
int sgnb_release_request(uint16_t nr_rnti);
|
||||
|
||||
// Interfaces for NGAP
|
||||
int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key);
|
||||
|
|
|
@ -80,6 +80,14 @@ public:
|
|||
eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti);
|
||||
}
|
||||
|
||||
void sgnb_release_ack(uint16_t eutra_rnti) override
|
||||
{
|
||||
if (eutra_stack == nullptr) {
|
||||
return;
|
||||
}
|
||||
eutra_stack->sgnb_release_ack(eutra_rnti);
|
||||
}
|
||||
|
||||
void set_activity_user(uint16_t eutra_rnti) override
|
||||
{
|
||||
if (eutra_stack == nullptr) {
|
||||
|
@ -88,6 +96,14 @@ public:
|
|||
eutra_stack->set_activity_user(eutra_rnti);
|
||||
}
|
||||
|
||||
int sgnb_release_request(uint16_t nr_rnti) override
|
||||
{
|
||||
if (nr_stack == nullptr) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
return nr_stack->sgnb_release_request(nr_rnti);
|
||||
}
|
||||
|
||||
// pdcp_interface_gtpu
|
||||
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override
|
||||
{
|
||||
|
|
|
@ -570,22 +570,48 @@ void rrc::set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_st
|
|||
void rrc::sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params)
|
||||
{
|
||||
logger.info("Received SgNB addition acknowledgement for rnti=%d", eutra_rnti);
|
||||
users.at(eutra_rnti)->endc_handler->trigger(ue::rrc_endc::sgnb_add_req_ack_ev{params});
|
||||
auto ue_it = users.find(eutra_rnti);
|
||||
if (ue_it == users.end()) {
|
||||
logger.warning("rnti=0x%x does not exist", eutra_rnti);
|
||||
return;
|
||||
}
|
||||
ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_add_req_ack_ev{params});
|
||||
|
||||
// trigger RRC Reconfiguration to send NR config to UE
|
||||
users.at(eutra_rnti)->send_connection_reconf();
|
||||
ue_it->second->send_connection_reconf();
|
||||
}
|
||||
|
||||
void rrc::sgnb_addition_reject(uint16_t eutra_rnti)
|
||||
{
|
||||
logger.error("Received SgNB addition reject for rnti=%d", eutra_rnti);
|
||||
users.at(eutra_rnti)->endc_handler->trigger(ue::rrc_endc::sgnb_add_req_reject_ev{});
|
||||
auto ue_it = users.find(eutra_rnti);
|
||||
if (ue_it == users.end()) {
|
||||
logger.warning("rnti=0x%x does not exist", eutra_rnti);
|
||||
return;
|
||||
}
|
||||
ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_add_req_reject_ev{});
|
||||
}
|
||||
|
||||
void rrc::sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti)
|
||||
{
|
||||
logger.info("User rnti=0x%x successfully enabled EN-DC", eutra_rnti);
|
||||
users.at(eutra_rnti)->endc_handler->trigger(ue::rrc_endc::sgnb_add_complete_ev{nr_rnti});
|
||||
auto ue_it = users.find(eutra_rnti);
|
||||
if (ue_it == users.end()) {
|
||||
logger.warning("rnti=0x%x does not exist", eutra_rnti);
|
||||
return;
|
||||
}
|
||||
ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_add_complete_ev{nr_rnti});
|
||||
}
|
||||
|
||||
void rrc::sgnb_release_ack(uint16_t eutra_rnti)
|
||||
{
|
||||
logger.info("Received SgNB release acknowledgement for rnti=%d", eutra_rnti);
|
||||
auto ue_it = users.find(eutra_rnti);
|
||||
if (ue_it == users.end()) {
|
||||
logger.warning("rnti=0x%x does not exist", eutra_rnti);
|
||||
return;
|
||||
}
|
||||
ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_rel_req_ack_ev{});
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -42,6 +42,11 @@ rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue, const rrc_endc_cfg_t& endc_cfg_)
|
|||
}
|
||||
}
|
||||
|
||||
rrc::ue::rrc_endc::~rrc_endc()
|
||||
{
|
||||
start_sgnb_release();
|
||||
}
|
||||
|
||||
//! Method to add NR fields to a RRC Connection Reconfiguration Message
|
||||
bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg)
|
||||
{
|
||||
|
@ -285,6 +290,12 @@ void rrc::ue::rrc_endc::start_sgnb_addition()
|
|||
trigger(sgnb_add_req);
|
||||
}
|
||||
|
||||
void rrc::ue::rrc_endc::start_sgnb_release()
|
||||
{
|
||||
sgnb_rel_req_ev sgnb_rel_req{nr_rnti};
|
||||
trigger(sgnb_rel_req);
|
||||
}
|
||||
|
||||
rrc::ue::rrc_endc::prepare_recfg_st::prepare_recfg_st(rrc_endc* parent_) : logger(parent_->logger) {}
|
||||
|
||||
void rrc::ue::rrc_endc::prepare_recfg_st::enter(rrc_endc* f, const sgnb_add_req_ack_ev& ev)
|
||||
|
@ -313,6 +324,15 @@ void rrc::ue::rrc_endc::handle_sgnb_add_req_ack(wait_sgnb_add_req_resp_st& s, co
|
|||
|
||||
// change GTPU tunnel RNTI to match NR RNTI
|
||||
rrc_enb->gtpu->mod_bearer_rnti(rrc_ue->rnti, ev.params.nr_rnti);
|
||||
|
||||
// store RNTI for later
|
||||
nr_rnti = ev.params.nr_rnti;
|
||||
}
|
||||
|
||||
void rrc::ue::rrc_endc::handle_sgnb_rel_req(endc_activated_st& s, const sgnb_rel_req_ev& ev)
|
||||
{
|
||||
logger.info("Triggering SgNB release");
|
||||
rrc_enb->rrc_nr->sgnb_release_request(nr_rnti);
|
||||
}
|
||||
|
||||
bool rrc::ue::rrc_endc::is_endc_supported()
|
||||
|
|
|
@ -511,6 +511,16 @@ int rrc_nr::sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstri
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int rrc_nr::sgnb_release_request(uint16_t nr_rnti)
|
||||
{
|
||||
task_sched.defer_task([this, nr_rnti]() {
|
||||
// remove user
|
||||
rem_user(nr_rnti);
|
||||
rrc_eutra->sgnb_release_ack(nr_rnti);
|
||||
});
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
UE class
|
||||
|
||||
|
|
Loading…
Reference in New Issue