From fd7c5e375c0fb2905615f8e3476c7416ddfafc62 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 9 Nov 2021 18:26:37 +0000 Subject: [PATCH] nr,gnb,rrc: implement NR RRCSetup in RRC and wrote unit test --- .../hdr/stack/common/test/dummy_nr_classes.h | 23 ++ srsgnb/hdr/stack/rrc/rrc_nr.h | 58 ++-- srsgnb/src/stack/rrc/cell_asn1_config.cc | 9 +- srsgnb/src/stack/rrc/rrc_nr.cc | 252 ++++++++++++------ srsgnb/src/stack/rrc/test/CMakeLists.txt | 4 +- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 40 ++- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 65 +++++ .../src/stack/rrc/test/rrc_nr_test_helpers.h | 60 +++++ test/phy/dummy_gnb_stack.h | 2 +- 9 files changed, 391 insertions(+), 122 deletions(-) rename srsenb/test/common/dummy_classes_nr.h => srsgnb/hdr/stack/common/test/dummy_nr_classes.h (65%) create mode 100644 srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc create mode 100644 srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h similarity index 65% rename from srsenb/test/common/dummy_classes_nr.h rename to srsgnb/hdr/stack/common/test/dummy_nr_classes.h index 76ba164c6..90e4f9906 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h @@ -15,9 +15,32 @@ #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h" +#include "srsran/interfaces/gnb_ngap_interfaces.h" namespace srsenb { +class ngap_dummy : public ngap_interface_rrc_nr +{ + void initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu) + {} + void initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu, + uint32_t m_tmsi) + {} + + void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t 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() { return true; } + void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) {} +}; + class rrc_nr_dummy : public rrc_interface_mac_nr { public: diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index 267764daa..9c9efe00d 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -103,18 +103,11 @@ public: // logging typedef enum { Rx = 0, Tx } direction_t; template - void log_rrc_message(const std::string& source, - const direction_t dir, - const asn1::dyn_octstring& oct, - const T& msg, - const std::string& msg_type); - - template - void log_rrc_message(const std::string& source, - const direction_t dir, - const srsran::byte_buffer_t& pdu, - const T& msg, - const std::string& msg_type); + void log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const T& msg, + const char* msg_type); class ue { public: @@ -128,12 +121,17 @@ public: /// @param [in] start_msg3_timer: indicates whether the UE is created as part of a RACH process ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer = true); - void send_connection_setup(); - void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg); + void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_dcch_msg); + + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void send_rrc_setup(); + void send_rrc_reject(uint8_t reject_wait_time_secs); int handle_sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params); void crnti_ce_received(); + void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); + // getters bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } @@ -156,8 +154,6 @@ public: private: rrc_nr* parent = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; - /// for basic DL/UL activity timeout - srsran::unique_timer activity_timer; int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); @@ -201,12 +197,19 @@ public: int add_drb(); // logging helpers - template - void log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type); + template + void log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type); + template + void log_rrc_container(const direction_t dir, srsran::const_byte_span pdu, const M& msg, const char* msg_type); // state - rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; - uint8_t transaction_id = 0; + rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; + uint8_t transaction_id = 0; + srsran::unique_timer activity_timer; /// for basic DL/UL activity timeout // RRC configs for UEs asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; @@ -251,18 +254,25 @@ private: srsran::unique_byte_buffer_t mib_buffer = nullptr; std::vector sib_buffer; }; - std::unique_ptr cell_ctxt; - std::map > users; - bool running = false; + std::unique_ptr cell_ctxt; + rnti_map_t > users; + bool running = false; /// Private Methods - void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu); + void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu); + void parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu); + void handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg); /// This gets called by rrc_nr::sgnb_addition_request and WILL NOT TRIGGER the RX MSG3 activity timer int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer); // Helper to create PDU from RRC message template srsran::unique_byte_buffer_t pack_into_pdu(const T& msg); + void log_rx_pdu_fail(uint16_t rnti, + uint32_t lcid, + srsran::const_byte_span pdu, + const char* cause_str, + bool log_hex = true); }; } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index c6535f280..379ef7f57 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -299,14 +299,7 @@ int fill_pdcch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pdcch_cfg_ (search_space_cfg.type == srsran_search_space_type_common_3)) { search_spaces[0].search_space_type.set_common(); - if ((search_space_cfg.formats[0] == srsran_dci_format_nr_0_0) and - (search_space_cfg.formats[1] == srsran_dci_format_nr_1_0)) { - search_spaces[ss_mod_list_idx].search_space_type.common().dci_format0_minus0_and_format1_minus0_present = - true; - } else { - get_logger(cfg).error("Config Error: Unsupported dci nr formats."); - return SRSRAN_ERROR; - } + search_spaces[ss_mod_list_idx].search_space_type.common().dci_format0_minus0_and_format1_minus0_present = true; } else { get_logger(cfg).error("Config Error: Unsupported search space type."); return SRSRAN_ERROR; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 6f3758f29..84258ec08 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -18,6 +18,7 @@ #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/string_helpers.h" using namespace asn1::rrc_nr; @@ -123,48 +124,33 @@ void rrc_nr::stop() } template -void rrc_nr::log_rrc_message(const std::string& source, - const direction_t dir, - const asn1::dyn_octstring& oct, - const T& msg, - const std::string& msg_type) +void rrc_nr::log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const T& msg, + const char* msg_type) { if (logger.debug.enabled()) { asn1::json_writer json_writer; msg.to_json(json_writer); - logger.debug(oct.data(), - oct.size(), - "%s - %s %s (%d B)", - source.c_str(), - dir == Tx ? "Tx" : "Rx", - msg_type.c_str(), - oct.size()); - logger.debug("Content:\n%s", json_writer.to_string().c_str()); + logger.debug(pdu.data(), pdu.size(), "%s - %s %s (%d B)", source, (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); + logger.debug("Content:%s", json_writer.to_string().c_str()); } else if (logger.info.enabled()) { - logger.info("%s - %s %s (%d B)", source.c_str(), dir == Tx ? "Tx" : "Rx", msg_type.c_str(), oct.size()); + logger.info(pdu.data(), pdu.size(), "%s - %s %s (%d B)", source, (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); } } -template -void rrc_nr::log_rrc_message(const std::string& source, - const direction_t dir, - const srsran::byte_buffer_t& pdu, - const T& msg, - const std::string& msg_type) +void rrc_nr::log_rx_pdu_fail(uint16_t rnti, + uint32_t lcid, + srsran::const_byte_span pdu, + const char* cause_str, + bool log_hex) { - if (logger.debug.enabled()) { - asn1::json_writer json_writer; - msg.to_json(json_writer); - logger.debug(pdu.msg, - pdu.N_bytes, - "%s - %s %s (%d B)", - source.c_str(), - (dir == Rx) ? "Rx" : "Tx", - msg_type.c_str(), - pdu.N_bytes); - logger.debug("Content:%s", json_writer.to_string().c_str()); - } else if (logger.info.enabled()) { - logger.info("%s - %s %s (%d B)", source.c_str(), (dir == Rx) ? "Rx" : "Tx", msg_type.c_str(), pdu.N_bytes); + if (log_hex) { + logger.error( + pdu.data(), pdu.size(), "Rx %s PDU, rnti=0x%x - Discarding. Cause: %s", get_rb_name(lcid), rnti, cause_str); + } else { + logger.error("Rx %s PDU, rnti=0x%x - Discarding. Cause: %s", get_rb_name(lcid), rnti, cause_str); } } @@ -174,9 +160,9 @@ void rrc_nr::log_rrc_message(const std::string& source, */ int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer) { - if (users.count(rnti) == 0) { + if (users.contains(rnti) == 0) { // If in the ue ctor, "start_msg3_timer" is set to true, this will start the MSG3 RX TIMEOUT at ue creation - users.insert(std::make_pair(rnti, std::unique_ptr(new ue(this, rnti, uecfg, start_msg3_timer)))); + users.insert(rnti, std::unique_ptr(new ue(this, rnti, uecfg, start_msg3_timer))); rlc->add_user(rnti); pdcp->add_user(rnti); logger.info("Added new user rnti=0x%x", rnti); @@ -386,7 +372,7 @@ int32_t rrc_nr::generate_sibs() } else { fmt::format_to(strbuf, "SI message={} payload", msg_index + 1); } - log_rrc_message(fmt::to_string(strbuf), Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], ""); + log_rrc_message("BCCH", Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], srsran::to_c_str(strbuf)); } return SRSRAN_SUCCESS; @@ -428,36 +414,78 @@ void rrc_nr::get_metrics(srsenb::rrc_metrics_t& m) } } -void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) +void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu) { - if (pdu) { - logger.info(pdu->msg, pdu->N_bytes, "Rx %s PDU", get_rb_name(lcid)); + logger.info(pdu.data(), pdu.size(), "Rx %s PDU", get_rb_name(lcid)); + + switch (static_cast(lcid)) { + case srsran::nr_srb::srb0: + parse_ul_ccch(rnti, pdu); + break; + case srsran::nr_srb::srb1: + case srsran::nr_srb::srb2: + // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); + break; + default: + std::string errcause = fmt::format("Invalid LCID=%d", lcid); + log_rx_pdu_fail(rnti, lcid, pdu, errcause.c_str()); + break; } +} - if (users.count(rnti) == 1) { - switch (static_cast(lcid)) { - case srsran::nr_srb::srb0: - // parse_ul_ccch(rnti, std::move(pdu)); - break; - case srsran::nr_srb::srb1: - case srsran::nr_srb::srb2: - // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); - break; - default: - logger.error("Rx PDU with invalid bearer id: %d", lcid); - break; +void rrc_nr::parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu) +{ + // Parse UL-CCCH + ul_ccch_msg_s ul_ccch_msg; + { + asn1::cbit_ref bref(pdu.data(), pdu.size()); + if (ul_ccch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or + ul_ccch_msg.msg.type().value != ul_ccch_msg_type_c::types_opts::c1) { + log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Failed to unpack UL-CCCH message", true); + return; } - } else { - logger.warning("Discarding PDU for removed rnti=0x%x", rnti); + } + + // Log Rx message + fmt::memory_buffer fmtbuf, fmtbuf2; + fmt::format_to(fmtbuf, "rnti=0x{:x}, SRB0", rnti); + fmt::format_to(fmtbuf2, "UL-CCCH.{}", ul_ccch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::to_c_str(fmtbuf), Rx, pdu, ul_ccch_msg, srsran::to_c_str(fmtbuf2)); + + // Handle message + switch (ul_ccch_msg.msg.c1().type().value) { + case ul_ccch_msg_type_c::c1_c_::types_opts::rrc_setup_request: + handle_rrc_setup_request(rnti, ul_ccch_msg.msg.c1().rrc_setup_request()); + break; + default: + log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Unsupported UL-CCCH message type"); + // TODO Remove user } } +void rrc_nr::handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg) +{ + auto ue_it = users.find(rnti); + + // TODO: Defer creation of ue to this point + if (ue_it == users.end()) { + logger.error("%s received for inexistent rnti=0x%x", "UL-CCCH", rnti); + return; + } + ue& u = *ue_it->second; + u.handle_rrc_setup_request(msg); +} + /******************************************************************************* PDCP interface *******************************************************************************/ void rrc_nr::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) { - handle_pdu(rnti, lcid, std::move(pdu)); + if (pdu == nullptr or pdu->N_bytes == 0) { + logger.error("Rx %s PDU, rnti=0x%x - Discarding. Cause: PDU is empty", srsenb::get_rb_name(lcid), rnti); + return; + } + handle_pdu(rnti, lcid, *pdu); } void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {} @@ -652,39 +680,18 @@ std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type) return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); } -void rrc_nr::ue::send_connection_setup() -{ - dl_ccch_msg_s dl_ccch_msg; - dl_ccch_msg.msg.set_c1().set_rrc_setup().rrc_transaction_id = ((transaction_id++) % 4u); - rrc_setup_ies_s& setup = dl_ccch_msg.msg.c1().rrc_setup().crit_exts.set_rrc_setup(); - radio_bearer_cfg_s& rr_cfg = setup.radio_bearer_cfg; - - // Add DRB1 to cfg - rr_cfg.drb_to_add_mod_list_present = true; - rr_cfg.drb_to_add_mod_list.resize(1); - auto& drb_item = rr_cfg.drb_to_add_mod_list[0]; - drb_item.drb_id = 1; - drb_item.pdcp_cfg_present = true; - drb_item.pdcp_cfg.ciphering_disabled_present = true; - // drb_item.cn_assoc_present = true; - // drb_item.cn_assoc.set_eps_bearer_id() = ; - drb_item.recover_pdcp_present = false; - - // TODO: send config to RLC/PDCP - - send_dl_ccch(&dl_ccch_msg); -} - -void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) +void rrc_nr::ue::send_dl_ccch(const dl_ccch_msg_s& dl_ccch_msg) { // Allocate a new PDU buffer, pack the message and send to PDCP - srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(*dl_ccch_msg); + srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(dl_ccch_msg); if (pdu == nullptr) { parent->logger.error("Failed to send DL-CCCH"); return; } - log_rrc_message(Tx, *pdu.get(), *dl_ccch_msg, "DL-CCCH"); - parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "DL-CCCH.{}", dl_ccch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::nr_srb::srb0, Tx, *pdu.get(), dl_ccch_msg, srsran::to_c_str(fmtbuf)); + parent->rlc->write_sdu(rnti, srsran::srb_to_lcid(srsran::nr_srb::srb0), std::move(pdu)); } template @@ -1234,7 +1241,7 @@ int rrc_nr::ue::pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_second } packed_secondary_cell_config.resize(bref_pack.distance_bytes()); - log_rrc_message(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); + log_rrc_container(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); return SRSRAN_SUCCESS; } @@ -1291,7 +1298,7 @@ int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_beare // resize to packed length packed_nr_bearer_config.resize(bref_pack.distance_bytes()); - log_rrc_message(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); + log_rrc_container(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); return SRSRAN_SUCCESS; } @@ -1446,6 +1453,62 @@ int rrc_nr::ue::add_drb() return SRSRAN_SUCCESS; } +void rrc_nr::ue::handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg) +{ + if (not parent->ngap->is_amf_connected()) { + parent->logger.error("MME isn't connected. Sending Connection Reject"); + const uint8_t max_wait_time_secs = 16; + send_rrc_reject(max_wait_time_secs); // See TS 38.331, RejectWaitTime + return; + } + + // TODO: Allocate PUCCH resources and reject if not available + + switch (msg.rrc_setup_request.ue_id.type().value) { + case asn1::rrc_nr::init_ue_id_c::types_opts::ng_minus5_g_s_tmsi_part1: + // TODO: communicate with NGAP + break; + case asn1::rrc_nr::init_ue_id_c::types_opts::random_value: + // TODO: communicate with NGAP + break; + default: + parent->logger.error("Unsupported RRCSetupRequest"); + } + + send_rrc_setup(); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); +} + +/// TS 38.331, RRCReject message +void rrc_nr::ue::send_rrc_reject(uint8_t reject_wait_time_secs) +{ + dl_ccch_msg_s msg; + rrc_reject_ies_s& reject = msg.msg.set_c1().set_rrc_reject().crit_exts.set_rrc_reject(); + if (reject_wait_time_secs > 0) { + reject.wait_time_present = true; + reject.wait_time = reject_wait_time_secs; + } + send_dl_ccch(msg); +} + +/// TS 38.331, RRCSetup +void rrc_nr::ue::send_rrc_setup() +{ + dl_ccch_msg_s msg; + rrc_setup_s& setup = msg.msg.set_c1().set_rrc_setup(); + setup.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); + rrc_setup_ies_s& setup_ies = setup.crit_exts.set_rrc_setup(); + + // Fill RRC Setup + // Note: See 5.3.5.6.3 - SRB addition/modification + setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present = true; + setup_ies.radio_bearer_cfg.srb_to_add_mod_list.resize(1); + srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; + srb1.srb_id = 1; + + send_dl_ccch(msg); +} + /** * @brief Deactivate all Bearers (MAC logical channel) for this specific RNTI * @@ -1462,12 +1525,27 @@ void rrc_nr::ue::deactivate_bearers() parent->mac->ue_cfg(rnti, uecfg); } -template -void rrc_nr::ue::log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type) +template +void rrc_nr::ue::log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) +{ + fmt::memory_buffer strbuf; + fmt::format_to(strbuf, "rnti=0x{:x}, {}", rnti, srsran::get_srb_name(srb)); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); +} + +template +void rrc_nr::ue::log_rrc_container(const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) { fmt::memory_buffer strbuf; - fmt::format_to(strbuf, "rnti=0x{:x}", rnti); - parent->log_rrc_message(fmt::to_string(strbuf), Tx, pdu, msg, msg_type); + fmt::format_to(strbuf, "rnti=0x{:x}, container", rnti); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/CMakeLists.txt b/srsgnb/src/stack/rrc/test/CMakeLists.txt index 798e2556d..9716fdaac 100644 --- a/srsgnb/src/stack/rrc/test/CMakeLists.txt +++ b/srsgnb/src/stack/rrc/test/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_library(rrc_nr_test_helpers rrc_nr_test_helpers.cc) + add_executable(rrc_nr_test rrc_nr_test.cc) -target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers ${ATOMIC_LIBS}) +target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers rrc_nr_test_helpers) add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) \ No newline at end of file diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index dc56df1f2..3bcca174b 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -10,11 +10,13 @@ * */ +#include "rrc_nr_test_helpers.h" #include "srsenb/hdr/enb.h" #include "srsenb/test/common/dummy_classes_common.h" -#include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/rrc/test_helpers.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" #include "srsgnb/hdr/stack/rrc/rrc_nr.h" +#include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/common/test_common.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include @@ -125,12 +127,47 @@ int test_rrc_setup() return SRSRAN_SUCCESS; } +void test_rrc_sa_connection() +{ + srsran::task_scheduler task_sched; + + phy_nr_dummy phy_obj; + mac_nr_dummy mac_obj; + rlc_nr_rrc_tester rlc_obj; + pdcp_nr_rrc_tester pdcp_obj; + ngap_dummy ngap_obj; + + rrc_nr rrc_obj(&task_sched); + + // set cfg + all_args_t args{}; + phy_cfg_t phy_cfg{}; + rrc_nr_cfg_t rrc_cfg_nr = rrc_nr_cfg_t{}; + rrc_cfg_nr.cell_list.emplace_back(); + rrc_cfg_nr.cell_list[0].phy_cell.carrier.pci = 500; + rrc_cfg_nr.cell_list[0].dl_arfcn = 634240; + rrc_cfg_nr.cell_list[0].band = 78; + rrc_cfg_nr.is_standalone = true; + args.enb.n_prb = 50; + enb_conf_sections::set_derived_args_nr(&args, &rrc_cfg_nr, &phy_cfg); + + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, &ngap_obj, nullptr, nullptr) == + SRSRAN_SUCCESS); + + sched_nr_ue_cfg_t uecfg = get_default_ue_cfg(1); + TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); + + TESTASSERT_SUCCESS(test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, 0x4601)); +} + } // namespace srsenb int main(int argc, char** argv) { auto& logger = srslog::fetch_basic_logger("ASN1"); logger.set_level(srslog::basic_levels::info); + auto& rrc_logger = srslog::fetch_basic_logger("RRC-NR"); + rrc_logger.set_level(srslog::basic_levels::info); srslog::init(); @@ -142,6 +179,7 @@ int main(int argc, char** argv) TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); + srsenb::test_rrc_sa_connection(); return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc new file mode 100644 index 000000000..3fbdb3aa6 --- /dev/null +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -0,0 +1,65 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "rrc_nr_test_helpers.h" +#include "srsran/common/test_common.h" + +using namespace asn1::rrc_nr; + +namespace srsenb { + +int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti) +{ + srsran::unique_byte_buffer_t pdu; + + // Send RRCSetupRequest + ul_ccch_msg_s setup_msg; + rrc_setup_request_ies_s& setup = setup_msg.msg.set_c1().set_rrc_setup_request().rrc_setup_request; + setup.establishment_cause.value = establishment_cause_opts::mo_data; + setup.ue_id.set_random_value().from_number(0); + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(setup_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + + rrc_obj.write_pdu(rnti, 0, std::move(pdu)); + task_sched.tic(); + + TESTASSERT_EQ(rnti, rlc.last_sdu_rnti); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb0), rlc.last_sdu_lcid); + TESTASSERT(rlc.last_sdu->size() > 0); + dl_ccch_msg_s dl_ccch_msg; + { + asn1::cbit_ref bref{rlc.last_sdu->data(), rlc.last_sdu->size()}; + TESTASSERT_SUCCESS(dl_ccch_msg.unpack(bref)); + } + TESTASSERT_EQ(dl_ccch_msg_type_c::types_opts::c1, dl_ccch_msg.msg.type().value); + TESTASSERT_EQ(dl_ccch_msg_type_c::c1_c_::types_opts::rrc_setup, dl_ccch_msg.msg.c1().type().value); + TESTASSERT_EQ(asn1::rrc_nr::rrc_setup_s::crit_exts_c_::types_opts::rrc_setup, + dl_ccch_msg.msg.c1().rrc_setup().crit_exts.type().value); + + const rrc_setup_ies_s& setup_ies = dl_ccch_msg.msg.c1().rrc_setup().crit_exts.rrc_setup(); + TESTASSERT(setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present); + TESTASSERT_EQ(1, setup_ies.radio_bearer_cfg.srb_to_add_mod_list.size()); + + const srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), srb1.srb_id); + + return SRSRAN_SUCCESS; +} + +} // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h new file mode 100644 index 000000000..92539e11f --- /dev/null +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -0,0 +1,60 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RRC_NR_TEST_HELPERS_H +#define SRSRAN_RRC_NR_TEST_HELPERS_H + +#include "srsenb/test/common/dummy_classes_common.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr.h" + +namespace srsenb { + +class pdcp_nr_rrc_tester : public pdcp_dummy +{ +public: + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override + { + last_sdu_rnti = rnti; + last_sdu_lcid = lcid; + last_sdu = std::move(sdu); + } + + uint16_t last_sdu_rnti = SRSRAN_INVALID_RNTI; + uint32_t last_sdu_lcid = srsran::MAX_NR_NOF_BEARERS; + srsran::unique_byte_buffer_t last_sdu; +}; + +class rlc_nr_rrc_tester : public rlc_dummy +{ +public: + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) + { + last_sdu_rnti = rnti; + last_sdu_lcid = lcid; + last_sdu = std::move(sdu); + } + + uint16_t last_sdu_rnti; + uint32_t last_sdu_lcid; + srsran::unique_byte_buffer_t last_sdu; +}; + +/// Run TS 38.331, 5.3.3 "RRC connection establishment" to completion +int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti); + +} // namespace srsenb + +#endif // SRSRAN_RRC_NR_TEST_HELPERS_H diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 790547448..d363ea9cd 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,8 +15,8 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" -#include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/common/rlc_test_dummy.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" #include "srsgnb/hdr/stack/mac/mac_nr.h" #include "srsgnb/hdr/stack/mac/sched_nr.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h"