From c0edfe58a1148271c7d35d1e6505d6af46886ef9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 3 Aug 2019 22:05:38 +0200 Subject: [PATCH] SRSENB: Add SIB7 (GERAN neighbor) support This adds the required missing bits to the eNB config file parser to enable minimalistic support of parsing SIB7 configuration. SIB7 contains GERAN (GSM) neighbor cell information, which is important if you are operating a combined 2G+4G netowrk and want to assist the UEs to reselect GSM cells once they move out of LTE coverage. Closes: #357 --- srsenb/hdr/enb.h | 1 + srsenb/src/enb_cfg_parser.cc | 91 ++++++++++++++++++++++++++++++++++++ srsenb/src/enb_cfg_parser.h | 14 ++++++ 3 files changed, 106 insertions(+) diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 7ef46f1a1c..f580077474 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -173,6 +173,7 @@ class enb : public enb_metrics_interface int parse_sib2(std::string filename, asn1::rrc::sib_type2_s* data); int parse_sib3(std::string filename, asn1::rrc::sib_type3_s* data); int parse_sib4(std::string filename, asn1::rrc::sib_type4_s* data); + int parse_sib7(std::string filename, asn1::rrc::sib_type7_s* data); int parse_sib9(std::string filename, asn1::rrc::sib_type9_s* data); int parse_sib13(std::string filename, asn1::rrc::sib_type13_r9_s* data); int parse_sibs(all_args_t* args, rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_config_common); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 80d5a8ad84..95f736d9ff 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -129,6 +129,71 @@ int field_intra_black_cell_list::parse(libconfig::Setting& root) return 0; } +int field_carrier_freqs_info_list::parse(libconfig::Setting& root) +{ + data->carrier_freqs_info_list.resize((uint32_t)root.getLength()); + data->carrier_freqs_info_list_present = data->carrier_freqs_info_list.size() > 0; + for (uint32_t i = 0; i < data->carrier_freqs_info_list.size() && i < 8; i++) { // FIXME + + int cell_resel_prio; + if (root[i].lookupValue("cell_resel_prio", cell_resel_prio)) { + data->carrier_freqs_info_list[i].common_info.cell_resel_prio_present = true; + data->carrier_freqs_info_list[i].common_info.cell_resel_prio = cell_resel_prio; + } + + int p_max_geran; + if (root[i].lookupValue("p_max_geran", p_max_geran)) { + data->carrier_freqs_info_list[i].common_info.p_max_geran_present = true; + data->carrier_freqs_info_list[i].common_info.p_max_geran = p_max_geran; + } + + field_asn1_bitstring_number, uint8_t> ncc_permitted("ncc_permitted", + &data->carrier_freqs_info_list[i].common_info.ncc_permitted); + if (ncc_permitted.parse(root[i])) { + ERROR("Error parsing `ncc_permitted` in carrier_freqs_info_lsit=%d\n", i); + return -1; + } + + int q_rx_lev_min = 0; + if (!root[i].lookupValue("q_rx_lev_min", q_rx_lev_min)) { + ERROR("Missing field `q_rx_lev_min` in carrier_freqs_info_list=%d\n", i); + return -1; + } + data->carrier_freqs_info_list[i].common_info.q_rx_lev_min = q_rx_lev_min; + + int thresh_x_high = 0; + if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) { + ERROR("Missing field `thresh_x_high` in carrier_freqs_info_list=%d\n", i); + return -1; + } + data->carrier_freqs_info_list[i].common_info.thresh_x_high = thresh_x_high; + + int thresh_x_low = 0; + if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) { + ERROR("Missing field `thresh_x_low` in carrier_freqs_info_list=%d\n", i); + return -1; + } + data->carrier_freqs_info_list[i].common_info.thresh_x_low = thresh_x_low; + + int start_arfcn = 0; + if (root[i].lookupValue("start_arfcn", start_arfcn)) { + data->carrier_freqs_info_list[i].carrier_freqs.start_arfcn = start_arfcn; + } + + field_asn1_enum_str band_ind("band_ind", + &data->carrier_freqs_info_list[i].carrier_freqs.band_ind); + if (band_ind.parse(root[i])) { + ERROR("Error parsing `band_ind` in carrier_freqs_info_list=%d\n", i); + return -1; + } + + data->carrier_freqs_info_list[i].carrier_freqs.following_arfcns.set_explicit_list_of_arfcns(); + + } + return 0; +} + + int enb::parse_sib1(std::string filename, sib_type1_s* data) { parser::section sib1("sib1"); @@ -483,6 +548,24 @@ int enb::parse_sib4(std::string filename, sib_type4_s* data) return parser::parse_section(filename, &sib4); } +int enb::parse_sib7(std::string filename, sib_type7_s* data) +{ + parser::section sib7("sib7"); + + sib7.add_field(new parser::field("t_resel_geran", &data->t_resel_geran)); + // TODO: t_resel_geran_sf + + data->carrier_freqs_info_list_present = true; + parser::section geran_neigh("carrier_freqs_info_list"); + sib7.add_subsection(&geran_neigh); + + bool dummy_bool = false; + geran_neigh.set_optional(&dummy_bool); + geran_neigh.add_field(new field_carrier_freqs_info_list(data)); + + return parser::parse_section(filename, &sib7); +} + int enb::parse_sib9(std::string filename, sib_type9_s* data) { parser::section sib9("sib9"); @@ -613,6 +696,7 @@ int enb::parse_sibs(all_args_t* args, rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_config_ sib_type2_s* sib2 = &rrc_cfg->sibs[1].set_sib2(); sib_type3_s* sib3 = &rrc_cfg->sibs[2].set_sib3(); sib_type4_s* sib4 = &rrc_cfg->sibs[3].set_sib4(); + sib_type7_s* sib7 = &rrc_cfg->sibs[6].set_sib7(); sib_type9_s* sib9 = &rrc_cfg->sibs[8].set_sib9(); sib_type13_r9_s* sib13 = &rrc_cfg->sibs[12].set_sib13_v920(); @@ -686,6 +770,13 @@ int enb::parse_sibs(all_args_t* args, rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_config_ } } + // Generate SIB7 if defined in mapping info + if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type7)) { + if (parse_sib7(args->enb_files.sib_config, sib7)) { + return -1; + } + } + // Generate SIB9 if defined in mapping info if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type9)) { if (parse_sib9(args->enb_files.sib_config, sib9)) { diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index 72b7ea5afe..464e733113 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -79,6 +79,20 @@ class field_intra_black_cell_list : public parser::field_itf asn1::rrc::sib_type4_s* data; }; +class field_carrier_freqs_info_list : public parser::field_itf +{ +public: + field_carrier_freqs_info_list(asn1::rrc::sib_type7_s* data_) { data = data_; } + ~field_carrier_freqs_info_list(){} + int parse(Setting &root); + const char* get_name() { + return "carrier_freqs_info_list"; + } + +private: + asn1::rrc::sib_type7_s* data; +}; + class field_sf_mapping : public parser::field_itf { public: