From 756374419fd07dad21c5dd708ac58e9e0f5e3be4 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. An example SIB7 section looks as follows: sib7 = { t_resel_geran = 1; carrier_freqs_info_list = ( { cell_resel_prio = 0; ncc_permitted = 255; q_rx_lev_min = 0; thresh_x_high = 7; thresh_x_low = 7; start_arfcn = 871; band_ind = "dcs1800"; explicit_list_of_arfcns = ( 873, 875, 877 ); } ); }; Closes: #357 --- srsenb/hdr/enb.h | 1 + srsenb/src/enb_cfg_parser.cc | 117 +++++++++++++++++++++++++++++++++++ srsenb/src/enb_cfg_parser.h | 14 +++++ 3 files changed, 132 insertions(+) diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 7ef46f1a1..f58007747 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -173,6 +173,7 @@ private: 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 80d5a8ad8..5a61dd670 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -129,6 +129,97 @@ 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; + if (data->carrier_freqs_info_list.size() > ASN1_RRC_MAX_GNFG) { + ERROR("CarrierFreqsInfoGERAN cannot have more than %d entries\n", ASN1_RRC_MAX_GNFG); + return -1; + } + for (uint32_t i = 0; i < data->carrier_freqs_info_list.size(); i++) { + + 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(); + + explicit_list_of_arfcns_l &exp_l = + data->carrier_freqs_info_list[i].carrier_freqs.following_arfcns.explicit_list_of_arfcns(); + if (root[i].exists("explicit_list_of_arfcns")) { + exp_l.resize((uint32_t)root[i]["explicit_list_of_arfcns"].getLength()); + if (exp_l.size() < 31) { /* SEQUENCE (SIZE (0..31)) OF ARFCN-ValueGERAN */ + for (uint32_t j = 0; j < exp_l.size(); j++) { + int arfcn = root[i]["explicit_list_of_arfcns"][j]; + if (arfcn >= 0 && arfcn <= 1024) { + exp_l[j] = (short unsigned int)arfcn; + } else { + fprintf(stderr, "Invalid ARFCN %d in for carrier_freqs_info_list=%d explicit_list_of_arfcns\n", i, j); + return -1; + } + } + } else { + fprintf(stderr, "Number of ARFCN in explicit_list_of_arfcns exceeds maximum (%d)\n", 31); + return -1; + } + } else { + exp_l.resize(0); + } + + } + return 0; +} + + int enb::parse_sib1(std::string filename, sib_type1_s* data) { parser::section sib1("sib1"); @@ -483,6 +574,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 +722,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 +796,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 72b7ea5af..464e73311 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -79,6 +79,20 @@ private: 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: