Changed logic in RRC/NAS/PHY for cell/plmn search to avoid stucking in IDLE

master
Ismael Gomez 7 years ago
parent 5a8454f5a8
commit 13efa740e8

@ -119,7 +119,7 @@ public:
virtual uint32_t get_ul_count() = 0; virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
virtual bool get_k_asme(uint8_t *k_asme_, uint32_t n) = 0; virtual bool get_k_asme(uint8_t *k_asme_, uint32_t n) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0; virtual bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
virtual void plmn_search_end() = 0; virtual void plmn_search_end() = 0;
}; };
@ -173,7 +173,7 @@ public:
virtual uint16_t get_mnc() = 0; virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0; virtual void enable_capabilities() = 0;
virtual void plmn_search() = 0; virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request = false) = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0; virtual std::string get_rb_name(uint32_t lcid) = 0;
}; };

@ -150,7 +150,7 @@ private:
srslte_ue_mib_t ue_mib; srslte_ue_mib_t ue_mib;
uint32_t cnt; uint32_t cnt;
uint32_t timeout; uint32_t timeout;
const static uint32_t SYNC_SFN_TIMEOUT = 500; const static uint32_t SYNC_SFN_TIMEOUT = 80;
}; };
// Class to perform cell measurements // Class to perform cell measurements

@ -88,9 +88,10 @@ public:
uint32_t get_ul_count(); uint32_t get_ul_count();
bool is_attached(); bool is_attached();
bool is_attaching(); bool is_attaching();
bool is_data_requested();
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);
bool get_k_asme(uint8_t *k_asme_, uint32_t n); bool get_k_asme(uint8_t *k_asme_, uint32_t n);
void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code);
void plmn_search_end(); void plmn_search_end();
// UE interface // UE interface

@ -249,7 +249,7 @@ public:
void enable_capabilities(); void enable_capabilities();
void plmn_search(); void plmn_search();
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request);
// PHY interface // PHY interface
void in_sync(); void in_sync();
@ -324,9 +324,6 @@ private:
uint32_t plmn_select_timeout; uint32_t plmn_select_timeout;
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000; static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;
uint32_t select_cell_timeout;
static const uint32_t RRC_SELECT_CELL_TIMEOUT = 1000;
uint8_t k_rrc_enc[32]; uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32]; uint8_t k_rrc_int[32];
uint8_t k_up_enc[32]; uint8_t k_up_enc[32];
@ -401,7 +398,7 @@ private:
uint16_t sysinfo_index; uint16_t sysinfo_index;
uint32_t last_win_start; uint32_t last_win_start;
void select_next_cell_in_plmn(); bool select_next_cell_in_plmn();
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id; LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id;
bool thread_running; bool thread_running;

@ -565,8 +565,8 @@ void phch_recv::run_thread()
} }
break; break;
case sfn_sync::TIMEOUT: case sfn_sync::TIMEOUT:
log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n"); log_h->warning("SYNC: Timeout while synchronizing SFN\n");
phy_state = CELL_SEARCH; rrc->out_of_sync();
break; break;
case sfn_sync::IDLE: case sfn_sync::IDLE:
break; break;
@ -1271,7 +1271,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
for (uint32_t sf5_cnt=0;sf5_cnt<nof_sf/5;sf5_cnt++) { for (uint32_t sf5_cnt=0;sf5_cnt<nof_sf/5;sf5_cnt++) {
sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx); sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx);
Info("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f\n", Debug("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f\n",
n_id_2, sf5_cnt, nof_sf/5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, sync_find.peak_value); n_id_2, sf5_cnt, nof_sf/5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, sync_find.peak_value);
if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) { if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) {

@ -529,7 +529,9 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10, if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10,
dl_rnti, type, &dci_msg) != 1) { dl_rnti, type, &dci_msg) != 1) {
if (type == SRSLTE_RNTI_RAR) { if (type == SRSLTE_RNTI_RAR) {
Info("RAR not found, SNR=%.1f dB\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))); Info("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), tti, cfi,
phy->config->dedicated.antenna_info_explicit_value.tx_mode, cell.id);
} }
return false; return false;
} }

@ -107,8 +107,8 @@ void nas::attach_request() {
selecting_plmn = current_plmn; selecting_plmn = current_plmn;
} }
} else if (state == EMM_STATE_REGISTERED) { } else if (state == EMM_STATE_REGISTERED) {
nas_log->info("NAS state is registered, connecting to same PLMN\n"); nas_log->info("NAS state is registered, selecting current PLMN\n");
rrc->plmn_select(current_plmn); rrc->plmn_select(current_plmn, true);
} else { } else {
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
} }
@ -123,12 +123,7 @@ void nas::deattach_request() {
* RRC interface * RRC interface
******************************************************************************/ ******************************************************************************/
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { bool nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
// Do not process new PLMN if already selected
if (plmn_selection == PLMN_SELECTED) {
return;
}
// Check if already registered // Check if already registered
for (uint32_t i=0;i<known_plmns.size();i++) { for (uint32_t i=0;i<known_plmns.size();i++) {
@ -136,10 +131,11 @@ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_
nas_log->info("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); nas_log->info("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
rrc->plmn_select(plmn_id); rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED);
selecting_plmn = plmn_id; selecting_plmn = plmn_id;
return true;
} }
return; return false;
} }
} }
@ -152,10 +148,11 @@ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_
tracking_area_code); tracking_area_code);
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
rrc->plmn_select(plmn_id); rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED);
selecting_plmn = plmn_id; selecting_plmn = plmn_id;
return true;
} }
return false;
} }
// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection // RRC indicates that the UE has gone through all EARFCN and finished PLMN selection
@ -170,7 +167,7 @@ void nas::plmn_search_end() {
plmn_id_to_string(home_plmn).c_str(), plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str()); plmn_id_to_string(known_plmns[0]).c_str());
} }
rrc->plmn_select(known_plmns[0]); rrc->plmn_select(known_plmns[0], state == EMM_STATE_REGISTERED_INITIATED);
} else { } else {
nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n"); nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n");
if (state == EMM_STATE_REGISTERED_INITIATED && plmn_selection == PLMN_NOT_SELECTED) { if (state == EMM_STATE_REGISTERED_INITIATED && plmn_selection == PLMN_NOT_SELECTED) {
@ -538,6 +535,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
state = EMM_STATE_REGISTERED; state = EMM_STATE_REGISTERED;
current_plmn = selecting_plmn; current_plmn = selecting_plmn;
plmn_selection = PLMN_SELECTED;
ctxt.rx_count++; ctxt.rx_count++;

@ -126,6 +126,8 @@ void rrc::init(phy_interface_rrc *phy_,
pending_mob_reconf = false; pending_mob_reconf = false;
connection_requested = false;
// Set default values for all layers // Set default values for all layers
set_rrc_default(); set_rrc_default();
set_phy_default(); set_phy_default();
@ -184,10 +186,8 @@ void rrc::run_thread() {
if (phy->sync_status()) { if (phy->sync_status()) {
// If attempting to attach, reselect cell // If attempting to attach, reselect cell
if (nas->is_attaching()) { if (nas->is_attaching()) {
sleep(1); rrc_log->info("RRC IDLE: NAS has pending data and camping on cell, connecting...\n");
rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n");
plmn_select_rrc(selected_plmn_id); plmn_select_rrc(selected_plmn_id);
connection_requested = true;
} }
// If not camping on a cell // If not camping on a cell
} else { } else {
@ -196,7 +196,6 @@ void rrc::run_thread() {
rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n"); rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n");
plmn_select_rrc(selected_plmn_id); plmn_select_rrc(selected_plmn_id);
} else if (nas->is_attaching()) { } else if (nas->is_attaching()) {
sleep(1);
rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n"); rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n");
plmn_search(); plmn_search();
} }
@ -234,16 +233,6 @@ void rrc::run_thread() {
state = RRC_STATE_CELL_SELECTED; state = RRC_STATE_CELL_SELECTED;
} }
} }
// Don't time out during reestablishment (T311 running)
if (!mac_timers->timer_get(t311)->is_running() || !phy->sync_status()) {
select_cell_timeout++;
if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) {
rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n");
select_cell_timeout = 0;
state = RRC_STATE_PLMN_START;
serving_cell->in_sync = false;
}
}
break; break;
case RRC_STATE_CELL_SELECTED: case RRC_STATE_CELL_SELECTED:
@ -258,9 +247,9 @@ void rrc::run_thread() {
con_restablish_cell_reselected(); con_restablish_cell_reselected();
state = RRC_STATE_CONNECTING; state = RRC_STATE_CONNECTING;
connecting_timeout = 0; connecting_timeout = 0;
} else if (connection_requested) { } else if (nas->is_attaching() || connection_requested) {
connection_requested = false;
rrc_log->info("RRC Cell Selected: Sending connection request...\n"); rrc_log->info("RRC Cell Selected: Sending connection request...\n");
connection_requested = false;
send_con_request(); send_con_request();
state = RRC_STATE_CONNECTING; state = RRC_STATE_CONNECTING;
connecting_timeout = 0; connecting_timeout = 0;
@ -442,8 +431,8 @@ void rrc::plmn_search() {
/* This is the NAS interface. When NAS requests to select a PLMN we have to /* This is the NAS interface. When NAS requests to select a PLMN we have to
* connect to either register or because there is pending higher layer traffic. * connect to either register or because there is pending higher layer traffic.
*/ */
void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request) {
connection_requested = true; connection_requested = connect_request;
plmn_select_rrc(plmn_id); plmn_select_rrc(plmn_id);
} }
@ -451,37 +440,41 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
* selected PLMN * selected PLMN
*/ */
void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
pthread_mutex_lock(&mutex);
// If already camping on the selected PLMN, select this cell // If already camping on the selected PLMN, select this cell
if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) { if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) {
if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) { if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) {
rrc_log->info("Already camping on selected PLMN, connecting...\n"); rrc_log->info("Already camping on selected PLMN\n");
} else { } else {
selected_plmn_id = plmn_id; selected_plmn_id = plmn_id;
if (serving_cell->plmn_equals(selected_plmn_id)) { if (serving_cell->plmn_equals(selected_plmn_id) && serving_cell->in_sync) {
phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); rrc_log->info("PLMN Id=%s selected, Selecting serving cell earfcn=%d, pci=%d\n",
plmn_id_to_string(plmn_id).c_str(), serving_cell->get_earfcn(), serving_cell->phy_cell.id);
} else { } else {
bool found = false; bool found = false;
for (uint32_t i=0;i<neighbour_cells.size() && !found;i++) { for (uint32_t i=0;i<neighbour_cells.size() && !found;i++) {
if (neighbour_cells[i]->plmn_equals(selected_plmn_id)) { if (neighbour_cells[i]->plmn_equals(selected_plmn_id)) {
rrc_log->info("PLMN Id=%s selected, PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci()); rrc_log->info("PLMN Id=%s selected, Selecting neighbour cell PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci());
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell); phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
found = true; found = true;
} }
} }
if (!found) { if (!found) {
rrc_log->warning("Could not find any cell for the selected PLMN\n"); rrc_log->warning("Could not find any cell for the selected PLMN. Searching another PLMN\n");
state = RRC_STATE_IDLE; plmn_search();
pthread_mutex_unlock(&mutex);
return; return;
} }
} }
} }
state = RRC_STATE_CELL_SELECTING; state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} else { } else {
rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]); rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]);
} }
pthread_mutex_unlock(&mutex);
} }
void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) { void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) {
@ -494,6 +487,7 @@ void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) {
} }
void rrc::set_serving_cell(uint32_t cell_idx) { void rrc::set_serving_cell(uint32_t cell_idx) {
if (cell_idx < neighbour_cells.size()) if (cell_idx < neighbour_cells.size())
{ {
// Remove future serving cell from neighbours to make space for current serving cell // Remove future serving cell from neighbours to make space for current serving cell
@ -529,29 +523,37 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
} }
} }
void rrc::select_next_cell_in_plmn() { bool rrc::select_next_cell_in_plmn() {
// Neighbour cells are sorted in descending order of RSRP // Neighbour cells are sorted in descending order of RSRP
for (uint32_t i = 0; i < neighbour_cells.size(); i++) { for (uint32_t i = 0; i < neighbour_cells.size(); i++) {
if (neighbour_cells[i]->plmn_equals(selected_plmn_id) && if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells
* neighbour_cells[i]->plmn_equals(selected_plmn_id) && */
neighbour_cells[i]->in_sync) // matches S criteria neighbour_cells[i]->in_sync) // matches S criteria
{
// If currently connected, verify cell selection criteria
if (!serving_cell->in_sync ||
(cell_selection_eval(neighbour_cells[i]->get_rsrp()) &&
neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5))
{ {
// Try to select Cell // Try to select Cell
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
set_serving_cell(i); set_serving_cell(i);
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", rrc_log->info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n",
serving_cell->phy_cell.id, serving_cell->get_earfcn(), i, serving_cell->phy_cell.id, serving_cell->get_earfcn());
serving_cell->get_cell_id()); rrc_log->console("Selected cell PCI=%d, EARFCN=%d\n",
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", serving_cell->phy_cell.id, serving_cell->get_earfcn());
serving_cell->phy_cell.id, serving_cell->get_earfcn(), phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
serving_cell->get_cell_id()); state = RRC_STATE_CELL_SELECTING;
return; return true;
} }
} }
rrc_log->info("No more known cells. Starting again\n"); }
return false;
} }
void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) {
pthread_mutex_lock(&mutex);
if (earfcn_i < 0 || pci_i < 0) { if (earfcn_i < 0 || pci_i < 0) {
earfcn_i = serving_cell->get_earfcn(); earfcn_i = serving_cell->get_earfcn();
pci_i = serving_cell->phy_cell.id; pci_i = serving_cell->phy_cell.id;
@ -582,16 +584,22 @@ 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) // Evaluate if we need to select a new cell
if (neighbour_cells.size() > 1 && select_next_cell_in_plmn();
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->get_rsrp());
state = RRC_STATE_CELL_SELECTING;
phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
} }
pthread_mutex_unlock(&mutex);
}
// PHY indicates that has gone through all known EARFCN
void rrc::earfcn_end() {
rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]);
// If searching for PLMN, indicate NAS we scanned all frequencies
if (state == RRC_STATE_PLMN_SELECTION) {
nas->plmn_search_end();
} else {
rrc_log->info("Restarting Cell search...\n");
phy->cell_search_start();
} }
} }
@ -600,51 +608,53 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
* new cell as current serving cell */ * new cell as current serving cell */
void rrc::cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { void rrc::cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
bool found = false;
int cell_idx = -1; int cell_idx = -1;
bool found = true;
pthread_mutex_lock(&mutex);
if (serving_cell->equals(earfcn, phy_cell.id)) { if (serving_cell->equals(earfcn, phy_cell.id)) {
serving_cell->set_rsrp(rsrp); serving_cell->set_rsrp(rsrp);
found = true;
} else { } else {
// Check if cell is in our list of neighbour cells // Check if cell is in our list of neighbour cells
cell_idx = find_neighbour_cell(earfcn, phy_cell.id); cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
if (cell_idx >= 0) { if (cell_idx >= 0) {
set_serving_cell(cell_idx); set_serving_cell(cell_idx);
serving_cell->set_rsrp(rsrp); serving_cell->set_rsrp(rsrp);
found = true; } else {
found = false;
if (!add_neighbour_cell(earfcn, phy_cell, rsrp)) {
rrc_log->info(
"No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours)\n",
rsrp,
NOF_NEIGHBOUR_CELLS);
} else {
set_serving_cell(earfcn, phy_cell.id);
serving_cell->set_rsrp(rsrp);
} }
} }
if (found) { }
pthread_mutex_unlock(&mutex);
if (!serving_cell->has_sib1()) { if (!serving_cell->has_sib1()) {
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
} else if (state == RRC_STATE_PLMN_SELECTION) { } else if (state == RRC_STATE_PLMN_SELECTION) {
bool ret = false;
for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) { 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); ret |= nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code);
} }
usleep(5000); // If any of the PLMNs in this cell is selected, search next cell
if (!ret) {
phy->cell_search_next(); phy->cell_search_next();
} }
} else {
// add to list of known cells and set current_cell
if (!add_neighbour_cell(earfcn, phy_cell, rsrp)) {
rrc_log->info("No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours)\n",
rsrp, NOF_NEIGHBOUR_CELLS);
usleep(5000);
phy->cell_search_next();
} else {
set_serving_cell(earfcn, phy_cell.id);
si_acquire_state = SI_ACQUIRE_SIB1;
}
} }
rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n",
found?"Updating":"Adding", found?"Updating":"Adding",
cell_idx>=0?"neighbour":"serving", cell_idx>=0?"neighbour":"serving", earfcn, phy_cell.id, rsrp);
serving_cell->get_earfcn(),
serving_cell->phy_cell.id,
serving_cell->get_rsrp());
} }
bool sort_rsrp(cell_t *u1, cell_t *u2) { bool sort_rsrp(cell_t *u1, cell_t *u2) {
@ -668,6 +678,8 @@ void rrc::clean_neighbours()
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
pthread_mutex_lock(&mutex);
std::vector<cell_t*>::iterator it = neighbour_cells.begin(); std::vector<cell_t*>::iterator it = neighbour_cells.begin();
while(it != neighbour_cells.end()) { while(it != neighbour_cells.end()) {
if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) { if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) {
@ -677,6 +689,7 @@ void rrc::clean_neighbours()
++it; ++it;
} }
} }
pthread_mutex_unlock(&mutex);
} }
// Sort neighbour cells by decreasing order of RSRP // Sort neighbour cells by decreasing order of RSRP
@ -695,6 +708,7 @@ void rrc::sort_neighbour_cells()
std::sort(neighbour_cells.begin(), neighbour_cells.end(), sort_rsrp); std::sort(neighbour_cells.begin(), neighbour_cells.end(), sort_rsrp);
if (neighbour_cells.size() > 0) {
char ordered[512]; char ordered[512];
int n=0; int n=0;
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp()); n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp());
@ -702,6 +716,9 @@ void rrc::sort_neighbour_cells()
n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp()); n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp());
} }
rrc_log->info("Neighbours: %s]\n", ordered); rrc_log->info("Neighbours: %s]\n", ordered);
} else {
rrc_log->info("Neighbours: Empty\n");
}
} }
bool rrc::add_neighbour_cell(cell_t *new_cell) { bool rrc::add_neighbour_cell(cell_t *new_cell) {
@ -762,18 +779,6 @@ int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) {
return -1; return -1;
} }
// PHY indicates that has gone through all known EARFCN
void rrc::earfcn_end() {
rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]);
// If searching for PLMN, indicate NAS we scanned all frequencies
if (state >= RRC_STATE_PLMN_SELECTION && state < RRC_STATE_CONNECTING) {
nas->plmn_search_end();
} else if (state >= RRC_STATE_CONNECTING && state < RRC_STATE_LEAVE_CONNECTED) {
leave_connected();
}
}
// Cell reselection in IDLE Section 5.2.4 of 36.304 // Cell reselection in IDLE Section 5.2.4 of 36.304
void rrc::cell_reselection_eval(float rsrp, float rsrq) void rrc::cell_reselection_eval(float rsrp, float rsrq)
{ {
@ -826,7 +831,6 @@ float rrc::get_squal(float Qqualmeas) {
// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1) // Detection of physical layer problems in RRC_CONNECTED (5.3.11.1)
void rrc::out_of_sync() { void rrc::out_of_sync() {
serving_cell->in_sync = false;
if (state == RRC_STATE_CONNECTED) { if (state == RRC_STATE_CONNECTED) {
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
n310_cnt++; n310_cnt++;
@ -838,10 +842,24 @@ void rrc::out_of_sync() {
n310_cnt = 0; n310_cnt = 0;
} }
} }
} else { } else if (state != RRC_STATE_LEAVE_CONNECTED) {
if (!mac_timers->timer_get(t311)->is_running()) {
if (serving_cell->in_sync) {
rrc_log->info("Detected out-of-sync while in IDLE. Resetting sync\n");
phy->sync_reset(); phy->sync_reset();
} else {
rrc_log->info("Detected out-of-sync while in IDLE. Selecting another cell in the PLMN\n");
if (!select_next_cell_in_plmn()) {
rrc_log->info("Could not find any available cell in this PLMN. Searching PLMN again.\n");
plmn_search();
} }
} }
} else {
rrc_log->info("Detected out-of-sync while T311 is running\n");
}
}
serving_cell->in_sync = false;
}
// Recovery of physical layer problems (5.3.11.2) // Recovery of physical layer problems (5.3.11.2)
void rrc::in_sync() { void rrc::in_sync() {

@ -81,7 +81,7 @@ public:
uint32_t get_last_sdu_len() { return last_sdu_len; } uint32_t get_last_sdu_len() { return last_sdu_len; }
void plmn_search() {}; void plmn_search() {};
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {}; void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool con_req) {};
uint16_t get_mcc() { return mcc; } uint16_t get_mcc() { return mcc; }
uint16_t get_mnc() { return mnc; } uint16_t get_mnc() { return mnc; }

Loading…
Cancel
Save