diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 1aaf6f29b..5f269ec86 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -65,12 +65,14 @@ class cell_t return earfcn == this->earfcn && pci == phy_cell.id; } bool greater(cell_t *x) { - return x->rsrp > rsrp; + return rsrp > x->rsrp; } bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { - for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) { - if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) { - return true; + if (has_valid_sib1) { + for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) { + if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) { + return true; + } } } return false; @@ -80,6 +82,7 @@ class cell_t cell_t(tmp, 0, 0); } cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) { + gettimeofday(&last_update, NULL); this->has_valid_sib1 = false; this->has_valid_sib2 = false; this->has_valid_sib3 = false; @@ -94,14 +97,106 @@ class cell_t bzero(&sib13, sizeof(sib13)); } - uint32_t earfcn; + uint32_t get_earfcn() { + return earfcn; + } + + uint32_t get_pci() { + return phy_cell.id; + } + + void set_rsrp(float rsrp) { + this->rsrp = rsrp; + in_sync = true; + gettimeofday(&last_update, NULL); + } + + float get_rsrp() { + return rsrp; + } + + void set_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1) { + memcpy(&this->sib1, sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); + has_valid_sib1 = true; + } + void set_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) { + memcpy(&this->sib2, sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); + has_valid_sib2 = true; + } + void set_sib3(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3) { + memcpy(&this->sib3, sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); + has_valid_sib3 = true; + } + void set_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) { + memcpy(&this->sib13, sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); + has_valid_sib13 = true; + } + + uint32_t timeout_secs(struct timeval now) { + struct timeval t[3]; + memcpy(&t[2], &now, sizeof(struct timeval)); + memcpy(&t[1], &last_update, sizeof(struct timeval)); + get_time_interval(t); + return t[0].tv_sec; + } + + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1ptr() { + return &sib1; + } + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2ptr() { + return &sib2; + } + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() { + return &sib3; + } + + uint32_t get_cell_id() { + return sib1.cell_id; + } + + bool has_sib1() { + return has_valid_sib1; + } + bool has_sib2() { + return has_valid_sib2; + } + bool has_sib3() { + return has_valid_sib3; + } + bool has_sib13() { + return has_valid_sib13; + } + + uint16_t get_mcc() { + if (has_valid_sib1) { + if (sib1.N_plmn_ids > 0) { + return sib1.plmn_id[0].id.mcc; + } + } + return 0; + } + + uint16_t get_mnc() { + if (has_valid_sib1) { + if (sib1.N_plmn_ids > 0) { + return sib1.plmn_id[0].id.mnc; + } + } + return 0; + } + srslte_cell_t phy_cell; + bool in_sync; + + private: float rsrp; + uint32_t earfcn; + struct timeval last_update; + bool has_valid_sib1; bool has_valid_sib2; bool has_valid_sib3; bool has_valid_sib13; - bool in_sync; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; @@ -274,6 +369,7 @@ private: } // List of strongest neighbour cell + const static int NEIGHBOUR_TIMEOUT = 5; const static int NOF_NEIGHBOUR_CELLS = 8; std::vector neighbour_cells; cell_t *serving_cell; @@ -285,6 +381,9 @@ private: bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); bool add_neighbour_cell(cell_t *cell); void sort_neighbour_cells(); + void clean_neighbours(); + std::vector::iterator delete_neighbour(std::vector::iterator it); + void delete_neighbour(uint32_t cell_idx); typedef enum { SI_ACQUIRE_IDLE = 0, @@ -315,6 +414,7 @@ private: void run_tti(uint32_t tti); bool timer_expired(uint32_t timer_id); void ho_finish(); + void delete_report(uint32_t earfcn, uint32_t pci); private: const static int NOF_MEASUREMENTS = 3; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 4d93c9452..9e26436ae 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -54,6 +54,7 @@ rrc::rrc() n310_cnt = 0; n311_cnt = 0; serving_cell = new cell_t(); + neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); } rrc::~rrc() @@ -168,6 +169,7 @@ void rrc::set_args(rrc_args_t *args) { void rrc::run_thread() { uint32_t failure_test = 0; + uint32_t cell_clean_cnt = 0; while (thread_running) { @@ -217,13 +219,13 @@ void rrc::run_thread() { * Cell is selected when all SIBs downloaded or applied. */ if (phy->sync_status()) { - if (!serving_cell->has_valid_sib1) { + if (!serving_cell->has_sib1()) { si_acquire_state = SI_ACQUIRE_SIB1; sysinfo_index = 0; - } else if (!serving_cell->has_valid_sib2) { + } else if (!serving_cell->has_sib2()) { si_acquire_state = SI_ACQUIRE_SIB2; } else { - apply_sib2_configs(&serving_cell->sib2); + apply_sib2_configs(serving_cell->sib2ptr()); si_acquire_state = SI_ACQUIRE_IDLE; state = RRC_STATE_CELL_SELECTED; } @@ -302,6 +304,13 @@ void rrc::run_thread() { default: break; } + if (state == RRC_STATE_CONNECTED || RRC_STATE_IDLE) { + cell_clean_cnt++; + if (cell_clean_cnt==1000) { + clean_neighbours(); + cell_clean_cnt = 0; + } + } usleep(1000); } } @@ -363,16 +372,16 @@ void rrc::run_si_acquisition_procedure() break; case SI_ACQUIRE_SIB2: // Instruct MAC to look for next SIB - if(sysinfo_index < serving_cell->sib1.N_sched_info) { - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length]; + if(sysinfo_index < serving_cell->sib1ptr()->N_sched_info) { + si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; x = sysinfo_index*si_win_len; sf = x%10; offset = x/10; tti = mac->get_current_tti(); - period = liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[sysinfo_index].si_periodicity]; + period = liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[sysinfo_index].si_periodicity]; si_win_start = sib_start_tti(tti, period, offset, sf); - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length]; + si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; if (last_win_start == 0 || (srslte_tti_interval(last_win_start, tti) > period*10 && srslte_tti_interval(last_win_start, tti) < 1000)) @@ -416,17 +425,11 @@ void rrc::run_si_acquisition_procedure() *******************************************************************************/ uint16_t rrc::get_mcc() { - if (serving_cell->sib1.N_plmn_ids > 0) { - return serving_cell->sib1.plmn_id[0].id.mcc; - } - return 0; + return serving_cell->get_mcc(); } uint16_t rrc::get_mnc() { - if (serving_cell->sib1.N_plmn_ids > 0) { - return serving_cell->sib1.plmn_id[0].id.mnc; - } - return 0; + return serving_cell->get_mnc(); } void rrc::plmn_search() { @@ -491,7 +494,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) { // Move serving cell to neighbours list if (serving_cell->is_valid()) { // Make sure it does not exist already - int serving_idx = find_neighbour_cell(serving_cell->earfcn, serving_cell->phy_cell.id); + int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->phy_cell.id); if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { printf("Error serving cell is already in the neighbour list. Removing it\n"); neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); @@ -506,7 +509,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) { serving_cell = new_serving_cell; rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n", - cell_idx, serving_cell->earfcn, serving_cell->phy_cell.id, neighbour_cells.size()); + cell_idx, serving_cell->get_earfcn(), serving_cell->phy_cell.id, neighbour_cells.size()); } else { rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); @@ -520,19 +523,19 @@ void rrc::select_next_cell_in_plmn() { neighbour_cells[i]->in_sync) // matches S criteria { // Try to select Cell - if (phy->cell_select(neighbour_cells[i]->earfcn, neighbour_cells[i]->phy_cell)) { + if (phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell)) { set_serving_cell(i); rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", - serving_cell->phy_cell.id, serving_cell->earfcn, - serving_cell->sib1.cell_id); + serving_cell->phy_cell.id, serving_cell->get_earfcn(), + serving_cell->get_cell_id()); rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", - serving_cell->phy_cell.id, serving_cell->earfcn, - serving_cell->sib1.cell_id); + serving_cell->phy_cell.id, serving_cell->get_earfcn(), + serving_cell->get_cell_id()); } else { // Set to out-of-sync if can't synchronize neighbour_cells[i]->in_sync = false; rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n", - neighbour_cells[i]->earfcn, neighbour_cells[i]->sib1.cell_id); + neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->get_cell_id()); } return; } @@ -543,7 +546,7 @@ void rrc::select_next_cell_in_plmn() { void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { if (earfcn_i < 0 || pci_i < 0) { - earfcn_i = serving_cell->earfcn; + earfcn_i = serving_cell->get_earfcn(); pci_i = serving_cell->phy_cell.id; } @@ -560,7 +563,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p // Update serving cell if (serving_cell->equals(earfcn, pci)) { cell_reselection_eval(rsrp, rsrq); - serving_cell->rsrp = rsrp; + serving_cell->set_rsrp(rsrp); rrc_log->info("MEAS: New measurement serving cell in IDLE, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); // Or update/add neighbour cell @@ -573,13 +576,13 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p } // Verify cell selection criteria with strongest neighbour cell (always first) - if (cell_selection_eval(neighbour_cells[0]->rsrp) && - neighbour_cells[0]->rsrp > serving_cell->rsrp + 5) + if (cell_selection_eval(neighbour_cells[0]->get_rsrp()) && + neighbour_cells[0]->get_rsrp() > serving_cell->get_rsrp() + 5) { set_serving_cell(0); - rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->rsrp); + rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->get_rsrp()); state = RRC_STATE_CELL_SELECTING; - phy->cell_select(serving_cell->earfcn, serving_cell->phy_cell); + phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); } } } @@ -590,7 +593,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { int cell_idx = -1; if (serving_cell->equals(earfcn, phy_cell.id)) { - serving_cell->rsrp = rsrp; + serving_cell->set_rsrp(rsrp); serving_cell->in_sync = true; found = true; } else { @@ -598,18 +601,18 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { cell_idx = find_neighbour_cell(earfcn, phy_cell.id); if (cell_idx >= 0) { set_serving_cell(cell_idx); - serving_cell->rsrp = rsrp; + serving_cell->set_rsrp(rsrp); serving_cell->in_sync = true; found = true; } } if (found) { - if (!serving_cell->has_valid_sib1) { + if (!serving_cell->has_sib1()) { si_acquire_state = SI_ACQUIRE_SIB1; } else if (state == RRC_STATE_PLMN_SELECTION) { - for (uint32_t j = 0; j < serving_cell->sib1.N_plmn_ids; j++) { - nas->plmn_found(serving_cell->sib1.plmn_id[j].id, serving_cell->sib1.tracking_area_code); + for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) { + nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code); } usleep(5000); phy->cell_search_next(); @@ -631,22 +634,54 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", found?"Updating":"Adding", cell_idx>=0?"neighbour":"serving", - serving_cell->earfcn, + serving_cell->get_earfcn(), serving_cell->phy_cell.id, - serving_cell->rsrp); + serving_cell->get_rsrp()); } bool sort_rsrp(cell_t *u1, cell_t *u2) { - return !u1->greater(u2); + return u1->greater(u2); } -// Sort neighbour cells by decreasing order of RSRP -void rrc::sort_neighbour_cells() { +void rrc::delete_neighbour(uint32_t cell_idx) { + measurements.delete_report(neighbour_cells[cell_idx]->get_earfcn(), neighbour_cells[cell_idx]->get_pci()); + delete neighbour_cells[cell_idx]; + neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end()); +} - for (uint32_t i=1;iin_sync == false) { - rrc_log->info("Removing neighbour cell PCI=%d, out_of_sync\n", neighbour_cells[i]->phy_cell.id); - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[i]), neighbour_cells.end()); +std::vector::iterator rrc::delete_neighbour(std::vector::iterator it) { + measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci()); + delete (*it); + return neighbour_cells.erase(it); +} + +void rrc::clean_neighbours() +{ + struct timeval now; + gettimeofday(&now, NULL); + + std::vector::iterator it = neighbour_cells.begin(); + while(it != neighbour_cells.end()) { + if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) { + rrc_log->info("Neighbour PCI=%d timed out. Deleting\n", (*it)->get_pci()); + it = delete_neighbour(it); + } else { + ++it; + } + } +} + +// Sort neighbour cells by decreasing order of RSRP +void rrc::sort_neighbour_cells() +{ + // Remove out-of-sync cells + std::vector::iterator it = neighbour_cells.begin(); + while(it != neighbour_cells.end()) { + if ((*it)->in_sync == false) { + rrc_log->info("Neighbour PCI=%d is out-of-sync. Deleting\n", (*it)->get_pci()); + it = delete_neighbour(it); + } else { + ++it; } } @@ -654,28 +689,27 @@ void rrc::sort_neighbour_cells() { char ordered[512]; int n=0; - n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->rsrp); + n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp()); for (uint32_t i=1;iphy_cell.id, neighbour_cells[i]->rsrp); + n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp()); } - rrc_log->info("Sorted neighbour cells: %s]\n", ordered); + rrc_log->info("Neighbours: %s]\n", ordered); } bool rrc::add_neighbour_cell(cell_t *new_cell) { bool ret = false; - if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS - 1) { + if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) { ret = true; - } else if (!neighbour_cells[neighbour_cells.size()-1]->greater(new_cell)) { - // Delete old one - delete neighbour_cells[neighbour_cells.size()-1]; - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[neighbour_cells.size()-1]), neighbour_cells.end()); + } else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) { + // Replace old one by new one + delete_neighbour(neighbour_cells.size()-1); ret = true; } if (ret) { neighbour_cells.push_back(new_cell); } rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d\n", - new_cell->earfcn, new_cell->phy_cell.id, neighbour_cells.size()); + new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size()); sort_neighbour_cells(); return ret; } @@ -690,7 +724,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { if (earfcn == 0) { - earfcn = serving_cell->earfcn; + earfcn = serving_cell->get_earfcn(); } // First check if already exists @@ -700,7 +734,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp // If exists, update RSRP, sort again and return if (cell_idx >= 0) { - neighbour_cells[cell_idx]->rsrp = rsrp; + neighbour_cells[cell_idx]->set_rsrp(rsrp); sort_neighbour_cells(); return true; } @@ -929,7 +963,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint8_t *msg_ptr = varShortMAC; // ASN.1 encode byte-aligned VarShortMAC-Input - liblte_rrc_pack_cell_identity_ie(serving_cell->sib1.cell_id, &msg_ptr); + liblte_rrc_pack_cell_identity_ie(serving_cell->get_cell_id(), &msg_ptr); msg_ptr = &varShortMAC[4]; liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr); msg_ptr = &varShortMAC[4+2]; @@ -937,7 +971,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, (4+2+4)*8); rrc_log->info("Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d\n", - serving_cell->sib1.cell_id, phy->get_current_pci(), crnti); + serving_cell->get_cell_id(), phy->get_current_pci(), crnti); // Compute MAC-I uint8_t mac_key[4]; @@ -1065,10 +1099,10 @@ bool rrc::ho_prepare() { if (pending_mob_reconf) { rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci); - int target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci); + int target_cell_idx = find_neighbour_cell(serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci); if (target_cell_idx < 0) { rrc_log->console("Received HO command to unknown PCI=%d\n", mob_reconf.mob_ctrl_info.target_pci); - rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci); + rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci); return false; } @@ -1076,7 +1110,7 @@ bool rrc::ho_prepare() { mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present && - mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->earfcn) { + mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->get_earfcn()) { rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); } @@ -1099,9 +1133,9 @@ bool rrc::ho_prepare() { mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->phy_cell.id); + rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci()); if (!phy->cell_handover(neighbour_cells[target_cell_idx]->phy_cell)) { - rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->phy_cell.id); + rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci()); return false; } @@ -1177,7 +1211,7 @@ void rrc::ho_failed() { // Instruct PHY to resync with source PCI if (!phy->cell_handover(ho_src_cell.phy_cell)) { - rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.phy_cell.id); + rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.get_pci()); return; } @@ -1302,27 +1336,23 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { rrc_log->info("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { - memcpy(&serving_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); - serving_cell->has_valid_sib1 = true; + serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1); handle_sib1(); - } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib2) { - memcpy(&serving_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); - serving_cell->has_valid_sib2 = true; + } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) { + serving_cell->set_sib2(&dlsch_msg.sibs[i].sib.sib2); handle_sib2(); - } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib3) { - memcpy(&serving_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); - serving_cell->has_valid_sib3 = true; + } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib3()) { + serving_cell->set_sib3(&dlsch_msg.sibs[i].sib.sib3); handle_sib3(); - }else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib13) { - memcpy(&serving_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); - serving_cell->has_valid_sib13 = true; + }else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib13()) { + serving_cell->set_sib13(&dlsch_msg.sibs[i].sib.sib13); handle_sib13(); } } last_win_start = 0; - if(serving_cell->has_valid_sib2) { + if(serving_cell->has_sib2()) { sysinfo_index++; } } @@ -1330,16 +1360,16 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { void rrc::handle_sib1() { rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", - serving_cell->sib1.cell_id&0xfff, - liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length], - liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[0].si_periodicity]); + serving_cell->get_cell_id()&0xfff, + liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length], + liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[0].si_periodicity]); // Print SIB scheduling info uint32_t i,j; - for(i=0;isib1.N_sched_info;i++){ - for(j=0;jsib1.sched_info[i].N_sib_mapping_info;j++){ - LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type; - LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1.sched_info[i].si_periodicity; + for(i=0;isib1ptr()->N_sched_info;i++){ + for(j=0;jsib1ptr()->sched_info[i].N_sib_mapping_info;j++){ + LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1ptr()->sched_info[i].sib_mapping_info[j].sib_type; + LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1ptr()->sched_info[i].si_periodicity; rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n", liblte_rrc_sib_type_num[t], liblte_rrc_si_periodicity_num[p]); @@ -1347,16 +1377,14 @@ void rrc::handle_sib1() } // Set TDD Config - if(serving_cell->sib1.tdd) { - phy->set_config_tdd(&serving_cell->sib1.tdd_cnfg); + if(serving_cell->sib1ptr()->tdd) { + phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg); } - serving_cell->has_valid_sib1 = true; - // Send PLMN and TAC to NAS std::stringstream ss; - for (uint32_t i = 0; i < serving_cell->sib1.N_plmn_ids; i++) { - nas->plmn_found(serving_cell->sib1.plmn_id[i].id, serving_cell->sib1.tracking_area_code); + for (uint32_t i = 0; i < serving_cell->sib1ptr()->N_plmn_ids; i++) { + nas->plmn_found(serving_cell->sib1ptr()->plmn_id[i].id, serving_cell->sib1ptr()->tracking_area_code); } // Jump to next state @@ -1379,7 +1407,7 @@ void rrc::handle_sib2() { rrc_log->info("SIB2 received\n"); - apply_sib2_configs(&serving_cell->sib2); + apply_sib2_configs(serving_cell->sib2ptr()); } @@ -1387,7 +1415,7 @@ void rrc::handle_sib3() { rrc_log->info("SIB3 received\n"); - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &serving_cell->sib3; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = serving_cell->sib3ptr(); // cellReselectionInfoCommon cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst]; @@ -1699,7 +1727,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { * *******************************************************************************/ void rrc::enable_capabilities() { - bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam; + bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2ptr()->rr_config_common_sib.pusch_cnfg.enable_64_qam; rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling"); phy->set_config_64qam_en(enable_ul_64); } @@ -2373,28 +2401,45 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa L3_filter(&pcell_measurement, values); // Update serving cell measurement - parent->serving_cell->rsrp = rsrp; + parent->serving_cell->set_rsrp(rsrp); } else { // Add to list of neighbour cells - parent->add_neighbour_cell(earfcn, pci, rsrp); - - log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti); - - // Save PHY measurement for all active measurements whose earfcn/pci matches - for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { - meas_t *m = &iter->second; - if (objects[m->object_id].earfcn == earfcn) { - // If it's a newly discovered cell, add it to objects - if (!m->cell_values.count(pci)) { - uint32_t cell_idx = objects[m->object_id].cells.size(); - objects[m->object_id].cells[cell_idx].pci = pci; - objects[m->object_id].cells[cell_idx].q_offset = 0; + bool added = parent->add_neighbour_cell(earfcn, pci, rsrp); + + log_h->info("MEAS: New measurement %s earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", + added?"added":"not added", earfcn, pci, rsrp, rsrq, tti); + + // Only report measurements of 8th strongest cells + if (added) { + // Save PHY measurement for all active measurements whose earfcn/pci matches + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t *m = &iter->second; + if (objects[m->object_id].earfcn == earfcn) { + // If it's a newly discovered cell, add it to objects + if (!m->cell_values.count(pci)) { + uint32_t cell_idx = objects[m->object_id].cells.size(); + objects[m->object_id].cells[cell_idx].pci = pci; + objects[m->object_id].cells[cell_idx].q_offset = 0; + } + // Update or add cell + L3_filter(&m->cell_values[pci], values); + return; } - // Update or add cell - L3_filter(&m->cell_values[pci], values); - return; + } + } + } +} + +// Remove all stored measurements for a given cell +void rrc::rrc_meas::delete_report(uint32_t earfcn, uint32_t pci) { + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t *m = &iter->second; + if (objects[m->object_id].earfcn == earfcn) { + if (m->cell_values.count(pci)) { + m->cell_values.erase(pci); + log_h->info("Deleting report PCI=%d from cell_values\n", pci); } } }