@ -98,6 +98,9 @@ void rrc::init(phy_interface_rrc *phy_,
mac_timers = mac_timers_ ;
state = RRC_STATE_IDLE ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
ho_syncing = false ;
thread_running = true ;
start ( ) ;
@ -111,6 +114,7 @@ void rrc::init(phy_interface_rrc *phy_,
args . nof_supported_bands = 1 ;
args . feature_group = 0xe6041c00 ;
t300 = mac_timers - > timer_get_unique_id ( ) ;
t301 = mac_timers - > timer_get_unique_id ( ) ;
t310 = mac_timers - > timer_get_unique_id ( ) ;
t311 = mac_timers - > timer_get_unique_id ( ) ;
@ -126,6 +130,8 @@ void rrc::init(phy_interface_rrc *phy_,
pending_mob_reconf = false ;
connection_requested = false ;
// Set default values for all layers
set_rrc_default ( ) ;
set_phy_default ( ) ;
@ -150,7 +156,7 @@ rrc_state_t rrc::get_state() {
}
bool rrc : : is_connected ( ) {
return ( RRC_STATE_CONNECTED = = state ) ;
return ( state > = RRC_STATE_CONNECTED & & state < RRC_STATE_LEAVE_CONNECTED ) ;
}
bool rrc : : have_drb ( ) {
@ -173,10 +179,6 @@ void rrc::run_thread() {
while ( thread_running ) {
if ( state > = RRC_STATE_IDLE & & state < RRC_STATE_CONNECTING ) {
run_si_acquisition_procedure ( ) ;
}
switch ( state ) {
/* Procedures in IDLE state 36.304 Sec 4 */
case RRC_STATE_IDLE :
@ -184,10 +186,8 @@ void rrc::run_thread() {
if ( phy - > sync_status ( ) ) {
// If attempting to attach, reselect cell
if ( nas - > is_attaching ( ) ) {
sleep ( 1 ) ;
rrc_log - > info ( " RRC IDLE: NAS is attaching and camping on cell, reselecting... \n " ) ;
rrc_log - > info ( " RRC IDLE: NAS has pending data and camping on cell, connecting... \n " ) ;
plmn_select_rrc ( selected_plmn_id ) ;
connection_requested = true ;
}
// If not camping on a cell
} else {
@ -196,7 +196,6 @@ void rrc::run_thread() {
rrc_log - > info ( " RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell... \n " ) ;
plmn_select_rrc ( selected_plmn_id ) ;
} else if ( nas - > is_attaching ( ) ) {
sleep ( 1 ) ;
rrc_log - > info ( " RRC IDLE: NAS is attaching, searching again PLMN \n " ) ;
plmn_search ( ) ;
}
@ -230,23 +229,16 @@ void rrc::run_thread() {
si_acquire_state = SI_ACQUIRE_SIB2 ;
} else {
apply_sib2_configs ( serving_cell - > sib2ptr ( ) ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
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 ;
}
run_si_acquisition_procedure ( ) ;
}
break ;
case RRC_STATE_CELL_SELECTED :
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
/* The cell is selected when the SIBs are received and applied.
* If we were in RRC_CONNECTED and arrive here it means a RLF occurred and we are in Reestablishment procedure .
* If T311 is running means there is a reestablishment in progress , send ConnectionReestablishmentRequest .
@ -258,9 +250,9 @@ void rrc::run_thread() {
con_restablish_cell_reselected ( ) ;
state = RRC_STATE_CONNECTING ;
connecting_timeout = 0 ;
} else if ( connection_requested ) {
connection_requested = false ;
} else if ( nas - > is_attaching ( ) | | connection_requested ) {
rrc_log - > info ( " RRC Cell Selected: Sending connection request... \n " ) ;
connection_requested = false ;
send_con_request ( ) ;
state = RRC_STATE_CONNECTING ;
connecting_timeout = 0 ;
@ -275,6 +267,8 @@ void rrc::run_thread() {
if ( connecting_timeout > = RRC_CONNECTING_TIMEOUT ) {
// Select another cell
rrc_log - > info ( " RRC Connecting: timeout expired. Selecting next cell \n " ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
state = RRC_STATE_CELL_SELECTING ;
}
break ;
@ -366,6 +360,7 @@ void rrc::run_si_acquisition_procedure()
if ( state = = RRC_STATE_CELL_SELECTING ) {
select_next_cell_in_plmn ( ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
} else if ( state = = RRC_STATE_PLMN_SELECTION ) {
phy - > cell_search_next ( ) ;
}
@ -392,13 +387,14 @@ void rrc::run_si_acquisition_procedure()
last_win_start = si_win_start ;
mac - > bcch_start_rx ( si_win_start , si_win_len ) ;
rrc_log - > debug ( " Instructed MAC to search for system info , win_start=%d, win_len=%d\n " ,
si_win_start , si_win_len ) ;
rrc_log - > info ( " Instructed MAC to search for system info =%d , win_start=%d, win_len=%d\n " ,
sysinfo_index , si_win_start , si_win_len ) ;
}
} else {
// We've received all SIBs, move on to connection request
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
state = RRC_STATE_CELL_SELECTED ;
}
break ;
@ -442,8 +438,8 @@ void rrc::plmn_search() {
/* 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 .
*/
void rrc : : plmn_select ( LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id ) {
connection_requested = true ;
void rrc : : plmn_select ( LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id , bool connect_request ) {
connection_requested = connect_request ;
plmn_select_rrc ( plmn_id ) ;
}
@ -451,37 +447,47 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
* selected PLMN
*/
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 ( 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 ) {
rrc_log - > info ( " Already camping on selected PLMN , connecting... \n " ) ;
rrc_log - > info ( " Already camping on selected PLMN \n " ) ;
} else {
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 ) {
rrc_log - > info ( " PLMN Id=%s selected, Selecting serving cell earfcn=%d, pci=%d, status=%d \n " ,
plmn_id_to_string ( plmn_id ) . c_str ( ) , serving_cell - > get_earfcn ( ) , serving_cell - > phy_cell . id ,
phy - > sync_status ( ) ) ;
if ( ! phy - > sync_status ( ) ) {
phy - > cell_select ( serving_cell - > get_earfcn ( ) , serving_cell - > phy_cell ) ;
}
} else {
bool found = false ;
for ( uint32_t i = 0 ; i < neighbour_cells . size ( ) & & ! found ; i + + ) {
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 ) ;
found = true ;
}
}
if ( ! found ) {
rrc_log - > warning ( " Could not find any cell for the selected PLMN \n " ) ;
state = RRC_STATE_IDLE ;
rrc_log - > warning ( " Could not find any cell for the selected PLMN. Searching another PLMN \n " ) ;
plmn_search ( ) ;
pthread_mutex_unlock ( & mutex ) ;
return ;
}
}
}
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
state = RRC_STATE_CELL_SELECTING ;
select_cell_timeout = 0 ;
} else {
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 ) {
@ -494,6 +500,7 @@ void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) {
}
void rrc : : set_serving_cell ( uint32_t cell_idx ) {
if ( cell_idx < neighbour_cells . size ( ) )
{
// Remove future serving cell from neighbours to make space for current serving cell
@ -529,29 +536,39 @@ 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
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
{
// 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
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 - > 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 - > get_earfcn ( ) ,
serving_cell - > get_cell_id ( ) ) ;
return ;
rrc_log - > info ( " Selected cell idx=%d, PCI=%d, EARFCN=%d \n " ,
i , serving_cell - > phy_cell . id , serving_cell - > get_earfcn ( ) ) ;
rrc_log - > console ( " Selected cell PCI=%d, EARFCN=%d \n " ,
serving_cell - > phy_cell . id , serving_cell - > get_earfcn ( ) ) ;
phy - > cell_select ( serving_cell - > get_earfcn ( ) , serving_cell - > phy_cell ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
state = RRC_STATE_CELL_SELECTING ;
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 ) {
pthread_mutex_lock ( & mutex ) ;
if ( earfcn_i < 0 | | pci_i < 0 ) {
earfcn_i = serving_cell - > get_earfcn ( ) ;
pci_i = serving_cell - > phy_cell . id ;
@ -582,16 +599,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)
if ( neighbour_cells . size ( ) > 1 & &
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 ) ;
// Evaluate if we need to select a new cell
select_next_cell_in_plmn ( ) ;
}
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 +623,56 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
* new cell as current serving cell */
void rrc : : cell_camping ( uint32_t earfcn , srslte_cell_t phy_cell , float rsrp ) {
bool found = false ;
int cell_idx = - 1 ;
bool found = true ;
pthread_mutex_lock ( & mutex ) ;
if ( serving_cell - > equals ( earfcn , phy_cell . id ) ) {
serving_cell - > set_rsrp ( rsrp ) ;
found = true ;
} else {
// Check if cell is in our list of neighbour cells
cell_idx = find_neighbour_cell ( earfcn , phy_cell . id ) ;
if ( cell_idx > = 0 ) {
set_serving_cell ( cell_idx ) ;
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 ) {
if ( ! serving_cell - > has_sib1 ( ) ) {
si_acquire_state = SI_ACQUIRE_SIB1 ;
} else if ( state = = RRC_STATE_PLMN_SELECTION ) {
pthread_mutex_unlock ( & mutex ) ;
if ( state = = RRC_STATE_PLMN_SELECTION & & serving_cell - > has_sib1 ( ) ) {
bool ret = false ;
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 ( ) ;
}
} 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 ;
}
} else if ( state < RRC_STATE_CONNECTING ) {
state = RRC_STATE_CELL_SELECTING ;
}
rrc_log - > info ( " %s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm \n " ,
found ? " Updating " : " Adding " ,
cell_idx > = 0 ? " neighbour " : " serving " ,
serving_cell - > get_earfcn ( ) ,
serving_cell - > phy_cell . id ,
serving_cell - > get_rsrp ( ) ) ;
cell_idx > = 0 ? " neighbour " : " serving " , earfcn , phy_cell . id , rsrp ) ;
if ( ho_syncing & & phy_cell . id = = ho_target_pci ) {
ho_synced ( ho_target_pci ) ;
}
}
bool sort_rsrp ( cell_t * u1 , cell_t * u2 ) {
@ -668,6 +696,8 @@ void rrc::clean_neighbours()
struct timeval now ;
gettimeofday ( & now , NULL ) ;
pthread_mutex_lock ( & mutex ) ;
std : : vector < cell_t * > : : iterator it = neighbour_cells . begin ( ) ;
while ( it ! = neighbour_cells . end ( ) ) {
if ( ( * it ) - > timeout_secs ( now ) > NEIGHBOUR_TIMEOUT ) {
@ -677,6 +707,7 @@ void rrc::clean_neighbours()
+ + it ;
}
}
pthread_mutex_unlock ( & mutex ) ;
}
// Sort neighbour cells by decreasing order of RSRP
@ -695,6 +726,7 @@ void rrc::sort_neighbour_cells()
std : : sort ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , sort_rsrp ) ;
if ( neighbour_cells . size ( ) > 0 ) {
char ordered [ 512 ] ;
int n = 0 ;
n + = snprintf ( ordered , 512 , " [pci=%d, rsrsp=%.2f " , neighbour_cells [ 0 ] - > phy_cell . id , neighbour_cells [ 0 ] - > get_rsrp ( ) ) ;
@ -702,6 +734,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 ( ) ) ;
}
rrc_log - > info ( " Neighbours: %s] \n " , ordered ) ;
} else {
rrc_log - > info ( " Neighbours: Empty \n " ) ;
}
}
bool rrc : : add_neighbour_cell ( cell_t * new_cell ) {
@ -762,18 +797,6 @@ int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) {
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 ) {
nas - > plmn_search_end ( ) ;
} else if ( state = = RRC_STATE_CONNECTED ) {
leave_connected ( ) ;
}
}
// Cell reselection in IDLE Section 5.2.4 of 36.304
void rrc : : cell_reselection_eval ( float rsrp , float rsrq )
{
@ -826,7 +849,10 @@ float rrc::get_squal(float Qqualmeas) {
// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1)
void rrc : : out_of_sync ( ) {
serving_cell - > in_sync = false ;
rrc_log - > info ( " Received out-of-sync state %s. n310=%d, t311=%s, t310=%s \n " ,
rrc_state_text [ state ] , n310_cnt ,
mac_timers - > timer_get ( t311 ) - > is_running ( ) ? " running " : " stop " ,
mac_timers - > timer_get ( t310 ) - > is_running ( ) ? " running " : " stop " ) ;
if ( state = = RRC_STATE_CONNECTED ) {
if ( ! mac_timers - > timer_get ( t311 ) - > is_running ( ) & & ! mac_timers - > timer_get ( t310 ) - > is_running ( ) ) {
n310_cnt + + ;
@ -838,9 +864,23 @@ void rrc::out_of_sync() {
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 ( ) ;
} 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)
@ -899,6 +939,13 @@ void rrc::timer_expired(uint32_t timeout_id) {
} else if ( timeout_id = = t311 ) {
rrc_log - > info ( " Timer T311 expired: Going to RRC IDLE \n " ) ;
state = RRC_STATE_LEAVE_CONNECTED ;
} else if ( timeout_id = = t300 ) {
rrc_log - > info ( " Timer T300 expired: ConnectionRequest failed. Reset MAC and restablished RLC. \n " ) ;
rlc - > reestablish ( ) ;
mac - > reset ( ) ;
set_mac_default ( ) ;
state = RRC_STATE_IDLE ;
nas - > plmn_search_end ( ) ;
} else if ( timeout_id = = t301 ) {
if ( state = = RRC_STATE_IDLE ) {
rrc_log - > info ( " Timer T301 expired: Already in IDLE. \n " ) ;
@ -954,6 +1001,8 @@ void rrc::send_con_request() {
ul_ccch_msg . msg . rrc_con_req . cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING ;
mac_timers - > timer_get ( t300 ) - > reset ( ) ;
mac_timers - > timer_get ( t300 ) - > run ( ) ;
send_ul_ccch_msg ( ) ;
}
@ -1021,6 +1070,8 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
mac - > reset ( ) ;
set_mac_default ( ) ;
phy - > sync_reset ( ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
state = RRC_STATE_CELL_SELECTING ;
}
@ -1109,7 +1160,9 @@ bool rrc::ho_prepare() {
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 - > get_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 ;
}
@ -1143,10 +1196,21 @@ bool rrc::ho_prepare() {
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 ] - > get_pci ( ) ) ;
rrc_log - > error ( " Could not synchronize with target cell pci=%d. Trying to return to source PCI \n " ,
neighbour_cells [ target_cell_idx ] - > get_pci ( ) ) ;
ho_failed ( ) ;
return false ;
}
ho_target_pci = neighbour_cells [ target_cell_idx ] - > phy_cell . id ;
ho_syncing = true ;
}
return true ;
}
void rrc : : ho_synced ( uint32_t current_pci )
{
ho_syncing = false ;
if ( current_pci = = ho_target_pci ) {
if ( mob_reconf . mob_ctrl_info . rach_cnfg_ded_present ) {
rrc_log - > info ( " Starting non-contention based RA with preamble_idx=%d, mask_idx=%d \n " ,
mob_reconf . mob_ctrl_info . rach_cnfg_ded . preamble_index ,
@ -1163,7 +1227,7 @@ bool rrc::ho_prepare() {
ncc = mob_reconf . sec_cnfg_ho . intra_lte . next_hop_chaining_count ;
if ( mob_reconf . sec_cnfg_ho . intra_lte . key_change_ind ) {
rrc_log - > console ( " keyChangeIndicator in securityConfigHO not supported \n " ) ;
return false ;
return ;
}
if ( mob_reconf . sec_cnfg_ho . intra_lte . sec_alg_cnfg_present ) {
cipher_algo = ( CIPHERING_ALGORITHM_ID_ENUM ) mob_reconf . sec_cnfg_ho . intra_lte . sec_alg_cnfg . cipher_alg ;
@ -1180,8 +1244,11 @@ bool rrc::ho_prepare() {
pdcp - > config_security_all ( k_rrc_enc , k_rrc_int , cipher_algo , integ_algo ) ;
send_rrc_con_reconfig_complete ( ) ;
} else {
rrc_log - > error ( " HO: Synchronized with incorrect cell. Target PCI=%d, current PCI=%d \n " , ho_target_pci , current_pci ) ;
ho_failed ( ) ;
}
return true ;
return ;
}
void rrc : : ho_ra_completed ( bool ra_successful ) {
@ -1219,7 +1286,8 @@ 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 . get_pci ( ) ) ;
rrc_log - > error ( " Could not synchronize with target cell pci=%d. Going to PLMN Search \n " , ho_src_cell . get_pci ( ) ) ;
plmn_search ( ) ;
return ;
}
@ -1265,9 +1333,14 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
byte_buffer_t * nas_sdu ;
for ( i = 0 ; i < reconfig - > N_ded_info_nas ; i + + ) {
nas_sdu = pool_allocate ;
if ( nas_sdu ) {
memcpy ( nas_sdu - > msg , & reconfig - > ded_info_nas_list [ i ] . msg , reconfig - > ded_info_nas_list [ i ] . N_bytes ) ;
nas_sdu - > N_bytes = reconfig - > ded_info_nas_list [ i ] . N_bytes ;
nas - > write_pdu ( lcid , nas_sdu ) ;
} else {
rrc_log - > error ( " Fatal Error: Couldn't allocate PDU in handle_rrc_con_reconfig(). \n " ) ;
return ;
}
}
}
}
@ -1284,6 +1357,8 @@ void rrc::leave_connected()
{
rrc_log - > console ( " RRC IDLE \n " ) ;
rrc_log - > info ( " Leaving RRC_CONNECTED state \n " ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
last_win_start = 0 ;
drb_up = false ;
measurements . reset ( ) ;
pdcp - > reset ( ) ;
@ -1361,6 +1436,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
if ( serving_cell - > has_sib2 ( ) ) {
sysinfo_index + + ;
rrc_log - > info ( " Increasing sysinfo_index=%d \n " , sysinfo_index ) ;
}
}
@ -1623,6 +1699,8 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ :
rrc_log - > info ( " Connection Reject received. Wait time: %d \n " ,
dl_ccch_msg . msg . rrc_con_rej . wait_time ) ;
// Stop T300 timer
mac_timers - > timer_get ( t300 ) - > stop ( ) ;
state = RRC_STATE_LEAVE_CONNECTED ;
break ;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP :
@ -1925,14 +2003,15 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
liblte_rrc_srs_subfr_config_num [ sib2 - > rr_config_common_sib . srs_ul_cnfg . subfr_cnfg ] ,
sib2 - > rr_config_common_sib . srs_ul_cnfg . ack_nack_simul_tx ? " yes " : " no " ) ;
mac_timers - > timer_get ( t300 ) - > set ( this , liblte_rrc_t300_num [ sib2 - > ue_timers_and_constants . t300 ] ) ;
mac_timers - > timer_get ( t301 ) - > set ( this , liblte_rrc_t301_num [ sib2 - > ue_timers_and_constants . t301 ] ) ;
mac_timers - > timer_get ( t310 ) - > set ( this , liblte_rrc_t310_num [ sib2 - > ue_timers_and_constants . t310 ] ) ;
mac_timers - > timer_get ( t311 ) - > set ( this , liblte_rrc_t311_num [ sib2 - > ue_timers_and_constants . t311 ] ) ;
N310 = liblte_rrc_n310_num [ sib2 - > ue_timers_and_constants . n310 ] ;
N311 = liblte_rrc_n311_num [ sib2 - > ue_timers_and_constants . n311 ] ;
rrc_log - > info ( " Set Constants and Timers: N310=%d, N311=%d, t30 1=%d, t310=%d, t311=%d\n " ,
N310 , N311 , mac_timers - > timer_get ( t30 1) - > get_timeout ( ) ,
rrc_log - > info ( " Set Constants and Timers: N310=%d, N311=%d, t30 0=%d, t30 1=%d, t310=%d, t311=%d\n " ,
N310 , N311 , mac_timers - > timer_get ( t30 0) - > get_timeout ( ) , mac_timers - > timer_get ( t30 1) - > get_timeout ( ) ,
mac_timers - > timer_get ( t310 ) - > get_timeout ( ) , mac_timers - > timer_get ( t311 ) - > get_timeout ( ) ) ;
}
@ -2169,6 +2248,10 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg)
}
void rrc : : handle_con_setup ( LIBLTE_RRC_CONNECTION_SETUP_STRUCT * setup ) {
// Stop T300 timer
mac_timers - > timer_get ( t300 ) - > stop ( ) ;
// Apply the Radio Resource configuration
apply_rr_config_dedicated ( & setup - > rr_cnfg ) ;
}
@ -2379,7 +2462,10 @@ void rrc::rrc_meas::reset()
filter_k_rsrp = liblte_rrc_filter_coefficient_num [ LIBLTE_RRC_FILTER_COEFFICIENT_FC4 ] ;
filter_k_rsrq = liblte_rrc_filter_coefficient_num [ LIBLTE_RRC_FILTER_COEFFICIENT_FC4 ] ;
objects . clear ( ) ;
active . clear ( ) ;
std : : map < uint32_t , meas_t > : : iterator iter = active . begin ( ) ;
while ( iter ! = active . end ( ) ) {
remove_meas_id ( iter + + ) ;
}
reports_cfg . clear ( ) ;
phy - > meas_reset ( ) ;
bzero ( & pcell_measurement , sizeof ( meas_value_t ) ) ;
@ -2750,7 +2836,7 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) {
if ( active . count ( measId ) ) {
mac_timers - > timer_get ( active [ measId ] . periodic_timer ) - > stop ( ) ;
mac_timers - > timer_release_id ( active [ measId ] . periodic_timer ) ;
log_h - > info ( " MEAS: Removed measId=%d \n " , measId ) ;
log_h - > info ( " MEAS: Removed measId=%d , timer_id=%d \n " , measId , active [ measId ] . periodic_timer ) ;
active . erase ( measId ) ;
} else {
log_h - > warning ( " MEAS: Removing unexistent measId=%d \n " , measId ) ;
@ -2760,7 +2846,7 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) {
void rrc : : rrc_meas : : remove_meas_id ( std : : map < uint32_t , meas_t > : : iterator it ) {
mac_timers - > timer_get ( it - > second . periodic_timer ) - > stop ( ) ;
mac_timers - > timer_release_id ( it - > second . periodic_timer ) ;
log_h - > info ( " MEAS: Removed measId=%d \n " , it - > first ) ;
log_h - > info ( " MEAS: Removed measId=%d , timer_id=%d \n " , it - > first , it - > second . periodic_timer ) ;
active . erase ( it ) ;
}
@ -2900,12 +2986,15 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
} else {
is_new = true ;
active [ measId - > meas_id ] . periodic_timer = mac_timers - > timer_get_unique_id ( ) ;
if ( ! active [ measId - > meas_id ] . periodic_timer ) {
log_h - > error ( " Could not get unique timer id \n " ) ;
}
}
active [ measId - > meas_id ] . object_id = measId - > meas_obj_id ;
active [ measId - > meas_id ] . report_id = measId - > rep_cnfg_id ;
log_h - > info ( " MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, nof_values=%d\n " ,
log_h - > info ( " MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%d, nof_values=%d\n " ,
is_new ? " Added " : " Updated " , measId - > meas_id , measId - > meas_obj_id , measId - > rep_cnfg_id ,
active [ measId - > meas_id ] . cell_values. size ( ) ) ;
active [ measId - > meas_id ] . periodic_timer, active [ measId - > meas_id ] . cell_values. size ( ) ) ;
}
}