diff --git a/srsenb/hdr/parser.h b/srsenb/hdr/parser.h index 542238af6..993bfeb40 100644 --- a/srsenb/hdr/parser.h +++ b/srsenb/hdr/parser.h @@ -319,33 +319,67 @@ private: }; template -int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root) -{ - flag = root.lookupValue(field_name, obj); - return 0; -} - -template -int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root, Parser field_parser) -{ - flag = false; - if (root.exists(field_name)) { - flag = true; - return field_parser(obj, root[field_name]); +struct DefaultFieldParser { + int operator()(T& obj, Setting& root) const + { + obj = (T)root; + return 0; } - return 0; +}; +// specialization for uint16_t bc Setting does not have overloaded uint16_t operator +template <> +struct DefaultFieldParser { + int operator()(uint16_t& obj, Setting& root) const + { + obj = (uint32_t)root; + return 0; + } +}; + +template > +int parse_opt_field(T& obj, + Setting& root, + const char* field_name, + const Parser& field_parser = {}, + bool* presence_flag = nullptr) +{ + bool exists = root.exists(field_name); + if (presence_flag != nullptr) { + *presence_flag = exists; + } + return exists ? field_parser(obj, root[field_name]) : 0; } -template -NumberType parse_bounded_number(Setting& fieldroot, NumberType num_min, NumberType num_max) +//! Parse field if it exists. If not, default to "default_val" +template > +int parse_default_field(T& obj, + Setting& root, + const char* fieldname, + const T& default_val, + const Parser& field_parser = {}, + bool* presence_flag = nullptr) { - NumberType num = (NumberType)fieldroot; + bool opt_flag; + int ret = parse_opt_field(obj, root, fieldname, field_parser, &opt_flag); + if (not opt_flag) { + obj = default_val; + } + if (presence_flag != nullptr) { + *presence_flag = opt_flag; + } + return ret; +} + +template +int parse_bounded_number(T& number, Setting& fieldroot, T num_min, T num_max) +{ + T num = (T)fieldroot; if (num < num_min or num > num_max) { std::cout << "Parser Warning: Value of " << fieldroot.getName() << " must be within bound [" << num_min << ", " << num_max << "]\n"; num = (num > num_max) ? num_max : num_min; } - return num; + return 0; } namespace asn1_parsers { @@ -389,7 +423,7 @@ int str_to_enum(EnumType& enum_val, Setting& root) template int opt_str_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name) { - return parse_opt_field(enum_val, presence_flag, name, root, str_to_enum); + return parse_opt_field(enum_val, root, name, str_to_enum, &presence_flag); } template @@ -428,7 +462,7 @@ int number_to_enum(EnumType& enum_val, Setting& root) template int opt_number_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name) { - return parse_opt_field(enum_val, presence_flag, name, root, number_to_enum); + return parse_opt_field(enum_val, root, name, number_to_enum, &presence_flag); } } // namespace asn1_parsers diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index f13789da6..7df17a2fa 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -97,9 +97,9 @@ struct rrc_meas_cfg_t { struct cell_cfg_t { uint32_t rf_port; uint32_t cell_id; - uint32_t tac; + uint16_t tac; uint32_t pci; - uint32_t root_seq_idx; + uint16_t root_seq_idx; uint32_t dl_earfcn; uint32_t ul_earfcn; std::vector scell_list; diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index 54fc58ea7..9c0d40a85 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -50,8 +50,21 @@ phy_cnfg = }; }; -rrc_cnfg = -{ +cell_list = +( + // rf_port = 0; + // cell_id = 0x01; + // tac = 0x0001; + // pci = 1; + // root_seq_idx = 204; + // dl_earfcn = 3400; + // ul_earfcn = 474; + + // CA cells + scell_list = ( + {cell_id = 0x02; cross_carrier_scheduling = false; scheduling_cell_id = 0x02; ul_allowed = true}; + ); + // Cells available for handover meas_cell_list = ( @@ -70,4 +83,4 @@ rrc_cnfg = a3_time_to_trigger = 480; rsrq_config = 4; }; -}; +); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 1ed80bacd..273b2e783 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -956,9 +956,9 @@ int enb::parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg_->cqi_cfg.sf_mapping, &rrc_cfg_->cqi_cfg.nof_subframes)); /* RRC config section */ - parser::section rrc_cnfg("rrc_cnfg"); + parser::section rrc_cnfg("cell_list"); rrc_cnfg.set_optional(&rrc_cfg_->meas_cfg_present); - rrc_cnfg.add_field(new rr_sections::rrc_cnfg_section(args_, rrc_cfg_)); + rrc_cnfg.add_field(new rr_sections::cell_list_section(args_, rrc_cfg_)); // Run parser with two sections parser p(args_->enb_files.rr_config); @@ -1208,40 +1208,41 @@ 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) { - cell_cfg_t& cell_cfg = rrc_cfg->cell_list[n]; - cell_cfg.rf_port = (uint32_t)root[n]["rf_port"]; - cell_cfg.cell_id = parse_bounded_number(root[n]["cell_id"], 0, 255); - cell_cfg.tac = (uint32_t)root[n]["tac"]; - cell_cfg.pci = (uint32_t)root[n]["pci"]; - cell_cfg.root_seq_idx = (uint32_t)root[n]["root_seq_idx"]; + cell_cfg_t& cell_cfg = rrc_cfg->cell_list[n]; - if (not root[n].lookupValue("dl_earfcn", cell_cfg.dl_earfcn)) { - cell_cfg.dl_earfcn = args->enb.dl_earfcn; // default to enb.conf - } - if (not root[n].lookupValue("ul_earfcn", cell_cfg.ul_earfcn)) { - cell_cfg.ul_earfcn = args->enb.ul_earfcn; - } + parse_opt_field(cell_cfg.rf_port, root[n], "rf_port"); + parse_default_field(cell_cfg.cell_id, root[n], "cell_id", self_cellid, cell_id_parser); + parse_default_field(cell_cfg.tac, root[n], "tac", args->stack.s1ap.tac); + parse_default_field(cell_cfg.pci, root[n], "pci", args->enb.pci); + parse_default_field( + cell_cfg.root_seq_idx, root[n], "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx); + parse_default_field(cell_cfg.dl_earfcn, root[n], "dl_earfcn", args->enb.dl_earfcn); + parse_default_field(cell_cfg.ul_earfcn, root[n], "ul_earfcn", args->enb.ul_earfcn); + + HANDLEPARSERCODE(parse_meas_cell_list(&rrc_cfg->meas_cfg, root[n]["meas_cell_list"])); + HANDLEPARSERCODE(parse_meas_report_desc(&rrc_cfg->meas_cfg, root[n]["meas_report_desc"])); cell_cfg.scell_list.resize(root["scell_list"].getLength()); for (uint32_t i = 0; i < cell_cfg.scell_list.size(); ++i) { - auto& scell = cell_cfg.scell_list[i]; - auto& scellroot = root["scell_list"][i]; - scell.cell_id = parse_bounded_number(scellroot["cell_id"], 0, 255); + auto& scell = cell_cfg.scell_list[i]; + auto& scellroot = root["scell_list"][i]; + cell_id_parser(scell.cell_id, scellroot["cell_id"]); scell.cross_carrier_sched = (bool)scellroot["cross_carrier_scheduling"]; - scell.sched_cell_id = parse_bounded_number(scellroot["scheduling_cell_id"], 0, 255); - scell.ul_allowed = (bool)scellroot["ul_allowed"]; + cell_id_parser(scell.sched_cell_id, scellroot["scheduling_cell_id"]); + scell.ul_allowed = (bool)scellroot["ul_allowed"]; } } return SRSLTE_SUCCESS; } -int rrc_cnfg_section::parse(libconfig::Setting& root) +int cell_list_section::parse(libconfig::Setting& root) { - HANDLEPARSERCODE(parse_meas_cell_list(&rrc_cfg->meas_cfg, root["meas_cell_list"])); - HANDLEPARSERCODE(parse_meas_report_desc(&rrc_cfg->meas_cfg, root["meas_report_desc"])); HANDLEPARSERCODE(parse_cell_list(args, rrc_cfg, root["cell_list"])); return 0; } diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index ef602e50c..a8bea8fab 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -115,10 +115,10 @@ namespace rr_sections { // rrc_cnfg -class rrc_cnfg_section final : public parser::field_itf +class cell_list_section final : public parser::field_itf { public: - explicit rrc_cnfg_section(all_args_t* all_args_, rrc_cfg_t* rrc_cfg_) : args(all_args_), rrc_cfg(rrc_cfg_) {} + explicit cell_list_section(all_args_t* all_args_, rrc_cfg_t* rrc_cfg_) : args(all_args_), rrc_cfg(rrc_cfg_) {} int parse(Setting& root) override;