enb,cfg_parser: Add SIB5 parsing.

This commit is contained in:
Matan Perelman 2022-05-26 13:13:30 +03:00 committed by Andre Puschmann
parent 8de3d7436e
commit ce731c851c
3 changed files with 271 additions and 0 deletions

View File

@ -137,6 +137,71 @@ sib3 =
}
};
#####################################################################
# sib5 configuration options (See TS 36.331)
# Contains information relevant for inter-frequency cell re-selection.
# Must be added to sib1::sched_info::si_mapping_info array parameter to be transmitted
#
# inter_freq_carrier_freq_list: A list of neighbouring inter-frequencies.
# dl_carrier_freq: The EARFCN for the EUTRA carrier frequency.
# q_rx_lev_min: Minimum received RSRP level in the E-UTRA cell, ([field_val] * 2) = [level in dBm].
# p_max: Optional maximum allowed transmission power for the neighbouring E-UTRA cells on this carrier frequency.
# t_resel_eutra: Cell reselection timer (seconds).
# t_resel_eutra_sf: Optional speed dependent ScalingFactor for t_resel_eutra.
# sf_medium: Scaling factor if the UE is in Medium Mobility state, one of "0.25", "0.5", "0.75" or "1.0".
# sf_high: Scaling factor if the UE is in High Mobility state, one of "0.25", "0.5", "0.75" or "1.0".
# thresh_x_high: Srclev threshold (dB) to select to a higher-priority RAT/Frequency.
# thresh_x_low: Srclev threshold (dB) to select to a lower-priority RAT/Frequency.
# allowed_meas_bw: Maximum allowed measurement bandwidth on a carrier frequency .
# presence_ant_port_1: whether all the neighbouring cells use Antenna Port 1.
# cell_resel_prio: Optional absolute priority of the carrier frequency group.
# neigh_cell_cfg: Information related to MBSFN and TDD UL/DL configuration of neighbour cells.
# q_offset_freq: Frequency specific offset for equal priority E-UTRAN frequencies.
# inter_freq_neigh_cell_list: A List of inter-frequency neighbouring cells with specific cell re-selection parameters.
# phys_cell_id: Physical layer identity of the cell.
# q_offset_cell: Cell spcific offset.
# inter_freq_black_cell_list: A List of blacklisted inter-frequency neighbouring cells.
# start: The lowest physical cell identity in the range.
# range: The number of physical cell identities in the range.
#
#####################################################################
sib5 =
{
inter_freq_carrier_freq_list =
(
{
dl_carrier_freq = 1450;
q_rx_lev_min = -70;
t_resel_eutra = 2;
t_resel_eutra_sf = {
sf_medium = "0.25";
sf_high = "1.0";
};
thresh_x_high = 3;
thresh_x_low = 2;
allowed_meas_bw = 75;
presence_ant_port_1 = True;
cell_resel_prio = 4;
neigh_cell_cfg = 2;
q_offset_freq = -6;
inter_freq_neigh_cell_list =
(
{
phys_cell_id = 500;
q_offset_cell = 2;
}
);
inter_freq_black_cell_list =
(
{
start = 123;
range = 4;
}
);
}
);
};
#####################################################################
# sib6 configuration options (See TS 36.331)
# Contains UTRA neighbor information for inter-rat handover.

View File

@ -142,6 +142,156 @@ int field_intra_black_cell_list::parse(libconfig::Setting& root)
return 0;
}
int field_inter_freq_carrier_freq_list::parse(libconfig::Setting& root)
{
data->inter_freq_carrier_freq_list.resize((uint32_t)root.getLength());
for (uint32_t i = 0; i < data->inter_freq_carrier_freq_list.size() && i < ASN1_RRC_MAX_FREQ; i++) {
unsigned int dl_carrier_freq = 0;
if (!root[i].lookupValue("dl_carrier_freq", dl_carrier_freq)) {
ERROR("Missing field `dl_carrier_freq` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].dl_carrier_freq = dl_carrier_freq;
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 inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].q_rx_lev_min = q_rx_lev_min;
int p_max = 0;
if (root[i].lookupValue("p_max", p_max)) {
data->inter_freq_carrier_freq_list[i].p_max_present = true;
data->inter_freq_carrier_freq_list[i].p_max = p_max;
}
unsigned int t_resel_eutra = 0;
if (!root[i].lookupValue("t_resel_eutra", t_resel_eutra)) {
ERROR("Missing field `t_resel_eutra` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].t_resel_eutra = t_resel_eutra;
if (root[i].exists("t_resel_eutra_sf")) {
data->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present = true;
field_asn1_enum_number_str<asn1::rrc::speed_state_scale_factors_s::sf_medium_e_> sf_medium(
"sf_medium", &data->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_medium);
if (sf_medium.parse(root[i]["t_resel_eutra_sf"])) {
ERROR("Error parsing `sf_medium` in inter_freq_carrier_freq_list=%d t_resel_eutra_sf", i);
return SRSRAN_ERROR;
}
field_asn1_enum_number_str<asn1::rrc::speed_state_scale_factors_s::sf_high_e_> sf_high(
"sf_high", &data->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_high);
if (sf_high.parse(root[i]["t_resel_eutra_sf"])) {
ERROR("Error parsing `sf_high` in inter_freq_carrier_freq_list=%d t_resel_eutra_sf", i);
return SRSRAN_ERROR;
}
}
unsigned int thresh_x_high = 0;
if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) {
ERROR("Missing field `thresh_x_high` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].thresh_x_high = thresh_x_high;
unsigned int thresh_x_low = 0;
if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) {
ERROR("Missing field `thresh_x_low` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].thresh_x_low = thresh_x_low;
field_asn1_enum_number<asn1::rrc::allowed_meas_bw_e> allowed_meas_bw(
"allowed_meas_bw", &data->inter_freq_carrier_freq_list[i].allowed_meas_bw);
if (allowed_meas_bw.parse(root[i])) {
ERROR("Error parsing `allowed_meas_bw` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
bool presence_ant_port1 = 0;
if (!root[i].lookupValue("presence_ant_port_1", presence_ant_port1)) {
ERROR("Missing field `presence_ant_port_1` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
data->inter_freq_carrier_freq_list[i].presence_ant_port1 = presence_ant_port1;
unsigned int cell_resel_prio = 0;
if (root[i].lookupValue("cell_resel_prio", cell_resel_prio)) {
data->inter_freq_carrier_freq_list[i].cell_resel_prio_present = true;
data->inter_freq_carrier_freq_list[i].cell_resel_prio = cell_resel_prio;
}
field_asn1_enum_number<asn1::rrc::q_offset_range_e> q_offset_freq(
"q_offset_freq", &data->inter_freq_carrier_freq_list[i].q_offset_freq);
if (!q_offset_freq.parse(root[i])) {
data->inter_freq_carrier_freq_list[i].q_offset_freq_present = true;
}
field_asn1_bitstring_number<asn1::fixed_bitstring<2>, uint8_t> neigh_cell_cfg(
"neigh_cell_cfg", &data->inter_freq_carrier_freq_list[i].neigh_cell_cfg);
if (neigh_cell_cfg.parse(root[i])) {
ERROR("Error parsing `neigh_cell_cfg` in inter_freq_carrier_freq_list=%d", i);
return SRSRAN_ERROR;
}
if (root[i].exists("inter_freq_neigh_cell_list")) {
auto inter_neigh_cell_list_parser = new field_inter_freq_neigh_cell_list(&data->inter_freq_carrier_freq_list[i]);
HANDLEPARSERCODE(inter_neigh_cell_list_parser->parse(root[i]["inter_freq_neigh_cell_list"]));
}
if (root[i].exists("inter_freq_black_cell_list")) {
auto inter_black_cell_list_parser = new field_inter_freq_black_cell_list(&data->inter_freq_carrier_freq_list[i]);
HANDLEPARSERCODE(inter_black_cell_list_parser->parse(root[i]["inter_freq_black_cell_list"]));
}
}
return 0;
}
int field_inter_freq_neigh_cell_list::parse(libconfig::Setting& root)
{
data->inter_freq_neigh_cell_list.resize((uint32_t)root.getLength());
data->inter_freq_neigh_cell_list_present = data->inter_freq_neigh_cell_list.size() > 0;
for (uint32_t i = 0; i < data->inter_freq_neigh_cell_list.size() && i < ASN1_RRC_MAX_CELL_BLACK; i++) {
if (not parse_enum_by_number(data->inter_freq_neigh_cell_list[i].q_offset_cell, "q_offset_cell", root[i])) {
ERROR("Missing field q_offset_cell in neigh_cell=%d\n", i);
return SRSRAN_ERROR;
}
unsigned int phys_cell_id = 0;
if (!root[i].lookupValue("phys_cell_id", phys_cell_id)) {
ERROR("Missing field phys_cell_id in neigh_cell=%d\n", i);
return SRSRAN_ERROR;
}
data->inter_freq_neigh_cell_list[i].pci = (uint16)phys_cell_id;
}
return 0;
}
int field_inter_freq_black_cell_list::parse(libconfig::Setting& root)
{
data->inter_freq_black_cell_list.resize((uint32_t)root.getLength());
data->inter_freq_black_cell_list_present = data->inter_freq_black_cell_list.size() > 0;
for (uint32_t i = 0; i < data->inter_freq_black_cell_list.size() && i < ASN1_RRC_MAX_CELL_BLACK; i++) {
if (not parse_enum_by_number(data->inter_freq_black_cell_list[i].range, "range", root[i])) {
ERROR("Missing field range in black_cell=%d\n", i);
return SRSRAN_ERROR;
}
data->inter_freq_black_cell_list[i].range_present = true;
unsigned int start = 0;
if (!root[i].lookupValue("start", start)) {
ERROR("Missing field start in black_cell=%d\n", i);
return SRSRAN_ERROR;
}
data->inter_freq_black_cell_list[i].start = (uint16)start;
}
return 0;
}
int field_carrier_freq_list_utra_fdd::parse(libconfig::Setting& root)
{
data->carrier_freq_list_utra_fdd.resize((uint32_t)root.getLength());
@ -2336,6 +2486,20 @@ int parse_sib4(std::string filename, sib_type4_s* data)
return parser::parse_section(std::move(filename), &sib4);
}
int parse_sib5(std::string filename, sib_type5_s* data)
{
parser::section sib5("sib5");
// interFreqCarrierFreqList
parser::section inter_freq_carrier_freq_list("inter_freq_carrier_freq_list");
sib5.add_subsection(&inter_freq_carrier_freq_list);
bool dummy_bool = false;
inter_freq_carrier_freq_list.set_optional(&dummy_bool);
inter_freq_carrier_freq_list.add_field(new field_inter_freq_carrier_freq_list(data));
return parser::parse_section(std::move(filename), &sib5);
}
int parse_sib6(std::string filename, sib_type6_s* data)
{
parser::section sib6("sib6");
@ -2449,6 +2613,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
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_type5_s* sib5 = &rrc_cfg_->sibs[4].set_sib5();
sib_type6_s* sib6 = &rrc_cfg_->sibs[5].set_sib6();
sib_type7_s* sib7 = &rrc_cfg_->sibs[6].set_sib7();
sib_type9_s* sib9 = &rrc_cfg_->sibs[8].set_sib9();
@ -2519,6 +2684,13 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
}
}
// Generate SIB5 if defined in mapping info
if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type5)) {
if (sib_sections::parse_sib5(args_->enb_files.sib_config, sib5) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
}
// Generate SIB6 if defined in mapping info
if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type6)) {
if (sib_sections::parse_sib6(args_->enb_files.sib_config, sib6) != SRSRAN_SUCCESS) {

View File

@ -54,6 +54,7 @@ int parse_sib1(std::string filename, asn1::rrc::sib_type1_s* data);
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_sib5(std::string filename, asn1::rrc::sib_type5_s* data);
int parse_sib6(std::string filename, asn1::rrc::sib_type6_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);
@ -141,6 +142,39 @@ private:
asn1::rrc::sib_type4_s* data;
};
class field_inter_freq_carrier_freq_list final : public parser::field_itf
{
public:
explicit field_inter_freq_carrier_freq_list(asn1::rrc::sib_type5_s* data_) { data = data_; }
int parse(Setting& root) override;
const char* get_name() override { return "inter_freq_carrier_freq_list"; }
private:
asn1::rrc::sib_type5_s* data;
};
class field_inter_freq_neigh_cell_list final : public parser::field_itf
{
public:
explicit field_inter_freq_neigh_cell_list(asn1::rrc::inter_freq_carrier_freq_info_s* data_) { data = data_; }
int parse(Setting& root) override;
const char* get_name() override { return "inter_freq_neigh_cell_list"; }
private:
asn1::rrc::inter_freq_carrier_freq_info_s* data;
};
class field_inter_freq_black_cell_list final : public parser::field_itf
{
public:
explicit field_inter_freq_black_cell_list(asn1::rrc::inter_freq_carrier_freq_info_s* data_) { data = data_; }
int parse(Setting& root) override;
const char* get_name() override { return "inter_freq_black_cell_list"; }
private:
asn1::rrc::inter_freq_carrier_freq_info_s* data;
};
class field_carrier_freq_list_utra_fdd final : public parser::field_itf
{
public: