refactor cell param handling and fix SIB transmissions
- move cell specific eNB params to cell list in rr.conf - make sure DL EARFCN and DL freq can be used to manually overwrite a single cell config - fix SIB packing and transmission for multi cell configs - introduce cell list to MAC - adapt default enb.conf.example and rr.conf.example
This commit is contained in:
parent
4e12405fff
commit
120ad76c63
|
@ -296,8 +296,8 @@ public:
|
|||
* Segmentation happens in this function. RLC PDU is stored in payload. */
|
||||
virtual int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||
|
||||
virtual void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload) = 0;
|
||||
virtual void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) = 0;
|
||||
virtual void read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload) = 0;
|
||||
virtual void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) = 0;
|
||||
|
||||
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread.
|
||||
* PDU gets placed into the buffer and higher layer thread gets notified. */
|
||||
|
@ -371,10 +371,10 @@ public:
|
|||
class rrc_interface_rlc
|
||||
{
|
||||
public:
|
||||
virtual void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload) = 0;
|
||||
virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0;
|
||||
virtual void max_retx_attempted(uint16_t rnti) = 0;
|
||||
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||
virtual void read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload) = 0;
|
||||
virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0;
|
||||
virtual void max_retx_attempted(uint16_t rnti) = 0;
|
||||
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||
};
|
||||
|
||||
// RRC interface for MAC
|
||||
|
@ -389,6 +389,29 @@ public:
|
|||
virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0;
|
||||
};
|
||||
|
||||
// SCell configuration
|
||||
struct scell_cfg_t {
|
||||
uint32_t cell_id;
|
||||
bool cross_carrier_sched = false;
|
||||
uint32_t sched_cell_id;
|
||||
bool ul_allowed;
|
||||
};
|
||||
|
||||
// Cell/Sector configuration
|
||||
struct cell_cfg_t {
|
||||
uint32_t rf_port;
|
||||
uint32_t cell_id;
|
||||
uint16_t tac;
|
||||
uint32_t pci;
|
||||
uint16_t root_seq_idx;
|
||||
uint32_t dl_earfcn;
|
||||
float dl_freq_hz;
|
||||
uint32_t ul_earfcn;
|
||||
float ul_freq_hz;
|
||||
std::vector<scell_cfg_t> scell_list;
|
||||
};
|
||||
typedef std::vector<cell_cfg_t> cell_list_t;
|
||||
|
||||
// RRC interface for PDCP
|
||||
class rrc_interface_pdcp
|
||||
{
|
||||
|
@ -482,6 +505,7 @@ typedef struct {
|
|||
} s1ap_args_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t nof_prb; ///< Needed to dimension MAC softbuffers for all cells
|
||||
sched_interface::sched_args_t sched;
|
||||
int link_failure_nof_err;
|
||||
} mac_args_t;
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
# eNB configuration
|
||||
#
|
||||
# enb_id: 20-bit eNB identifier.
|
||||
# cell_id: 8-bit cell identifier.
|
||||
# tac: 16-bit Tracking Area Code.
|
||||
# mcc: Mobile Country Code
|
||||
# mnc: Mobile Network Code
|
||||
# mme_addr: IP address of MME for S1 connnection
|
||||
|
@ -20,9 +18,6 @@
|
|||
#####################################################################
|
||||
[enb]
|
||||
enb_id = 0x19B
|
||||
cell_id = 0x01
|
||||
phy_cell_id = 1
|
||||
tac = 0x0007
|
||||
mcc = 001
|
||||
mnc = 01
|
||||
mme_addr = 127.0.1.100
|
||||
|
@ -48,7 +43,7 @@ drb_config = drb.conf
|
|||
#####################################################################
|
||||
# RF configuration
|
||||
#
|
||||
# dl_earfcn: EARFCN code for DL
|
||||
# dl_earfcn: EARFCN code for DL (only valid if a single cell is configured in rr.conf)
|
||||
# tx_gain: Transmit gain (dB).
|
||||
# rx_gain: Optional receive gain (dB). If disabled, AGC if enabled
|
||||
#
|
||||
|
@ -64,7 +59,7 @@ drb_config = drb.conf
|
|||
# Default "auto". B210 USRP: 100 samples, bladeRF: 27.
|
||||
#####################################################################
|
||||
[rf]
|
||||
dl_earfcn = 3400
|
||||
#dl_earfcn = 3400
|
||||
tx_gain = 80
|
||||
rx_gain = 40
|
||||
|
||||
|
|
|
@ -59,10 +59,10 @@ namespace srsenb {
|
|||
*******************************************************************************/
|
||||
|
||||
struct enb_args_t {
|
||||
uint32_t dl_earfcn;
|
||||
uint32_t ul_earfcn;
|
||||
std::string enb_id;
|
||||
uint32_t dl_earfcn; // By default the EARFCN from rr.conf's cell list are used but this value can be used for single
|
||||
// cell eNB
|
||||
uint32_t n_prb;
|
||||
uint32_t pci;
|
||||
uint32_t nof_ports;
|
||||
uint32_t transmission_mode;
|
||||
float p_a;
|
||||
|
|
|
@ -370,6 +370,17 @@ int parse_default_field(T& obj,
|
|||
return ret;
|
||||
}
|
||||
|
||||
//! Parse required field and return error if field isn't specified
|
||||
template <typename T, typename Parser = DefaultFieldParser<T> >
|
||||
int parse_required_field(T& obj, Setting& root, const char* field_name, const Parser& field_parser = {})
|
||||
{
|
||||
if (not root.exists(field_name)) {
|
||||
fprintf(stderr, "PARSER ERROR: Field \"%s\" doesn't exist.\n", field_name);
|
||||
return -1;
|
||||
}
|
||||
return field_parser(obj, root[field_name]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int parse_bounded_number(T& number, Setting& fieldroot, T num_min, T num_max)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
mac();
|
||||
~mac();
|
||||
bool init(const mac_args_t& args_,
|
||||
srslte_cell_t* cell,
|
||||
const cell_list_t& cells_,
|
||||
phy_interface_stack_lte* phy,
|
||||
rlc_interface_mac* rlc,
|
||||
rrc_interface_mac* rrc,
|
||||
|
@ -114,7 +114,7 @@ private:
|
|||
stack_interface_mac_lte* stack = nullptr;
|
||||
srslte::log* log_h = nullptr;
|
||||
|
||||
srslte_cell_t cell = {};
|
||||
cell_list_t cells = {};
|
||||
mac_args_t args = {};
|
||||
|
||||
// derived from args
|
||||
|
@ -137,7 +137,7 @@ private:
|
|||
int rar_idx,
|
||||
uint32_t pdu_len,
|
||||
uint32_t tti);
|
||||
uint8_t* assemble_si(uint32_t index);
|
||||
uint8_t* assemble_si(const uint8_t cc_idx, const uint32_t index);
|
||||
|
||||
const static int rar_payload_len = 128;
|
||||
std::vector<srslte::rar_pdu> rar_pdu_msg;
|
||||
|
|
|
@ -74,13 +74,6 @@ struct meas_cell_cfg_t {
|
|||
float q_offset;
|
||||
};
|
||||
|
||||
struct scell_cfg_t {
|
||||
uint32_t cell_id;
|
||||
bool cross_carrier_sched = false;
|
||||
uint32_t sched_cell_id;
|
||||
bool ul_allowed;
|
||||
};
|
||||
|
||||
// neigh measurement Cell info
|
||||
struct rrc_meas_cfg_t {
|
||||
std::vector<meas_cell_cfg_t> meas_cells;
|
||||
|
@ -92,23 +85,10 @@ struct rrc_meas_cfg_t {
|
|||
// TODO: Add multiple meas configs
|
||||
};
|
||||
|
||||
// Cell/Sector configuration
|
||||
struct cell_cfg_t {
|
||||
uint32_t rf_port;
|
||||
uint32_t cell_id;
|
||||
uint16_t tac;
|
||||
uint32_t pci;
|
||||
uint16_t root_seq_idx;
|
||||
uint32_t dl_earfcn;
|
||||
float dl_freq_hz;
|
||||
uint32_t ul_earfcn;
|
||||
float ul_freq_hz;
|
||||
std::vector<scell_cfg_t> scell_list;
|
||||
};
|
||||
|
||||
#define MAX_NOF_QCI 10
|
||||
|
||||
struct rrc_cfg_t {
|
||||
uint32_t enb_id; ///< Required to pack SIB1
|
||||
asn1::rrc::sib_type1_s sib1;
|
||||
asn1::rrc::sib_info_item_c sibs[ASN1_RRC_MAX_SIB];
|
||||
asn1::rrc::mac_main_cfg_s mac_cnfg;
|
||||
|
@ -119,16 +99,14 @@ struct rrc_cfg_t {
|
|||
rrc_cfg_sr_t sr_cfg;
|
||||
rrc_cfg_cqi_t cqi_cfg;
|
||||
rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI];
|
||||
srslte_cell_t cell;
|
||||
bool enable_mbsfn;
|
||||
uint32_t inactivity_timeout_ms;
|
||||
srslte::CIPHERING_ALGORITHM_ID_ENUM eea_preference_list[srslte::CIPHERING_ALGORITHM_ID_N_ITEMS];
|
||||
srslte::INTEGRITY_ALGORITHM_ID_ENUM eia_preference_list[srslte::INTEGRITY_ALGORITHM_ID_N_ITEMS];
|
||||
bool meas_cfg_present = false;
|
||||
rrc_meas_cfg_t meas_cfg;
|
||||
std::vector<cell_cfg_t> cell_list;
|
||||
uint32_t pci; // TODO: add this to srslte_cell_t?
|
||||
uint32_t dl_earfcn; // TODO: add this to srslte_cell_t?
|
||||
srslte_cell_t cell;
|
||||
cell_list_t cell_list;
|
||||
};
|
||||
|
||||
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE",
|
||||
|
@ -148,7 +126,7 @@ public:
|
|||
rrc();
|
||||
~rrc();
|
||||
|
||||
void init(rrc_cfg_t* cfg,
|
||||
void init(const rrc_cfg_t& cfg_,
|
||||
phy_interface_rrc_lte* phy,
|
||||
mac_interface_rrc* mac,
|
||||
rlc_interface_rrc* rlc,
|
||||
|
@ -170,7 +148,7 @@ public:
|
|||
bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) override;
|
||||
|
||||
// rrc_interface_rlc
|
||||
void read_pdu_bcch_dlsch(uint32_t sib_idx, uint8_t* payload) override;
|
||||
void read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload) override;
|
||||
void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) override;
|
||||
void max_retx_attempted(uint16_t rnti) override;
|
||||
|
||||
|
@ -390,7 +368,7 @@ private:
|
|||
std::map<uint16_t, std::unique_ptr<ue> > users; // NOTE: has to have fixed addr
|
||||
std::map<uint32_t, asn1::s1ap::ue_paging_id_c> pending_paging;
|
||||
|
||||
std::vector<srslte::unique_byte_buffer_t> sib_buffer;
|
||||
std::map<uint8_t, std::vector<srslte::unique_byte_buffer_t> > sib_buffer; ///< Packed SIBs for each CC
|
||||
|
||||
void process_release_complete(uint16_t rnti);
|
||||
void process_rl_failure(uint16_t rnti);
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
// rlc_interface_mac
|
||||
int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
||||
void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload);
|
||||
void read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload);
|
||||
void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
||||
void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size);
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ cell_list =
|
|||
(
|
||||
{
|
||||
// rf_port = 0;
|
||||
// cell_id = 0x01;
|
||||
// tac = 0x0001;
|
||||
// pci = 1;
|
||||
cell_id = 0x01;
|
||||
tac = 0x0001;
|
||||
pci = 1;
|
||||
// root_seq_idx = 204;
|
||||
// dl_earfcn = 3400;
|
||||
// ul_earfcn = 21400;
|
||||
dl_earfcn = 3400;
|
||||
ul_earfcn = 21400;
|
||||
ho_active = false;
|
||||
|
||||
// CA cells
|
||||
|
|
|
@ -651,19 +651,6 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
|
|||
p.add_section(&phy_cfg_);
|
||||
p.add_section(&rrc_cnfg);
|
||||
|
||||
// If the cell list is empty, use default values from enb.conf to keep backwards compatibility
|
||||
if (rrc_cfg_->cell_list.empty()) {
|
||||
rrc_cfg_->cell_list.resize(1);
|
||||
cell_cfg_t& cell_cfg = rrc_cfg_->cell_list[0];
|
||||
cell_cfg.rf_port = 0;
|
||||
cell_cfg.cell_id = 0;
|
||||
cell_cfg.tac = args_->stack.s1ap.tac;
|
||||
cell_cfg.pci = args_->enb.pci;
|
||||
cell_cfg.root_seq_idx = rrc_cfg_->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx;
|
||||
cell_cfg.dl_earfcn = args_->enb.dl_earfcn;
|
||||
cell_cfg.ul_earfcn = args_->enb.ul_earfcn;
|
||||
}
|
||||
|
||||
return p.parse();
|
||||
}
|
||||
|
||||
|
@ -672,7 +659,7 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root)
|
|||
meas_cfg->meas_cells.resize(root.getLength());
|
||||
for (uint32_t i = 0; i < meas_cfg->meas_cells.size(); ++i) {
|
||||
meas_cfg->meas_cells[i].earfcn = root[i]["dl_earfcn"];
|
||||
meas_cfg->meas_cells[i].pci = (unsigned int)root[i]["pci"] % 504;
|
||||
meas_cfg->meas_cells[i].pci = (unsigned int)root[i]["pci"] % SRSLTE_NUM_PCI;
|
||||
meas_cfg->meas_cells[i].eci = (unsigned int)root[i]["eci"];
|
||||
meas_cfg->meas_cells[i].q_offset = 0; // LIBLTE_RRC_Q_OFFSET_RANGE_DB_0; // TODO
|
||||
// // TODO: TEMP
|
||||
|
@ -715,7 +702,6 @@ static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& root)
|
|||
static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
|
||||
{
|
||||
auto cell_id_parser = [](uint32_t& cell_id, Setting& root) { return parse_bounded_number(cell_id, root, 0u, 255u); };
|
||||
uint32_t self_cellid = args->stack.s1ap.cell_id & 0xFFu;
|
||||
|
||||
rrc_cfg->cell_list.resize(root.getLength());
|
||||
for (uint32_t n = 0; n < rrc_cfg->cell_list.size(); ++n) {
|
||||
|
@ -723,13 +709,14 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
|
|||
auto& cellroot = root[n];
|
||||
|
||||
parse_opt_field(cell_cfg.rf_port, cellroot, "rf_port");
|
||||
parse_default_field(cell_cfg.cell_id, cellroot, "cell_id", self_cellid, cell_id_parser);
|
||||
parse_default_field(cell_cfg.tac, cellroot, "tac", args->stack.s1ap.tac);
|
||||
parse_default_field(cell_cfg.pci, cellroot, "pci", args->enb.pci);
|
||||
HANDLEPARSERCODE(parse_required_field(cell_cfg.cell_id, cellroot, "cell_id"));
|
||||
HANDLEPARSERCODE(parse_required_field(cell_cfg.tac, cellroot, "tac"));
|
||||
HANDLEPARSERCODE(parse_required_field(cell_cfg.pci, cellroot, "pci"));
|
||||
cell_cfg.pci = cell_cfg.pci % SRSLTE_NUM_PCI;
|
||||
HANDLEPARSERCODE(parse_required_field(cell_cfg.dl_earfcn, cellroot, "dl_earfcn"));
|
||||
HANDLEPARSERCODE(parse_required_field(cell_cfg.ul_earfcn, cellroot, "ul_earfcn"));
|
||||
parse_default_field(
|
||||
cell_cfg.root_seq_idx, cellroot, "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx);
|
||||
cell_cfg.dl_earfcn = cellroot["dl_earfcn"];
|
||||
cell_cfg.ul_earfcn = cellroot["ul_earfcn"];
|
||||
|
||||
if (cellroot["ho_active"]) {
|
||||
HANDLEPARSERCODE(parse_meas_cell_list(&rrc_cfg->meas_cfg, cellroot["meas_cell_list"]));
|
||||
|
@ -778,13 +765,12 @@ namespace enb_conf_sections {
|
|||
int parse_cell_cfg(all_args_t* args_, srslte_cell_t* cell)
|
||||
{
|
||||
cell->frame_type = SRSLTE_FDD;
|
||||
cell->id = args_->enb.pci;
|
||||
cell->cp = SRSLTE_CP_NORM;
|
||||
cell->nof_ports = args_->enb.nof_ports;
|
||||
cell->nof_prb = args_->enb.n_prb;
|
||||
// PCI not configured yet
|
||||
|
||||
phich_cfg_s phichcfg;
|
||||
|
||||
parser::section phy_cnfg("phy_cnfg");
|
||||
parser::section phich_cnfg("phich_cnfg");
|
||||
phy_cnfg.add_subsection(&phich_cnfg);
|
||||
|
@ -853,7 +839,7 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
} catch (const SettingTypeException& stex) {
|
||||
fprintf(stderr, "\"Error parsing DRB configuration: %s\n", stex.getPath());
|
||||
fprintf(stderr, "Error parsing DRB configuration: %s\n", stex.getPath());
|
||||
return SRSLTE_ERROR;
|
||||
} catch (const ConfigException& cex) {
|
||||
fprintf(stderr, "Error parsing DRB configuration\n");
|
||||
|
@ -861,18 +847,61 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
|
|||
}
|
||||
|
||||
// Set fields derived from others, and check for correctness of the parsed configuration
|
||||
return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, &cell_common_cfg);
|
||||
return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg);
|
||||
}
|
||||
|
||||
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, srslte_cell_t* cell_cfg_)
|
||||
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srslte_cell_t& cell_cfg_)
|
||||
{
|
||||
// Copy cell struct to rrc and phy
|
||||
rrc_cfg_->cell = *cell_cfg_;
|
||||
// Sanity check
|
||||
if (rrc_cfg_->cell_list.empty()) {
|
||||
ERROR("No cell specified in RR config.");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Check for a forced DL EARFCN or frequency (only valid for a single cell config (Xico's favorite feature))
|
||||
if (rrc_cfg_->cell_list.size() == 1) {
|
||||
auto& cfg = rrc_cfg_->cell_list.at(0);
|
||||
if (args_->enb.dl_earfcn > 0) {
|
||||
cfg.dl_earfcn = args_->enb.dl_earfcn;
|
||||
ERROR("Force DL EARFCN for cell PCI=%d to %d\n", cfg.pci, cfg.dl_earfcn);
|
||||
}
|
||||
if (args_->rf.dl_freq > 0) {
|
||||
cfg.dl_freq_hz = args_->rf.dl_freq;
|
||||
ERROR("Force DL freq for cell PCI=%d to %f MHz\n", cfg.pci, cfg.dl_freq_hz / 1e6f);
|
||||
}
|
||||
} else {
|
||||
// If more than one cell is defined, single EARFCN or DL freq will be ignored
|
||||
if (args_->enb.dl_earfcn > 0 || args_->rf.dl_freq > 0) {
|
||||
INFO("Multiple cells defined in rr.conf. Ignoring single EARFCN and/or frequency config.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// set config for RRC's base cell
|
||||
rrc_cfg_->cell = cell_cfg_;
|
||||
|
||||
// Set S1AP related params from cell list (Convert hex strings)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << args_->enb.enb_id;
|
||||
sstr >> args_->stack.s1ap.enb_id;
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << rrc_cfg_->cell_list.at(0).cell_id;
|
||||
uint16_t tmp; // Need intermediate uint16_t as uint8_t is treated as char
|
||||
sstr >> tmp;
|
||||
args_->stack.s1ap.cell_id = tmp;
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << rrc_cfg_->cell_list.at(0).tac;
|
||||
sstr >> args_->stack.s1ap.tac;
|
||||
}
|
||||
|
||||
// Create dedicated cell configuration from RRC configuration
|
||||
for (auto& cfg : rrc_cfg_->cell_list) {
|
||||
phy_cell_cfg_t phy_cell_cfg = {};
|
||||
phy_cell_cfg.cell = *cell_cfg_;
|
||||
phy_cell_cfg.cell = cell_cfg_;
|
||||
phy_cell_cfg.cell.id = cfg.pci;
|
||||
phy_cell_cfg.cell_id = cfg.cell_id;
|
||||
phy_cell_cfg.root_seq_idx = cfg.root_seq_idx;
|
||||
|
@ -906,16 +935,12 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
|
|||
rrc_cfg_->inactivity_timeout_ms = args_->general.rrc_inactivity_timer;
|
||||
rrc_cfg_->enable_mbsfn = args_->stack.embms.enable;
|
||||
|
||||
rrc_cfg_->dl_earfcn = args_->enb.dl_earfcn;
|
||||
rrc_cfg_->pci = args_->enb.pci;
|
||||
|
||||
// Check number of control symbols
|
||||
if (cell_cfg_->nof_prb < 50 && args_->stack.mac.sched.nof_ctrl_symbols != 3) {
|
||||
if (cell_cfg_.nof_prb < 50 && args_->stack.mac.sched.nof_ctrl_symbols != 3) {
|
||||
args_->stack.mac.sched.nof_ctrl_symbols = 3;
|
||||
fprintf(stdout,
|
||||
"Setting number of control symbols to %d for %d PRB cell.\n",
|
||||
args_->stack.mac.sched.nof_ctrl_symbols,
|
||||
cell_cfg_->nof_prb);
|
||||
INFO("Setting number of control symbols to %d for %d PRB cell.\n",
|
||||
args_->stack.mac.sched.nof_ctrl_symbols,
|
||||
cell_cfg_.nof_prb);
|
||||
}
|
||||
|
||||
// Parse EEA preference list
|
||||
|
@ -968,9 +993,9 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
|
|||
|
||||
// Check PRACH configuration
|
||||
uint32_t prach_freq_offset = rrc_cfg_->sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset;
|
||||
if (rrc_cfg_->cell.nof_prb > 10) {
|
||||
if (args_->enb.n_prb > 10) {
|
||||
uint32_t lower_bound = SRSLTE_MAX(rrc_cfg_->sr_cfg.nof_prb, rrc_cfg_->cqi_cfg.nof_prb);
|
||||
uint32_t upper_bound = rrc_cfg_->cell.nof_prb - lower_bound;
|
||||
uint32_t upper_bound = args_->enb.n_prb - lower_bound;
|
||||
if (prach_freq_offset + 6 > upper_bound or prach_freq_offset < lower_bound) {
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid PRACH configuration - prach_freq_offset=%d collides with PUCCH.\n",
|
||||
|
@ -982,12 +1007,12 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
} else { // 6 PRB case
|
||||
if (prach_freq_offset + 6 > rrc_cfg_->cell.nof_prb) {
|
||||
if (prach_freq_offset + 6 > args_->enb.n_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);
|
||||
args_->enb.n_prb);
|
||||
fprintf(
|
||||
stderr,
|
||||
" Consider changing the \"prach_freq_offset\" value to 0 in the sib.conf file when using 6 PRBs.\n");
|
||||
|
@ -1001,6 +1026,12 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
|
|||
args_->rf.nof_carriers = rrc_cfg_->cell_list.size();
|
||||
args_->rf.nof_antennas = args_->enb.nof_ports;
|
||||
|
||||
// MAC needs to know the cell bandwidth to dimension softbuffers
|
||||
args_->stack.mac.nof_prb = args_->enb.n_prb;
|
||||
|
||||
// RRC needs eNB id for SIB1 packing
|
||||
rrc_cfg_->enb_id = args_->stack.s1ap.enb_id;
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1390,10 +1421,6 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
|
|||
}
|
||||
|
||||
// Fill rest of data from enb config
|
||||
sib_type1_s::cell_access_related_info_s_* cell_access = &sib1->cell_access_related_info;
|
||||
cell_access->cell_id.from_number((args_->stack.s1ap.enb_id << 8u) + args_->stack.s1ap.cell_id);
|
||||
cell_access->tac.from_number(args_->stack.s1ap.tac);
|
||||
sib1->freq_band_ind = (uint8_t)srslte_band_get_band(args_->enb.dl_earfcn);
|
||||
std::string mnc_str;
|
||||
if (not srslte::mnc_to_string(args_->stack.s1ap.mnc, &mnc_str)) {
|
||||
ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mnc);
|
||||
|
@ -1404,6 +1431,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
|
|||
ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mcc);
|
||||
return -1;
|
||||
}
|
||||
sib_type1_s::cell_access_related_info_s_* cell_access = &sib1->cell_access_related_info;
|
||||
cell_access->plmn_id_list.resize(1);
|
||||
srslte::plmn_id_t plmn;
|
||||
if (plmn.from_string(mcc_str + mnc_str) == SRSLTE_ERROR) {
|
||||
|
@ -1424,9 +1452,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
|
|||
if (sib2->freq_info.ul_bw_present) {
|
||||
asn1::number_to_enum(sib2->freq_info.ul_bw, args_->enb.n_prb);
|
||||
}
|
||||
if (sib2->freq_info.ul_carrier_freq_present) {
|
||||
sib2->freq_info.ul_carrier_freq = (uint16_t)args_->enb.ul_earfcn;
|
||||
}
|
||||
// UL carrier freq is patched before packing the SIB for each CC
|
||||
|
||||
// Update MBSFN list counter. Only 1 supported
|
||||
if (not args_->stack.embms.enable) {
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace enb_conf_sections {
|
|||
|
||||
int parse_cell_cfg(all_args_t* args_, srslte_cell_t* cell);
|
||||
int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_);
|
||||
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, srslte_cell_t* cell_cfg_);
|
||||
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srslte_cell_t& cell_cfg_);
|
||||
|
||||
} // namespace enb_conf_sections
|
||||
|
||||
|
|
|
@ -49,9 +49,6 @@ string config_file;
|
|||
|
||||
void parse_args(all_args_t* args, int argc, char* argv[])
|
||||
{
|
||||
string enb_id;
|
||||
string cell_id;
|
||||
string tac;
|
||||
string mcc;
|
||||
string mnc;
|
||||
|
||||
|
@ -67,16 +64,13 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
bpo::options_description common("Configuration options");
|
||||
common.add_options()
|
||||
|
||||
("enb.enb_id", bpo::value<string>(&enb_id)->default_value("0x0"), "eNodeB ID")
|
||||
("enb.enb_id", bpo::value<string>(&args->enb.enb_id)->default_value("0x0"), "eNodeB ID")
|
||||
("enb.name", bpo::value<string>(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name")
|
||||
("enb.cell_id", bpo::value<string>(&cell_id)->default_value("0x0"), "Cell ID")
|
||||
("enb.tac", bpo::value<string>(&tac)->default_value("0x0"), "Tracking Area Code")
|
||||
("enb.mcc", bpo::value<string>(&mcc)->default_value("001"), "Mobile Country Code")
|
||||
("enb.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code")
|
||||
("enb.mme_addr", bpo::value<string>(&args->stack.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connection")
|
||||
("enb.gtp_bind_addr", bpo::value<string>(&args->stack.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection")
|
||||
("enb.s1c_bind_addr", bpo::value<string>(&args->stack.s1ap.s1c_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for S1AP connection")
|
||||
("enb.phy_cell_id", bpo::value<uint32_t>(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)")
|
||||
("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB")
|
||||
("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports")
|
||||
("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)")
|
||||
|
@ -86,8 +80,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files")
|
||||
("enb_files.drb_config", bpo::value<string>(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files")
|
||||
|
||||
("rf.dl_earfcn", bpo::value<uint32_t>(&args->enb.dl_earfcn)->default_value(3400), "Downlink EARFCN")
|
||||
("rf.ul_earfcn", bpo::value<uint32_t>(&args->enb.ul_earfcn)->default_value(0), "Uplink EARFCN (Default based on Downlink EARFCN)")
|
||||
("rf.dl_earfcn", bpo::value<uint32_t>(&args->enb.dl_earfcn)->default_value(0), "Force Downlink EARFCN for single cell")
|
||||
("rf.rx_gain", bpo::value<float>(&args->rf.rx_gain)->default_value(50), "Front-end receiver gain")
|
||||
("rf.tx_gain", bpo::value<float>(&args->rf.tx_gain)->default_value(70), "Front-end transmitter gain")
|
||||
("rf.dl_freq", bpo::value<float>(&args->rf.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)")
|
||||
|
@ -252,25 +245,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
// Convert hex strings
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << vm["enb.enb_id"].as<std::string>();
|
||||
sstr >> args->stack.s1ap.enb_id;
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << vm["enb.cell_id"].as<std::string>();
|
||||
uint16_t tmp; // Need intermediate uint16_t as uint8_t is treated as char
|
||||
sstr >> tmp;
|
||||
args->stack.s1ap.cell_id = tmp;
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << std::hex << vm["enb.tac"].as<std::string>();
|
||||
sstr >> args->stack.s1ap.tac;
|
||||
}
|
||||
|
||||
// Convert MCC/MNC strings
|
||||
if (!srslte::string_to_mcc(mcc, &args->stack.s1ap.mcc)) {
|
||||
cout << "Error parsing enb.mcc:" << mcc << " - must be a 3-digit string." << endl;
|
||||
|
@ -279,24 +253,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl;
|
||||
}
|
||||
|
||||
// Convert UL/DL EARFCN to frequency if needed
|
||||
if (args->rf.dl_freq < 0) {
|
||||
args->rf.dl_freq = 1e6 * srslte_band_fd(args->enb.dl_earfcn);
|
||||
if (args->rf.dl_freq < 0) {
|
||||
fprintf(stderr, "Error getting DL frequency for EARFCN=%d\n", args->enb.dl_earfcn);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (args->rf.ul_freq < 0) {
|
||||
if (args->enb.ul_earfcn == 0) {
|
||||
args->enb.ul_earfcn = srslte_band_ul_earfcn(args->enb.dl_earfcn);
|
||||
}
|
||||
args->rf.ul_freq = 1e6 * srslte_band_fu(args->enb.ul_earfcn);
|
||||
if (args->rf.ul_freq < 0) {
|
||||
fprintf(stderr, "Error getting UL frequency for EARFCN=%d\n", args->enb.dl_earfcn);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (args->stack.embms.enable) {
|
||||
if (args->stack.mac.sched.nof_ctrl_symbols == 3) {
|
||||
fprintf(stderr,
|
||||
|
|
|
@ -106,10 +106,10 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
|
|||
rx_sockets.reset(new srslte::rx_multisocket_handler("ENBSOCKETS", &stack_log));
|
||||
|
||||
// Init all layers
|
||||
mac.init(args.mac, &rrc_cfg.cell, phy, &rlc, &rrc, this, &mac_log);
|
||||
mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc, this, &mac_log);
|
||||
rlc.init(&pdcp, &rrc, &mac, &timers, &rlc_log);
|
||||
pdcp.init(&rlc, &rrc, >pu);
|
||||
rrc.init(&rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, &rrc_log);
|
||||
rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, &rrc_log);
|
||||
s1ap.init(args.s1ap, &rrc, &timers, this);
|
||||
gtpu.init(args.s1ap.gtp_bind_addr,
|
||||
args.s1ap.mme_addr,
|
||||
|
|
|
@ -51,7 +51,7 @@ mac::~mac()
|
|||
}
|
||||
|
||||
bool mac::init(const mac_args_t& args_,
|
||||
srslte_cell_t* cell_,
|
||||
const cell_list_t& cells_,
|
||||
phy_interface_stack_lte* phy,
|
||||
rlc_interface_mac* rlc,
|
||||
rrc_interface_mac* rrc,
|
||||
|
@ -60,7 +60,7 @@ bool mac::init(const mac_args_t& args_,
|
|||
{
|
||||
started = false;
|
||||
|
||||
if (cell_ && phy && rlc && log_h_) {
|
||||
if (phy && rlc && log_h_) {
|
||||
phy_h = phy;
|
||||
rlc_h = rlc;
|
||||
rrc_h = rrc;
|
||||
|
@ -68,7 +68,7 @@ bool mac::init(const mac_args_t& args_,
|
|||
log_h = log_h_;
|
||||
|
||||
args = args_;
|
||||
cell = *cell_;
|
||||
cells = cells_;
|
||||
|
||||
stack_task_queue = stack->get_task_queue();
|
||||
|
||||
|
@ -79,13 +79,13 @@ bool mac::init(const mac_args_t& args_,
|
|||
|
||||
// Init softbuffer for SI messages
|
||||
for (int i = 0; i < NOF_BCCH_DLSCH_MSG; i++) {
|
||||
srslte_softbuffer_tx_init(&bcch_softbuffer_tx[i], cell.nof_prb);
|
||||
srslte_softbuffer_tx_init(&bcch_softbuffer_tx[i], args.nof_prb);
|
||||
}
|
||||
// Init softbuffer for PCCH
|
||||
srslte_softbuffer_tx_init(&pcch_softbuffer_tx, cell.nof_prb);
|
||||
srslte_softbuffer_tx_init(&pcch_softbuffer_tx, args.nof_prb);
|
||||
|
||||
// Init softbuffer for RAR
|
||||
srslte_softbuffer_tx_init(&rar_softbuffer_tx, cell.nof_prb);
|
||||
srslte_softbuffer_tx_init(&rar_softbuffer_tx, args.nof_prb);
|
||||
|
||||
reset();
|
||||
|
||||
|
@ -430,7 +430,7 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx
|
|||
|
||||
// Create new UE
|
||||
if (ue_db.count(rnti) == 0) {
|
||||
ue_db[rnti] = new ue(rnti, cell.nof_prb, &scheduler, rrc_h, rlc_h, log_h, SRSLTE_FDD_NOF_HARQ);
|
||||
ue_db[rnti] = new ue(rnti, args.nof_prb, &scheduler, rrc_h, rlc_h, log_h, SRSLTE_FDD_NOF_HARQ);
|
||||
}
|
||||
|
||||
// Set PCAP if available
|
||||
|
@ -581,7 +581,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res_list)
|
|||
// Set softbuffer
|
||||
if (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH) {
|
||||
dl_sched_res->pdsch[n].softbuffer_tx[0] = &bcch_softbuffer_tx[sched_result.bc[i].index];
|
||||
dl_sched_res->pdsch[n].data[0] = assemble_si(sched_result.bc[i].index);
|
||||
dl_sched_res->pdsch[n].data[0] = assemble_si(enb_cc_idx, sched_result.bc[i].index);
|
||||
#ifdef WRITE_SIB_PCAP
|
||||
if (pcap) {
|
||||
pcap->write_dl_sirnti(dl_sched_res->pdsch[n].data[0], sched_result.bc[i].tbs, true, tti, enb_cc_idx);
|
||||
|
@ -739,9 +739,9 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants,
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t* mac::assemble_si(uint32_t index)
|
||||
uint8_t* mac::assemble_si(const uint8_t cc_idx, const uint32_t index)
|
||||
{
|
||||
rlc_h->read_pdu_bcch_dlsch(index, bcch_dlsch_payload);
|
||||
rlc_h->read_pdu_bcch_dlsch(cc_idx, index, bcch_dlsch_payload);
|
||||
return bcch_dlsch_payload;
|
||||
}
|
||||
|
||||
|
@ -833,7 +833,7 @@ void mac::write_mcch(sib_type2_s* sib2_, sib_type13_r9_s* sib13_, mcch_msg_s* mc
|
|||
mcch.pack(bref);
|
||||
current_mcch_length = bref.distance_bytes(&mcch_payload_buffer[1]);
|
||||
current_mcch_length = current_mcch_length + rlc_header_len;
|
||||
ue_db[SRSLTE_MRNTI] = new ue(SRSLTE_MRNTI, cell.nof_prb, &scheduler, rrc_h, rlc_h, log_h);
|
||||
ue_db[SRSLTE_MRNTI] = new ue(SRSLTE_MRNTI, args.nof_prb, &scheduler, rrc_h, rlc_h, log_h);
|
||||
|
||||
rrc_h->add_user(SRSLTE_MRNTI, {});
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ rrc::rrc()
|
|||
|
||||
rrc::~rrc() {}
|
||||
|
||||
void rrc::init(rrc_cfg_t* cfg_,
|
||||
void rrc::init(const rrc_cfg_t& cfg_,
|
||||
phy_interface_rrc_lte* phy_,
|
||||
mac_interface_rrc* mac_,
|
||||
rlc_interface_rrc* rlc_,
|
||||
|
@ -64,10 +64,10 @@ void rrc::init(rrc_cfg_t* cfg_,
|
|||
|
||||
pool = srslte::byte_buffer_pool::get_instance();
|
||||
|
||||
cfg = *cfg_;
|
||||
cfg = cfg_;
|
||||
|
||||
if (cfg.sibs[12].type() == asn1::rrc::sys_info_r8_ies_s::sib_type_and_info_item_c_::types::sib13_v920 &&
|
||||
cfg_->enable_mbsfn) {
|
||||
cfg.enable_mbsfn) {
|
||||
configure_mbsfn_sibs(&cfg.sibs[1].sib2(), &cfg.sibs[12].sib13_v920());
|
||||
}
|
||||
|
||||
|
@ -126,10 +126,10 @@ void rrc::get_metrics(rrc_metrics_t& m)
|
|||
to the queue and process later
|
||||
*******************************************************************************/
|
||||
|
||||
void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
||||
void rrc::read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload)
|
||||
{
|
||||
if (sib_index < ASN1_RRC_MAX_SIB) {
|
||||
memcpy(payload, sib_buffer[sib_index]->msg, sib_buffer[sib_index]->N_bytes);
|
||||
if (sib_index < ASN1_RRC_MAX_SIB && cc_idx < sib_buffer.size()) {
|
||||
memcpy(payload, sib_buffer.at(cc_idx).at(sib_index)->msg, sib_buffer.at(cc_idx).at(sib_index)->N_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -776,7 +776,7 @@ void rrc::config_mac()
|
|||
|
||||
// set sib/prach cfg
|
||||
for (uint32_t i = 0; i < nof_si_messages; i++) {
|
||||
item.sibs[i].len = sib_buffer[i]->N_bytes;
|
||||
item.sibs[i].len = sib_buffer.at(ccidx).at(i)->N_bytes;
|
||||
if (i == 0) {
|
||||
item.sibs[i].period_rf = 8; // SIB1 is always 8 rf
|
||||
} else {
|
||||
|
@ -794,7 +794,7 @@ void rrc::config_mac()
|
|||
item.nrb_pucch = SRSLTE_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb);
|
||||
rrc_log->info("Allocating %d PRBs for PUCCH\n", item.nrb_pucch);
|
||||
|
||||
// Copy Cell configuration
|
||||
// Copy base cell configuration
|
||||
item.cell = cfg.cell;
|
||||
|
||||
// copy secondary cell list info
|
||||
|
@ -821,58 +821,90 @@ void rrc::config_mac()
|
|||
mac->cell_cfg(sched_cfg);
|
||||
}
|
||||
|
||||
/* This methods packs the SIBs for each component carrier and stores them
|
||||
* inside the sib_buffer, a vector of SIBs for each CC.
|
||||
*
|
||||
* Before packing the message, it patches the cell specific params of
|
||||
* the SIB, including the cellId and the PRACH config index.
|
||||
*
|
||||
* @return The number of SIBs messages per CC
|
||||
*/
|
||||
uint32_t rrc::generate_sibs()
|
||||
{
|
||||
// nof_messages includes SIB2 by default, plus all configured SIBs
|
||||
uint32_t nof_messages = 1 + cfg.sib1.sched_info_list.size();
|
||||
sched_info_list_l& sched_info = cfg.sib1.sched_info_list;
|
||||
|
||||
// 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
|
||||
asn1::dyn_array<bcch_dl_sch_msg_s> msg(nof_messages + 1);
|
||||
// generate SIBs for each CC
|
||||
for (uint8_t cc_idx = 0; cc_idx < cfg.cell_list.size(); cc_idx++) {
|
||||
// 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
|
||||
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;
|
||||
// Copy SIB1 to first SI message
|
||||
msg[0].msg.set_c1().set_sib_type1() = cfg.sib1;
|
||||
|
||||
// Copy rest of SIBs
|
||||
for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages - 1; sched_info_elem++) {
|
||||
uint32_t msg_index = sched_info_elem + 1; // first msg is SIB1, therefore start with second
|
||||
// Update cellId
|
||||
sib_type1_s::cell_access_related_info_s_* cell_access = &msg[0].msg.c1().sib_type1().cell_access_related_info;
|
||||
cell_access->cell_id.from_number((cfg.enb_id << 8u) + cfg.cell_list.at(cc_idx).cell_id);
|
||||
cell_access->tac.from_number(cfg.cell_list.at(cc_idx).tac);
|
||||
|
||||
msg[msg_index].msg.set_c1().set_sys_info().crit_exts.set_sys_info_r8();
|
||||
sys_info_r8_ies_s::sib_type_and_info_l_& sib_list =
|
||||
msg[msg_index].msg.c1().sys_info().crit_exts.sys_info_r8().sib_type_and_info;
|
||||
// Update DL EARFCN
|
||||
msg[0].msg.c1().sib_type1().freq_band_ind = (uint8_t)srslte_band_get_band(cfg.cell_list.at(cc_idx).dl_earfcn);
|
||||
|
||||
// SIB2 always in second SI message
|
||||
if (msg_index == 1) {
|
||||
sib_list.push_back(cfg.sibs[1]);
|
||||
// Save SIB2
|
||||
sib2 = cfg.sibs[1].sib2();
|
||||
// Copy rest of SIBs
|
||||
for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages - 1; sched_info_elem++) {
|
||||
uint32_t msg_index = sched_info_elem + 1; // first msg is SIB1, therefore start with second
|
||||
|
||||
msg[msg_index].msg.set_c1().set_sys_info().crit_exts.set_sys_info_r8();
|
||||
sys_info_r8_ies_s::sib_type_and_info_l_& sib_list =
|
||||
msg[msg_index].msg.c1().sys_info().crit_exts.sys_info_r8().sib_type_and_info;
|
||||
|
||||
// SIB2 always in second SI message
|
||||
if (msg_index == 1) {
|
||||
// update PRACH root seq index for this cell
|
||||
cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx = cfg.cell_list.at(cc_idx).root_seq_idx;
|
||||
|
||||
// update carrier freq
|
||||
if (cfg.sibs[1].sib2().freq_info.ul_carrier_freq_present) {
|
||||
cfg.sibs[1].sib2().freq_info.ul_carrier_freq = cfg.cell_list.at(cc_idx).ul_earfcn;
|
||||
}
|
||||
|
||||
sib_list.push_back(cfg.sibs[1]);
|
||||
|
||||
// Save SIB2
|
||||
sib2 = cfg.sibs[1].sib2();
|
||||
}
|
||||
|
||||
// Add other SIBs to this message, if any
|
||||
for (auto& mapping_enum : sched_info[sched_info_elem].sib_map_info) {
|
||||
sib_list.push_back(cfg.sibs[(int)mapping_enum + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add other SIBs to this message, if any
|
||||
for (auto& mapping_enum : sched_info[sched_info_elem].sib_map_info) {
|
||||
sib_list.push_back(cfg.sibs[(int)mapping_enum + 2]);
|
||||
// Pack payload for all messages
|
||||
for (uint32_t msg_index = 0; msg_index < nof_messages; msg_index++) {
|
||||
srslte::unique_byte_buffer_t sib = srslte::allocate_unique_buffer(*pool);
|
||||
asn1::bit_ref bref(sib->msg, sib->get_tailroom());
|
||||
asn1::bit_ref bref0 = bref;
|
||||
if (msg[msg_index].pack(bref) == asn1::SRSASN_ERROR_ENCODE_FAIL) {
|
||||
rrc_log->error("Failed to pack SIB message %d\n", msg_index);
|
||||
}
|
||||
sib->N_bytes = static_cast<uint32_t>((bref.distance(bref0) - 1) / 8 + 1);
|
||||
sib_buffer[cc_idx].push_back(std::move(sib));
|
||||
|
||||
// Log SIBs in JSON format
|
||||
std::string log_msg("CC" + std::to_string(cc_idx) + " SIB payload");
|
||||
log_rrc_message(log_msg,
|
||||
Tx,
|
||||
sib_buffer.at(cc_idx).at(msg_index).get(),
|
||||
msg[msg_index],
|
||||
msg[msg_index].msg.c1().type().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Pack payload for all messages
|
||||
for (uint32_t msg_index = 0; msg_index < nof_messages; msg_index++) {
|
||||
srslte::unique_byte_buffer_t sib = srslte::allocate_unique_buffer(*pool);
|
||||
asn1::bit_ref bref(sib->msg, sib->get_tailroom());
|
||||
asn1::bit_ref bref0 = bref;
|
||||
if (msg[msg_index].pack(bref) == asn1::SRSASN_ERROR_ENCODE_FAIL) {
|
||||
rrc_log->error("Failed to pack SIB message %d\n", msg_index);
|
||||
if (cfg.sibs[6].type() == asn1::rrc::sys_info_r8_ies_s::sib_type_and_info_item_c_::types::sib7) {
|
||||
sib7 = cfg.sibs[6].sib7();
|
||||
}
|
||||
sib->N_bytes = static_cast<uint32_t>((bref.distance(bref0) - 1) / 8 + 1);
|
||||
sib_buffer.push_back(std::move(sib));
|
||||
|
||||
// Log SIBs in JSON format
|
||||
log_rrc_message(
|
||||
"SIB payload", Tx, sib_buffer[msg_index].get(), msg[msg_index], msg[msg_index].msg.c1().type().to_string());
|
||||
}
|
||||
|
||||
if (cfg.sibs[6].type() == asn1::rrc::sys_info_r8_ies_s::sib_type_and_info_item_c_::types::sib7) {
|
||||
sib7 = cfg.sibs[6].sib7();
|
||||
}
|
||||
|
||||
return nof_messages;
|
||||
|
|
|
@ -861,15 +861,16 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci,
|
|||
hoprep_r8.as_cfg.source_sib_type1 = rrc_enb->cfg.sib1;
|
||||
hoprep_r8.as_cfg.source_sib_type2 = rrc_enb->sib2;
|
||||
asn1::number_to_enum(hoprep_r8.as_cfg.ant_info_common.ant_ports_count, rrc_enb->cfg.cell.nof_ports);
|
||||
hoprep_r8.as_cfg.source_dl_carrier_freq = rrc_enb->cfg.dl_earfcn;
|
||||
hoprep_r8.as_cfg.source_dl_carrier_freq =
|
||||
rrc_enb->cfg.cell_list.at(0).dl_earfcn; // TODO: use actual DL EARFCN of source cell
|
||||
// - fill as_context
|
||||
hoprep_r8.as_context_present = true;
|
||||
hoprep_r8.as_context.reest_info_present = true;
|
||||
hoprep_r8.as_context.reest_info.source_pci = rrc_enb->cfg.pci;
|
||||
hoprep_r8.as_context.reest_info.source_pci = rrc_enb->cfg.cell_list.at(0).pci; // TODO: use actual PCI of source cell
|
||||
hoprep_r8.as_context.reest_info.target_cell_short_mac_i.from_number(
|
||||
rrc_details::compute_mac_i(rrc_ue->rnti,
|
||||
rrc_enb->cfg.sib1.cell_access_related_info.cell_id.to_number(),
|
||||
rrc_enb->cfg.pci,
|
||||
rrc_enb->cfg.cell_list.at(0).pci, // TODO: use actual PCI of source cell
|
||||
rrc_ue->integ_algo,
|
||||
rrc_ue->k_rrc_int));
|
||||
|
||||
|
|
|
@ -193,10 +193,10 @@ void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof
|
|||
pthread_rwlock_unlock(&rwlock);
|
||||
}
|
||||
|
||||
void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
||||
void rlc::read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index, uint8_t* payload)
|
||||
{
|
||||
// RLC is transparent for BCCH
|
||||
rrc->read_pdu_bcch_dlsch(sib_index, payload);
|
||||
rrc->read_pdu_bcch_dlsch(cc_idx, sib_index, payload);
|
||||
}
|
||||
|
||||
void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu)
|
||||
|
|
|
@ -46,7 +46,7 @@ int test_erab_setup(bool qci_exists)
|
|||
gtpu_dummy gtpu;
|
||||
rrc_log->set_level(srslte::LOG_LEVEL_INFO);
|
||||
rrc_log->set_hex_limit(1024);
|
||||
rrc.init(&cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, rrc_log.get());
|
||||
rrc.init(cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, rrc_log.get());
|
||||
|
||||
auto tic = [&timers, &rrc] {
|
||||
timers.step_all();
|
||||
|
|
|
@ -282,7 +282,7 @@ int test_mobility_class(mobility_test_params test_params)
|
|||
gtpu_dummy gtpu;
|
||||
rrc_log->set_level(srslte::LOG_LEVEL_INFO);
|
||||
rrc_log->set_hex_limit(1024);
|
||||
rrc.init(&cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, rrc_log.get());
|
||||
rrc.init(cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, rrc_log.get());
|
||||
|
||||
auto tic = [&timers, &rrc] {
|
||||
timers.step_all();
|
||||
|
|
Loading…
Reference in New Issue