nr,gnb,rrc: generation of MIB/SIB1 inside rrc_nr class and test to verify the correct output

master
Francisco 3 years ago committed by Francisco Paisana
parent 5f3afffd05
commit 2d6ce768c7

@ -50,6 +50,7 @@ class sched_nr_interface
{
public:
static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS;
static const size_t MAX_SIBS = 2;
///// Configuration /////
@ -63,11 +64,17 @@ public:
uint32_t numerology_idx = 0;
};
struct cell_cfg_sib_t {
uint32_t len;
uint32_t period_rf;
};
struct cell_cfg_t {
srsran_carrier_nr_t carrier = {};
srsran_duplex_config_nr_t duplex = {};
srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {};
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common
srsran::bounded_vector<cell_cfg_sib_t, MAX_SIBS> sibs;
};
struct sched_args_t {

@ -47,16 +47,12 @@ struct rrc_cell_cfg_nr_t {
typedef std::vector<rrc_cell_cfg_nr_t> rrc_cell_list_nr_t;
struct rrc_nr_cfg_t {
asn1::rrc_nr::mib_s mib;
asn1::rrc_nr::sib1_s sib1;
asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_item_c_ sibs[ASN1_RRC_NR_MAX_SIB];
uint32_t nof_sibs;
rrc_nr_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg;
rrc_cell_list_nr_t cell_list;
asn1::rrc_nr::rach_cfg_common_s rach_cfg_common;
uint16_t prach_root_seq_idx_type;
bool is_standalone;
rrc_nr_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg;
rrc_cell_list_nr_t cell_list;
asn1::rrc_nr::rach_cfg_common_s rach_cfg_common;
uint16_t prach_root_seq_idx_type;
bool is_standalone;
std::string log_name = "RRC-NR";
std::string log_level;

@ -61,12 +61,11 @@ public:
void get_metrics(srsenb::rrc_metrics_t& m);
rrc_nr_cfg_t update_default_cfg(const rrc_nr_cfg_t& rrc_cfg);
void config_phy();
void config_mac();
int32_t generate_sibs();
int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) final;
int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final;
void config_phy();
void config_mac();
int32_t generate_sibs();
int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) final;
int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final;
/// User manegement
int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg);
@ -245,12 +244,16 @@ private:
asn1::rrc_nr::sp_cell_cfg_s base_sp_cell_cfg;
// vars
std::map<uint16_t, std::unique_ptr<ue> > users;
bool running = false;
std::vector<srsran::unique_byte_buffer_t> sib_buffer;
srsran::unique_byte_buffer_t mib_buffer = nullptr;
uint32_t nof_si_messages = 0;
struct cell_ctxt_t {
asn1::rrc_nr::mib_s mib;
asn1::rrc_nr::sib1_s sib1;
asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_l_ sibs;
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;
/// Private Methods
void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu);

@ -1181,11 +1181,13 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr
// NR cells available.
if (rrc_cfg_->cell_list.size() == 0) {
// SA mode. Update NGAP args
rrc_nr_cfg_->is_standalone = true;
args_->nr_stack.ngap.gnb_id = args_->enb.enb_id;
args_->nr_stack.ngap.cell_id = rrc_nr_cfg_->cell_list[0].phy_cell.cell_id;
args_->nr_stack.ngap.tac = rrc_nr_cfg_->cell_list[0].tac;
} else {
// NSA mode.
rrc_nr_cfg_->is_standalone = false;
// update EUTRA RRC params for ENDC
rrc_cfg_->endc_cfg.abs_frequency_ssb = rrc_nr_cfg_->cell_list.at(0).ssb_absolute_freq_point;
rrc_cfg_->endc_cfg.nr_band = rrc_nr_cfg_->cell_list.at(0).band;

@ -44,8 +44,9 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_,
gtpu = gtpu_;
rrc_eutra = rrc_eutra_;
// TODO: overwriting because we are not passing config right now
cfg = update_default_cfg(cfg_);
cfg = cfg_;
cell_ctxt.reset(new cell_ctxt_t{});
// derived
slot_dur_ms = 1;
@ -132,54 +133,6 @@ void rrc_nr::log_rrc_message(const std::string& source,
}
}
rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current)
{
// NOTE: This function is temporary.
rrc_nr_cfg_t cfg_default = current;
// Fill MIB
cfg_default.mib.sub_carrier_spacing_common.value = mib_s::sub_carrier_spacing_common_opts::scs15or60;
cfg_default.mib.ssb_subcarrier_offset = 0;
cfg_default.mib.intra_freq_resel.value = mib_s::intra_freq_resel_opts::allowed;
cfg_default.mib.cell_barred.value = mib_s::cell_barred_opts::not_barred;
cfg_default.mib.pdcch_cfg_sib1.search_space_zero = 0;
cfg_default.mib.pdcch_cfg_sib1.ctrl_res_set_zero = 0;
cfg_default.mib.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2;
cfg_default.mib.sys_frame_num.from_number(0);
// Fill SIB1
cfg_default.sib1.cell_access_related_info.plmn_id_list.resize(1);
cfg_default.sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.resize(1);
srsran::plmn_id_t plmn;
plmn.from_string("90170");
srsran::to_asn1(&cfg_default.sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0], plmn);
cfg_default.sib1.cell_access_related_info.plmn_id_list[0].cell_id.from_number(1);
cfg_default.sib1.cell_access_related_info.plmn_id_list[0].cell_reserved_for_oper.value =
plmn_id_info_s::cell_reserved_for_oper_opts::not_reserved;
cfg_default.sib1.si_sched_info_present = true;
cfg_default.sib1.si_sched_info.si_request_cfg.rach_occasions_si_present = true;
cfg_default.sib1.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.ra_resp_win.value =
rach_cfg_generic_s::ra_resp_win_opts::sl8;
cfg_default.sib1.si_sched_info.si_win_len.value = si_sched_info_s::si_win_len_opts::s20;
cfg_default.sib1.si_sched_info.sched_info_list.resize(1);
cfg_default.sib1.si_sched_info.sched_info_list[0].si_broadcast_status.value =
sched_info_s::si_broadcast_status_opts::broadcasting;
cfg_default.sib1.si_sched_info.sched_info_list[0].si_periodicity.value = sched_info_s::si_periodicity_opts::rf16;
cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info.resize(1);
// scheduling of SI messages
cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].type.value = sib_type_info_s::type_opts::sib_type2;
cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag_present = true;
cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag = 0;
// Fill SIB2+
cfg_default.nof_sibs = 1;
sib2_s& sib2 = cfg_default.sibs[0].set_sib2();
sib2.cell_resel_info_common.q_hyst.value = sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5;
// TODO: Fill SIB2 values
return cfg_default;
}
/* @brief PRIVATE function, gets called by sgnb_addition_request
*
* This function WILL NOT TRIGGER the RX MSG3 activity timer
@ -307,6 +260,17 @@ void rrc_nr::config_mac()
ret2 = srsran::make_duplex_cfg_from_serv_cell(base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, &cell.duplex);
srsran_assert(ret2, "Invalid NR cell configuration.");
// Set SIB1 and SI messages
cell.sibs.resize(cell_ctxt->sib_buffer.size());
for (uint32_t i = 0; i < cell_ctxt->sib_buffer.size(); i++) {
cell.sibs[i].len = cell_ctxt->sib_buffer[i]->N_bytes;
if (i == 0) {
cell.sibs[i].period_rf = 16; // SIB1 is always 16 rf
} else {
cell.sibs[i].period_rf = cell_ctxt->sib1.si_sched_info.sched_info_list[i - 1].si_periodicity.to_number();
}
}
// Configure MAC/scheduler
mac->cell_cfg(sched_cells_cfg);
}
@ -314,9 +278,9 @@ void rrc_nr::config_mac()
int32_t rrc_nr::generate_sibs()
{
// MIB packing
fill_mib_from_enb_cfg(cfg, cell_ctxt->mib);
bcch_bch_msg_s mib_msg;
mib_s& mib = mib_msg.msg.set_mib();
mib = cfg.mib;
mib_msg.msg.set_mib() = cell_ctxt->mib;
{
srsran::unique_byte_buffer_t mib_buf = srsran::make_byte_buffer();
if (mib_buf == nullptr) {
@ -330,19 +294,27 @@ int32_t rrc_nr::generate_sibs()
}
mib_buf->N_bytes = bref.distance_bytes();
logger.debug(mib_buf->msg, mib_buf->N_bytes, "MIB payload (%d B)", mib_buf->N_bytes);
mib_buffer = std::move(mib_buf);
cell_ctxt->mib_buffer = std::move(mib_buf);
}
si_sched_info_s::sched_info_list_l_& sched_info = cfg.sib1.si_sched_info.sched_info_list;
uint32_t nof_messages = cfg.sib1.si_sched_info_present ? cfg.sib1.si_sched_info.sched_info_list.size() : 0;
// SIB1 packing
fill_sib1_from_enb_cfg(cfg, cell_ctxt->sib1);
si_sched_info_s::sched_info_list_l_& sched_info = cell_ctxt->sib1.si_sched_info.sched_info_list;
// SI messages packing
cell_ctxt->sibs.resize(1);
sib2_s& sib2 = cell_ctxt->sibs[0].set_sib2();
sib2.cell_resel_info_common.q_hyst.value = asn1::rrc_nr::sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5;
// msg is array of SI messages, each SI message msg[i] may contain multiple SIBs
// all SIBs in a SI message msg[i] share the same periodicity
sib_buffer.reserve(nof_messages + 1);
const uint32_t nof_messages =
cell_ctxt->sib1.si_sched_info_present ? cell_ctxt->sib1.si_sched_info.sched_info_list.size() : 0;
cell_ctxt->sib_buffer.reserve(nof_messages + 1);
asn1::dyn_array<bcch_dl_sch_msg_s> msg(nof_messages + 1);
// Copy SIB1 to first SI message
msg[0].msg.set_c1().set_sib_type1() = cfg.sib1;
msg[0].msg.set_c1().set_sib_type1() = cell_ctxt->sib1;
// Copy rest of SIBs
for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages; sched_info_elem++) {
@ -353,27 +325,25 @@ int32_t rrc_nr::generate_sibs()
for (uint32_t mapping = 0; mapping < sched_info[sched_info_elem].sib_map_info.size(); ++mapping) {
uint32_t sibidx = sched_info[sched_info_elem].sib_map_info[mapping].type; // SIB2 == 0
sib_list.push_back(cfg.sibs[sibidx]);
sib_list.push_back(cell_ctxt->sibs[sibidx]);
}
}
// Pack payload for all messages
for (uint32_t msg_index = 0; msg_index < nof_messages + 1; msg_index++) {
srsran::unique_byte_buffer_t sib = pack_into_pdu(msg[msg_index]);
if (sib == nullptr) {
srsran::unique_byte_buffer_t sib_pdu = pack_into_pdu(msg[msg_index]);
if (sib_pdu == nullptr) {
logger.error("Failed to pack SIB");
return SRSRAN_ERROR;
}
sib_buffer.push_back(std::move(sib));
cell_ctxt->sib_buffer.push_back(std::move(sib_pdu));
// Log SIBs in JSON format
fmt::memory_buffer strbuf;
fmt::format_to(strbuf, "SI message={} payload", msg_index);
log_rrc_message(fmt::to_string(strbuf), Tx, *sib_buffer.back().get(), msg[msg_index], "");
log_rrc_message(fmt::to_string(strbuf), Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], "");
}
nof_si_messages = sib_buffer.size() - 1;
return SRSRAN_SUCCESS;
}
@ -383,21 +353,21 @@ int32_t rrc_nr::generate_sibs()
int rrc_nr::read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer)
{
if (mib_buffer == nullptr || buffer.get_tailroom() < mib_buffer->N_bytes) {
if (cell_ctxt->mib_buffer == nullptr || buffer.get_tailroom() < cell_ctxt->mib_buffer->N_bytes) {
return SRSRAN_ERROR;
}
buffer = *mib_buffer;
buffer = *cell_ctxt->mib_buffer;
return SRSRAN_SUCCESS;
}
int rrc_nr::read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer)
{
if (sib_index >= sib_buffer.size()) {
if (sib_index >= cell_ctxt->sib_buffer.size()) {
logger.error("SIB %d is not a configured SIB.", sib_index);
return SRSRAN_ERROR;
}
buffer = *sib_buffer[sib_index];
buffer = *cell_ctxt->sib_buffer[sib_index];
return SRSRAN_SUCCESS;
}

@ -39,14 +39,18 @@ public:
class mac_nr_dummy : public mac_interface_rrc_nr
{
public:
int cell_cfg(const std::vector<srsenb::sched_nr_interface::cell_cfg_t>& nr_cells) override { return SRSRAN_SUCCESS; }
int cell_cfg(const std::vector<srsenb::sched_nr_interface::cell_cfg_t>& nr_cells_) override
{
nr_cells = nr_cells_;
return SRSRAN_SUCCESS;
}
uint16_t reserve_rnti(uint32_t enb_cc_idx, const sched_nr_ue_cfg_t& uecfg) override { return 0x4601; }
int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override { return SRSRAN_SUCCESS; }
int remove_ue(uint16_t rnti) override { return SRSRAN_SUCCESS; }
srsenb::sched_interface::cell_cfg_t cellcfgobj;
std::vector<srsenb::sched_nr_interface::cell_cfg_t> nr_cells;
};
class phy_nr_dummy : public phy_interface_stack_nr

@ -41,27 +41,51 @@ int test_sib_generation()
{
srsran::task_scheduler task_sched;
phy_nr_dummy phy_obj;
mac_nr_dummy mac_obj;
rlc_dummy rlc_obj;
pdcp_dummy pdcp_obj;
rrc_nr rrc_obj(&task_sched);
// set cfg
rrc_nr_cfg_t default_cfg = {};
rrc_nr_cfg_t rrc_cfg = rrc_obj.update_default_cfg(default_cfg);
auto& sched_elem = rrc_cfg.sib1.si_sched_info.sched_info_list[0];
all_args_t args{};
phy_cfg_t phy_cfg{};
rrc_nr_cfg_t rrc_cfg_nr = {};
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, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) ==
TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) ==
SRSRAN_SUCCESS);
TESTASSERT(test_cell_cfg(mac_obj.cellcfgobj) == SRSRAN_SUCCESS);
// TEMP tests
TESTASSERT(mac_obj.cellcfgobj.sibs[1].len > 0);
TESTASSERT(mac_obj.cellcfgobj.sibs[1].period_rf == sched_elem.si_periodicity.to_number());
for (int i = 2; i < 16; ++i) {
TESTASSERT(mac_obj.cellcfgobj.sibs[i].len == 0);
const sched_nr_interface::cell_cfg_t& nrcell = mac_obj.nr_cells.at(0);
TESTASSERT(nrcell.sibs.size() > 0);
// TEST SIB1
TESTASSERT(nrcell.sibs[0].len > 0);
TESTASSERT_EQ(16, nrcell.sibs[0].period_rf);
srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
TESTASSERT_EQ(SRSRAN_SUCCESS, rrc_obj.read_pdu_bcch_dlsch(0, *pdu));
TESTASSERT(pdu->size() > 0);
asn1::rrc_nr::bcch_dl_sch_msg_s msg;
{
asn1::cbit_ref bref{pdu->data(), pdu->size()};
TESTASSERT_EQ(SRSRAN_SUCCESS, msg.unpack(bref));
}
TESTASSERT(mac_obj.cellcfgobj.cell.nof_prb == 25);
TESTASSERT_EQ(bcch_dl_sch_msg_type_c::types_opts::c1, msg.msg.type().value);
TESTASSERT_EQ(bcch_dl_sch_msg_type_c::c1_c_::types_opts::sib_type1, msg.msg.c1().type().value);
asn1::rrc_nr::sib1_s& sib1 = msg.msg.c1().sib_type1();
TESTASSERT(sib1.serving_cell_cfg_common_present);
pdcch_cfg_common_s& pdcch = sib1.serving_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup();
TESTASSERT(not pdcch.ctrl_res_set_zero_present); // CORESET#0 id is passed in MIB
TESTASSERT(not pdcch.search_space_zero_present); // SS#0 id is passed in MIB
return SRSRAN_SUCCESS;
}
@ -79,11 +103,12 @@ int test_rrc_setup()
// set cfg
all_args_t args{};
phy_cfg_t phy_cfg{};
rrc_nr_cfg_t rrc_cfg_nr = rrc_obj.update_default_cfg(rrc_nr_cfg_t{});
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 = false;
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, nullptr, nullptr, nullptr) ==
@ -115,8 +140,7 @@ int main(int argc, char** argv)
}
argparse::parse_args(argc, argv);
// FIXME: disabled temporarily until SIB generation is fixed
// TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS);
TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS);
TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;

@ -14,6 +14,8 @@
#include "srsenb/hdr/enb.h"
#include "srsran/common/test_common.h"
using namespace asn1::rrc;
namespace argparse {
std::string repository_dir;

@ -19,7 +19,6 @@
#include "srsran/adt/span.h"
using namespace srsenb;
using namespace asn1::rrc;
namespace argparse {
@ -229,9 +228,9 @@ namespace srsenb {
meas_cell_cfg_t generate_cell1();
report_cfg_eutra_s generate_rep1();
asn1::rrc::report_cfg_eutra_s generate_rep1();
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell);
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const asn1::rrc::cells_to_add_mod_s& cell);
} // namespace srsenb

Loading…
Cancel
Save