nr,gnb,rrc: implement NR RRCSetup in RRC and wrote unit test

master
Francisco 3 years ago committed by Francisco Paisana
parent 89ca761680
commit fd7c5e375c

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

@ -103,18 +103,11 @@ public:
// logging
typedef enum { Rx = 0, Tx } direction_t;
template <class T>
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 <class T>
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 <class T, class M>
void log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type);
template <class M>
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 <class M>
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<srsran::unique_byte_buffer_t> sib_buffer;
};
std::unique_ptr<cell_ctxt_t> cell_ctxt;
std::map<uint16_t, std::unique_ptr<ue> > users;
bool running = false;
std::unique_ptr<cell_ctxt_t> cell_ctxt;
rnti_map_t<std::unique_ptr<ue> > 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 <class T>
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

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

@ -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 <class T>
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 <class T>
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<ue>(new ue(this, rnti, uecfg, start_msg3_timer))));
users.insert(rnti, std::unique_ptr<ue>(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<srsran::nr_srb>(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<srsran::nr_srb>(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 <class T>
@ -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 <class T, class M>
void rrc_nr::ue::log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type)
template <class M>
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 <class M>
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

@ -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}/../..)

@ -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 <iostream>
@ -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;
}

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

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

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

Loading…
Cancel
Save