From f9589c9c5dd4f21493e3ae37944199db7bef2b68 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 20 Jul 2021 23:30:08 +0200 Subject: [PATCH] enb,rrc,endc: refactor UE capability enquiry and check this patch first makes sure that ENDC is only configured if the UE support it. Second the patch also requests the EUTRA-NR and NR capabilities if the UE indicated ENDC support in its EUTRA caps. --- srsenb/hdr/stack/rrc/rrc_endc.h | 3 ++- srsenb/hdr/stack/rrc/rrc_metrics.h | 1 + srsenb/hdr/stack/rrc/rrc_ue.h | 5 ++-- srsenb/src/stack/rrc/rrc_endc.cc | 13 +++++++++- srsenb/src/stack/rrc/rrc_ue.cc | 39 +++++++++++++++++++++--------- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc_endc.h b/srsenb/hdr/stack/rrc/rrc_endc.h index 422371575..c33c9752c 100644 --- a/srsenb/hdr/stack/rrc/rrc_endc.h +++ b/srsenb/hdr/stack/rrc/rrc_endc.h @@ -43,12 +43,13 @@ public: rrc_endc(srsenb::rrc::ue* outer_ue); bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg); - void handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps); + 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 handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); void handle_sgnb_addition_reject(); void handle_sgnb_addition_complete(); + bool is_endc_supported(); private: // Send SgNB addition request to gNB diff --git a/srsenb/hdr/stack/rrc/rrc_metrics.h b/srsenb/hdr/stack/rrc/rrc_metrics.h index 32031e962..9361ac63f 100644 --- a/srsenb/hdr/stack/rrc/rrc_metrics.h +++ b/srsenb/hdr/stack/rrc/rrc_metrics.h @@ -24,6 +24,7 @@ typedef enum { RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE, RRC_STATE_WAIT_FOR_SECURITY_MODE_COMPLETE, RRC_STATE_WAIT_FOR_UE_CAP_INFO, + RRC_STATE_WAIT_FOR_UE_CAP_INFO_ENDC, /* only entered for UEs with NSA support */ RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE, RRC_STATE_REESTABLISHMENT_COMPLETE, RRC_STATE_REGISTERED, diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 554d7c0a5..2a9d19b8d 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -16,6 +16,7 @@ #include "mac_controller.h" #include "rrc.h" #include "srsran/adt/pool/batch_mem_pool.h" +#include "srsran/asn1/rrc/uecap.h" #include "srsran/interfaces/enb_phy_interfaces.h" #include "srsran/interfaces/pdcp_interface_types.h" @@ -77,7 +78,7 @@ public: bool phy_cfg_updated = true, srsran::const_byte_span nas_pdu = {}); void send_security_mode_command(); - void send_ue_cap_enquiry(); + void send_ue_cap_enquiry(const std::vector& rats); void send_ue_info_req(); void parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); @@ -104,7 +105,7 @@ public: void handle_rrc_reconf_complete(asn1::rrc::rrc_conn_recfg_complete_s* msg, srsran::unique_byte_buffer_t pdu); void handle_security_mode_complete(asn1::rrc::security_mode_complete_s* msg); void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg); - bool handle_ue_cap_info(asn1::rrc::ue_cap_info_s* msg); + int handle_ue_cap_info(asn1::rrc::ue_cap_info_s* msg); void handle_ue_init_ctxt_setup_req(const asn1::s1ap::init_context_setup_request_s& msg); bool handle_ue_ctxt_mod_req(const asn1::s1ap::ue_context_mod_request_s& msg); void handle_ue_info_resp(const asn1::rrc::ue_info_resp_r9_s& msg, srsran::unique_byte_buffer_t pdu); diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index 71245c05e..6b80b1838 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -160,8 +160,14 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn } //! Called when UE capabilities are received -void rrc::ue::rrc_endc::handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps) +void rrc::ue::rrc_endc::handle_eutra_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps) { + // skip any further checks if eNB runs without NR cells + if (rrc_enb->cfg.cell_list_nr.empty()) { + Debug("Skipping UE capabilities. No NR cell configured."); + return; + } + // Only enabled ENDC support if UE caps have been exchanged and UE signals support if (eutra_caps.non_crit_ext_present) { if (eutra_caps.non_crit_ext.non_crit_ext_present) { @@ -272,4 +278,9 @@ void rrc::ue::rrc_endc::handle_sgnb_addition_complete() logger.info("Received SgNB addition complete for rnti=%d", rrc_ue->rnti); } +bool rrc::ue::rrc_endc::is_endc_supported() +{ + return endc_supported; +} + } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index f53b528ee..38821f2d1 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -359,15 +359,23 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) break; case ul_dcch_msg_type_c::c1_c_::types::security_mode_complete: handle_security_mode_complete(&ul_dcch_msg.msg.c1().security_mode_complete()); - send_ue_cap_enquiry(); + send_ue_cap_enquiry({asn1::rrc::rat_type_opts::options::eutra}); state = RRC_STATE_WAIT_FOR_UE_CAP_INFO; break; case ul_dcch_msg_type_c::c1_c_::types::security_mode_fail: handle_security_mode_failure(&ul_dcch_msg.msg.c1().security_mode_fail()); break; case ul_dcch_msg_type_c::c1_c_::types::ue_cap_info: - if (handle_ue_cap_info(&ul_dcch_msg.msg.c1().ue_cap_info())) { - send_connection_reconf(std::move(pdu)); + if (handle_ue_cap_info(&ul_dcch_msg.msg.c1().ue_cap_info()) == SRSRAN_SUCCESS) { + if (not parent->cfg.cell_list_nr.empty() && endc_handler->is_endc_supported() && + state == RRC_STATE_WAIT_FOR_UE_CAP_INFO) { + // request EUTRA-NR and NR capabilities as well + send_ue_cap_enquiry({asn1::rrc::rat_type_opts::options::eutra_nr, asn1::rrc::rat_type_opts::options::nr}); + state = RRC_STATE_WAIT_FOR_UE_CAP_INFO_ENDC; // avoid endless loop + } else { + // send RRC reconfiguration to complete procedure + send_connection_reconf(std::move(pdu)); + } } else { send_connection_reject(procedure_result_code::none); state = RRC_STATE_IDLE; @@ -911,7 +919,7 @@ void rrc::ue::handle_security_mode_failure(security_mode_fail_s* msg) /* * UE capabilities info */ -void rrc::ue::send_ue_cap_enquiry() +void rrc::ue::send_ue_cap_enquiry(const std::vector& rats) { dl_dcch_msg_s dl_dcch_msg; dl_dcch_msg.msg.set_c1().set_ue_cap_enquiry().crit_exts.set_c1().set_ue_cap_enquiry_r8(); @@ -919,13 +927,20 @@ void rrc::ue::send_ue_cap_enquiry() ue_cap_enquiry_s* enq = &dl_dcch_msg.msg.c1().ue_cap_enquiry(); enq->rrc_transaction_id = (uint8_t)((transaction_id++) % 4); - enq->crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request.resize(1); - enq->crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request[0].value = rat_type_e::eutra; + enq->crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request.resize(rats.size()); + for (uint32_t i = 0; i < rats.size(); ++i) { + enq->crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request[i].value = rats.at(i); + } send_dl_dcch(&dl_dcch_msg); } -bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) +/** + * @brief Handle the reception of UE capability information message + * + * @return int SRSRAN_SUCCESS if unpacking was ok. SRSRAN_ERROR otherwise + */ +int rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) { parent->logger.info("UECapabilityInformation transaction ID: %d", msg->rrc_transaction_id); ue_cap_info_r8_ies_s* msg_r8 = &msg->crit_exts.c1().ue_cap_info_r8(); @@ -940,7 +955,7 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) msg_r8->ue_cap_rat_container_list[i].ue_cap_rat_container.size()); if (eutra_capabilities.unpack(bref) != asn1::SRSASN_SUCCESS) { parent->logger.error("Failed to unpack EUTRA capabilities message"); - return false; + return SRSRAN_ERROR; } if (parent->logger.debug.enabled()) { asn1::json_writer js{}; @@ -953,7 +968,7 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) parent->logger.info("UE rnti: 0x%x category: %d", rnti, eutra_capabilities.ue_category); if (endc_handler) { - endc_handler->handle_ue_capabilities(eutra_capabilities); + endc_handler->handle_eutra_capabilities(eutra_capabilities); } } @@ -961,7 +976,7 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); if (pdu == nullptr) { parent->logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); - return false; + return SRSRAN_ERROR; } asn1::bit_ref bref2{pdu->msg, pdu->get_tailroom()}; msg->pack(bref2); @@ -972,13 +987,13 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) bref2 = asn1::bit_ref{pdu->msg, pdu->get_tailroom()}; if (ue_rat_caps.pack(bref2) != asn1::SRSASN_SUCCESS) { parent->logger.error("Couldn't pack ue rat caps"); - return false; + return SRSRAN_ERROR; } pdu->N_bytes = bref2.distance_bytes(); parent->s1ap->send_ue_cap_info_indication(rnti, std::move(pdu)); } - return true; + return SRSRAN_SUCCESS; } /*