automatically resolve invalid prach_offset for prb6

This commit is contained in:
Francisco Paisana 2019-04-29 11:29:10 +01:00 committed by Andre Puschmann
parent 47acbc1e08
commit 1674c8939f
5 changed files with 52 additions and 120 deletions

View File

@ -25,10 +25,15 @@
#include <cstdint>
#include <string>
#define CEILFRAC(x, y) ((((x)-1) / (y)) + 1)
#define CEILFRAC(x, y) (((x) > 0) ? ((((x)-1) / (y)) + 1) : 0)
namespace srslte {
constexpr uint32_t ceil_div(uint32_t x, uint32_t y)
{
return (x > 0) ? (x - 1) / y + 1 : 0;
}
template <size_t N, bool reversed = false>
class bounded_bitset
{
@ -49,10 +54,12 @@ public:
if (new_size > max_size()) {
printf("ERROR: bitset resize out of bounds: %lu>=%lu\n", max_size(), new_size);
return;
} else if (new_size == cur_size) {
return;
}
cur_size = new_size;
sanitize_();
for (size_t i = nof_words_(); i < sizeof(buffer); ++i) {
for (size_t i = nof_words_(); i < max_nof_words_(); ++i) {
get_word_(i) = static_cast<word_t>(0);
}
}
@ -63,8 +70,7 @@ public:
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
return;
}
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) |= maskbit(pos);
set_(pos);
}
void reset(size_t pos) noexcept
@ -73,8 +79,7 @@ public:
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
return;
}
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) &= ~(maskbit(pos));
reset_(pos);
}
void reset() noexcept
@ -111,11 +116,11 @@ public:
// NOTE: can be optimized
if (value) {
for (size_t i = startpos; i < endpos; ++i) {
set(i);
set_(i);
}
} else {
for (size_t i = startpos; i < endpos; ++i) {
reset(i);
reset_(i);
}
}
return *this;
@ -176,7 +181,7 @@ public:
return result;
}
bool operator==(bounded_bitset<N, reversed>& other) const noexcept
bool operator==(const bounded_bitset<N, reversed>& other) const noexcept
{
if (size() != other.size()) {
return false;
@ -188,7 +193,7 @@ public:
return true;
}
bool operator!=(bounded_bitset<N, reversed>& other) const noexcept { return not(*this == other); }
bool operator!=(const bounded_bitset<N, reversed>& other) const noexcept { return not(*this == other); }
bounded_bitset<N, reversed>& operator|=(const bounded_bitset<N, reversed>& other) noexcept
{
@ -253,7 +258,7 @@ public:
std::string to_hex() const noexcept
{
size_t nof_digits = (size() - 1) / 4 + 1;
char cstr[CEILFRAC(CEILFRAC(N, bits_per_word) * bits_per_word, 4) + 1];
char cstr[ceil_div(ceil_div(N, bits_per_word) * bits_per_word, 4) + 1];
size_t count = 0;
for (int i = nof_words_() - 1; i >= 0; --i) {
@ -271,8 +276,9 @@ private:
void sanitize_()
{
if (N % bits_per_word != 0) {
buffer[nof_words_() - 1] &= ~((~static_cast<word_t>(0)) << (size() % bits_per_word));
size_t n = size() % bits_per_word;
if (n != 0) {
buffer[nof_words_() - 1] &= ~((~static_cast<word_t>(0)) << n);
}
}
@ -282,6 +288,18 @@ private:
return ((get_word_(pos) & maskbit(pos)) != static_cast<word_t>(0));
}
void set_(size_t pos) noexcept
{
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) |= maskbit(pos);
}
void reset_(size_t pos) noexcept
{
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) &= ~(maskbit(pos));
}
size_t nof_words_() const noexcept { return size() > 0 ? (size() - 1) / bits_per_word + 1 : 0; }
word_t& get_word_(size_t pos) noexcept { return buffer[pos / bits_per_word]; }
@ -291,6 +309,8 @@ private:
size_t word_idx_(size_t pos) const { return pos / bits_per_word; }
static word_t maskbit(size_t pos) { return (static_cast<word_t>(1)) << (pos % bits_per_word); }
static size_t max_nof_words_() { return (N - 1) / bits_per_word + 1; }
};
template <size_t N, bool reversed>
@ -315,7 +335,6 @@ template <size_t N, bool reversed>
inline bounded_bitset<N, reversed> fliplr(const bounded_bitset<N, reversed>& other) noexcept
{
bounded_bitset<N, reversed> ret(other.size());
ret.reset();
for (uint32_t i = 0; i < ret.size(); ++i) {
if (other.test(i)) {
ret.set(ret.size() - 1 - i);

View File

@ -1,90 +0,0 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <iostream>
#include "srslte/asn1/liblte_rrc.h"
#include "srslte/common/log_filter.h"
#include "srslte/srslte.h"
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int rrc_connection_reconf_test()
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
LIBLTE_BIT_MSG_STRUCT bit_buf;
LIBLTE_BIT_MSG_STRUCT bit_buf2;
LIBLTE_BYTE_MSG_STRUCT byte_buf;
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
uint8_t rrc_message[] = {0x20, 0x02, 0x01, 0x80, 0x01, 0x10, 0x10, 0x08, 0x21, 0x60, 0xCA, 0x32, 0x00, 0x06, 0x60};
uint32_t rrc_message_len = sizeof(rrc_message);
// 20020180011010082160CA32000660
bzero(&dl_dcch_msg, sizeof(dl_dcch_msg));
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len * 8);
bit_buf.N_bits = rrc_message_len * 8;
liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &dl_dcch_msg);
TESTASSERT(dl_dcch_msg.msg_type == LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG);
LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT* reconf = &dl_dcch_msg.msg.rrc_con_reconfig;
TESTASSERT(reconf->rrc_transaction_id == 0);
TESTASSERT(not reconf->meas_cnfg_present);
TESTASSERT(not reconf->mob_ctrl_info_present);
TESTASSERT(reconf->N_ded_info_nas == 0);
TESTASSERT(reconf->rr_cnfg_ded_present);
TESTASSERT(not reconf->sec_cnfg_ho_present);
// RR Config
TESTASSERT(reconf->rr_cnfg_ded.phy_cnfg_ded_present);
TESTASSERT(reconf->rr_cnfg_ded.drb_to_add_mod_list_size == 0);
TESTASSERT(reconf->rr_cnfg_ded.phy_cnfg_ded.ext);
TESTASSERT(reconf->rr_cnfg_ded.phy_cnfg_ded.ext_groups.N_groups == 5);
TESTASSERT(reconf->rr_cnfg_ded.phy_cnfg_ded.ext_groups.groups_present[1]);
TESTASSERT(reconf->rr_cnfg_ded.phy_cnfg_ded.ext_groups.group1.pucch_config_dedicated_v1020_present);
LIBLTE_RRC_PUCCH_CONFIG_DEDICATED_v1020* v1020 =
&reconf->rr_cnfg_ded.phy_cnfg_ded.ext_groups.group1.pucch_config_dedicated_v1020;
TESTASSERT(v1020->pucch_format_r10_present);
TESTASSERT(v1020->pucch_format_r10_choice == LIBLTE_RRC_PUCCH_CONFIG_DEDICATED_v1020::format3_r10);
TESTASSERT(v1020->pucch_format_r10.format3_r10.N_n3_pucch_an_list_r13 == 4);
TESTASSERT(v1020->pucch_format_r10.format3_r10.n3_pucch_an_list_r13[0] == 25);
TESTASSERT(v1020->pucch_format_r10.format3_r10.n3_pucch_an_list_r13[1] == 281);
TESTASSERT(v1020->pucch_format_r10.format3_r10.n3_pucch_an_list_r13[2] == 0);
TESTASSERT(v1020->pucch_format_r10.format3_r10.n3_pucch_an_list_r13[3] == 51);
return 0;
}
int main(int argc, char** argv)
{
TESTASSERT(rrc_connection_reconf_test() == 0);
}

View File

@ -171,8 +171,10 @@ bool enb::init(all_args_t *args_)
} else { // 6 PRB case
if (prach_freq_offset + 6 > cell_cfg.nof_prb) {
fprintf(stderr,
"Invalid PRACH configuration: frequency interval=(%d, %d) does not fit into the eNB PRBs=(0,%d)\n",
prach_freq_offset, prach_freq_offset + 6, cell_cfg.nof_prb);
"Warning: Invalid PRACH configuration - prach=(%d, %d) does not fit into the eNB PRBs=(0,%d)\n",
prach_freq_offset,
prach_freq_offset + 6,
cell_cfg.nof_prb);
return false;
}
}

View File

@ -702,6 +702,18 @@ int enb::parse_sibs(all_args_t* args, rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_config_
}
}
// Resolve invalid prach offset
uint32_t prach_freq_offset = sib2->rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset;
if (prach_freq_offset + 6 > rrc_cfg->cell.nof_prb) {
fprintf(stderr,
"Warning: Invalid PRACH configuration - prach=(%d, %d) does not fit into the eNB PRBs=(0,%d)\n",
prach_freq_offset,
prach_freq_offset + 6,
rrc_cfg->cell.nof_prb);
fprintf(stderr, "Warning: Going to use default prach offset. Change sib.conf to suppress with warning.\n");
sib2->rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset = 0;
}
// Copy PHY common configuration
bzero(&phy_config_common->cell, sizeof(phy_config_common->cell));
phy_config_common->prach_cnfg = sib2->rr_cfg_common.prach_cfg;

View File

@ -125,9 +125,9 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg)
}
P = srslte_ra_type0_P(cfg.cell.nof_prb);
si_n_rbg = ceilf((float) 4/P);
rar_n_rbg = ceilf((float) 3/P);
nof_rbg = (uint32_t) ceil((float) cfg.cell.nof_prb/P);
si_n_rbg = srslte::ceil_div(4, P);
rar_n_rbg = srslte::ceil_div(3, P);
nof_rbg = srslte::ceil_div(cfg.cell.nof_prb, P);
sched_vars.init(this);
// Compute Common locations for DCI for each CFI
@ -144,17 +144,6 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg)
}
configured = true;
// PRACH has to fit within the PUSCH space
bool invalid_prach = cfg.cell.nof_prb == 6 and (cfg.prach_freq_offset + 6 > cfg.cell.nof_prb);
invalid_prach |= cfg.cell.nof_prb > 6 and ((cfg.prach_freq_offset + 6) > (cfg.cell.nof_prb - cfg.nrb_pucch) or
(int) cfg.prach_freq_offset < cfg.nrb_pucch);
if (invalid_prach) {
log_h->error("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset);
log_h->console("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n",
cfg.prach_freq_offset);
return -1;
}
if (common_locations[sched_cfg.nof_ctrl_symbols - 1].nof_loc[2] == 0) {
Error("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.nof_ctrl_symbols in conf file).\n",
sched_cfg.nof_ctrl_symbols);