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.
master
Andre Puschmann 3 years ago
parent a7eb9b471b
commit f9589c9c5d

@ -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

@ -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,

@ -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<asn1::rrc::rat_type_opts::options>& 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);

@ -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

@ -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<asn1::rrc::rat_type_opts::options>& 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;
}
/*

Loading…
Cancel
Save