@ -26,12 +26,11 @@
# include <unistd.h>
# include <iostream>
# include <fstream>
# include <sstream>
# include "srslte/asn1/liblte_rrc.h"
# include "upper/rrc.h"
# include <boost/assign.hpp>
# include <upper/rrc.h>
# include <srslte/asn1/liblte_rrc.h>
# include "srslte/asn1/liblte_rrc.h"
# include "srslte/common/security.h"
# include "srslte/common/bcd_helpers.h"
@ -93,9 +92,15 @@ void rrc::init(phy_interface_rrc *phy_,
pthread_mutex_init ( & mutex , NULL ) ;
first_stimsi_attempt = false ;
reestablishment_in_progress = false ;
ue_category = SRSLTE_UE_CATEGORY ;
args . ue_category = SRSLTE_UE_CATEGORY ;
args . supported_bands [ 0 ] = 7 ;
args . nof_supported_bands = 1 ;
args . feature_group = 0xe6041c00 ;
args . stmsi_attach = false ;
t301 = mac_timers - > timer_get_unique_id ( ) ;
t310 = mac_timers - > timer_get_unique_id ( ) ;
t311 = mac_timers - > timer_get_unique_id ( ) ;
@ -131,12 +136,8 @@ bool rrc::have_drb() {
return drb_up ;
}
void rrc : : set_ue_category ( int category ) {
if ( category > = 1 & & category < = 5 ) {
ue_category = category ;
} else {
rrc_log - > error ( " Unsupported UE category %d \n " , category ) ;
}
void rrc : : set_args ( rrc_args_t * args ) {
memcpy ( & this - > args , args , sizeof ( rrc_args_t ) ) ;
}
/*
@ -591,6 +592,66 @@ void rrc::timer_expired(uint32_t timeout_id) {
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool rrc : : read_stimsi_file ( LIBLTE_RRC_S_TMSI_STRUCT * s_tmsi ) {
std : : ifstream file ;
std : : string line ;
if ( ! s_tmsi ) {
return false ;
}
const char * mmec_str = " mmec= " ;
size_t mmec_str_len = strlen ( mmec_str ) ;
const char * mtmsi_str = " mtmsi= " ;
size_t mtmsi_str_len = strlen ( mtmsi_str ) ;
file . open ( " .stmsi " , std : : ios : : in ) ;
if ( file . is_open ( ) ) {
bool read_ok = true ;
if ( std : : getline ( file , line ) ) {
if ( ! line . substr ( 0 , mmec_str_len ) . compare ( mmec_str ) ) {
s_tmsi - > mmec = atoi ( line . substr ( 5 ) . c_str ( ) ) ;
} else {
read_ok = false ;
}
} else {
read_ok = false ;
}
if ( std : : getline ( file , line ) ) {
if ( ! line . substr ( 0 , mtmsi_str_len ) . compare ( mtmsi_str ) ) {
s_tmsi - > m_tmsi = atoi ( line . substr ( mtmsi_str_len ) . c_str ( ) ) ;
} else {
read_ok = false ;
}
} else {
read_ok = false ;
}
file . close ( ) ;
if ( read_ok ) {
rrc_log - > info ( " Read S-TMSI value: %x:%x \n " , s_tmsi - > mmec , s_tmsi - > m_tmsi ) ;
return true ;
} else {
rrc_log - > error ( " Invalid s-tmsi persistent file format \n " ) ;
return false ;
}
} else {
return false ;
}
}
bool rrc : : write_stimsi_file ( LIBLTE_RRC_S_TMSI_STRUCT s_tmsi ) {
std : : ofstream file ;
file . open ( " .stmsi " , std : : ios : : out | std : : ios : : trunc ) ;
if ( file . is_open ( ) ) {
file < < " mmec= " < < ( int ) s_tmsi . mmec < < std : : endl ;
file < < " mtmsi= " < < ( int ) s_tmsi . m_tmsi < < std : : endl ;
rrc_log - > info ( " Saved S-TMSI in persistent file: %x:%x \n " , s_tmsi . mmec , s_tmsi . m_tmsi ) ;
file . close ( ) ;
return true ;
} else {
return false ;
}
}
void rrc : : send_con_request ( ) {
rrc_log - > debug ( " Preparing RRC Connection Request \n " ) ;
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg ;
@ -598,13 +659,32 @@ void rrc::send_con_request() {
// Prepare ConnectionRequest packet
ul_ccch_msg . msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ ;
if ( nas - > get_s_tmsi ( & s_tmsi ) ) {
bool valid_stmsi = false ;
if ( nas - > get_s_tmsi ( & s_tmsi ) | | ( args . stmsi_attach & & ! first_stimsi_attempt ) ) {
ul_ccch_msg . msg . rrc_con_req . ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI ;
ul_ccch_msg . msg . rrc_con_req . ue_id . s_tmsi = s_tmsi ;
} else {
if ( nas - > get_s_tmsi ( & s_tmsi ) ) {
ul_ccch_msg . msg . rrc_con_req . ue_id . s_tmsi = s_tmsi ;
valid_stmsi = true ;
} else {
first_stimsi_attempt = true ;
if ( args . stmsi_value . m_tmsi ) {
ul_ccch_msg . msg . rrc_con_req . ue_id . s_tmsi = args . stmsi_value ;
valid_stmsi = true ;
} else {
if ( ! read_stimsi_file ( & ul_ccch_msg . msg . rrc_con_req . ue_id . s_tmsi ) ) {
rrc_log - > warning ( " Could not read S-TMSI from persistent file. Trying normal attach. \n " ) ;
} else {
valid_stmsi = true ;
}
}
}
}
if ( ! valid_stmsi ) {
ul_ccch_msg . msg . rrc_con_req . ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE ;
ul_ccch_msg . msg . rrc_con_req . ue_id . random = 1000 ;
}
ul_ccch_msg . msg . rrc_con_req . cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING ;
liblte_rrc_pack_ul_ccch_msg ( & ul_ccch_msg , ( LIBLTE_BIT_MSG_STRUCT * ) & bit_buf ) ;
@ -876,6 +956,14 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
nas_sdu - > N_bytes = reconfig - > ded_info_nas_list [ i ] . N_bytes ;
nas - > write_pdu ( lcid , nas_sdu ) ;
}
// Get S-TMSI from NAS and store it in persistent file
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi ;
if ( nas - > get_s_tmsi ( & s_tmsi ) ) {
if ( ! write_stimsi_file ( s_tmsi ) ) {
rrc_log - > warning ( " Could not store S-TMSI in persistent file \n " ) ;
}
}
}
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
@ -1022,10 +1110,12 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) {
LIBLTE_RRC_S_TMSI_STRUCT * s_tmsi_paged ;
for ( uint32_t i = 0 ; i < pcch_msg . paging_record_list_size ; i + + ) {
s_tmsi_paged = & pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi ;
rrc_log - > info ( " Received paging (%d/%d) for UE 0x%x \n " , i + 1 , pcch_msg . paging_record_list_size ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi ) ;
rrc_log - > console ( " Received paging (%d/%d) for UE 0x%x \n " , i + 1 , pcch_msg . paging_record_list_size ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi ) ;
rrc_log - > info ( " Received paging (%d/%d) for UE %x:%x \n " , i + 1 , pcch_msg . paging_record_list_size ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi . mmec ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi . m_tmsi ) ;
rrc_log - > console ( " Received paging (%d/%d) for UE %x:%x \n " , i + 1 , pcch_msg . paging_record_list_size ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi . mmec ,
pcch_msg . paging_record_list [ i ] . ue_identity . s_tmsi . m_tmsi ) ;
if ( s_tmsi . mmec = = s_tmsi_paged - > mmec & & s_tmsi . m_tmsi = = s_tmsi_paged - > m_tmsi ) {
rrc_log - > info ( " S-TMSI match in paging message \n " ) ;
rrc_log - > console ( " S-TMSI match in paging message \n " ) ;
@ -1200,7 +1290,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void rrc : : enable_capabilities ( ) {
bool enable_ul_64 = ue_category > = 5 & & current_cell - > sib2 . rr_config_common_sib . pusch_cnfg . enable_64_qam ;
bool enable_ul_64 = args. ue_category > = 5 & & current_cell - > sib2 . 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 ) ;
}
@ -1218,7 +1308,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT * cap = & info - > ue_capability_rat [ 0 ] . eutra_capability ;
cap - > access_stratum_release = LIBLTE_RRC_ACCESS_STRATUM_RELEASE_REL8 ;
cap - > ue_category = ue_category;
cap - > ue_category = args. ue_category;
cap - > pdcp_params . max_rohc_ctxts_present = false ;
cap - > pdcp_params . supported_rohc_profiles [ 0 ] = false ;
@ -1234,31 +1324,17 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
cap - > phy_params . specific_ref_sigs_supported = false ;
cap - > phy_params . tx_antenna_selection_supported = false ;
//TODO: Generate this from user input?
cap - > rf_params . N_supported_band_eutras = 3 ;
cap - > rf_params . supported_band_eutra [ 0 ] . band_eutra = 3 ;
cap - > rf_params . supported_band_eutra [ 0 ] . half_duplex = false ;
cap - > rf_params . supported_band_eutra [ 1 ] . band_eutra = 7 ;
cap - > rf_params . supported_band_eutra [ 1 ] . half_duplex = false ;
cap - > rf_params . supported_band_eutra [ 2 ] . band_eutra = 20 ;
cap - > rf_params . supported_band_eutra [ 2 ] . half_duplex = false ;
cap - > meas_params . N_band_list_eutra = 3 ;
cap - > meas_params . band_list_eutra [ 0 ] . N_inter_freq_need_for_gaps = 3 ;
cap - > meas_params . band_list_eutra [ 0 ] . inter_freq_need_for_gaps [ 0 ] = true ;
cap - > meas_params . band_list_eutra [ 0 ] . inter_freq_need_for_gaps [ 1 ] = true ;
cap - > meas_params . band_list_eutra [ 0 ] . inter_freq_need_for_gaps [ 2 ] = true ;
cap - > meas_params . band_list_eutra [ 1 ] . N_inter_freq_need_for_gaps = 3 ;
cap - > meas_params . band_list_eutra [ 1 ] . inter_freq_need_for_gaps [ 0 ] = true ;
cap - > meas_params . band_list_eutra [ 1 ] . inter_freq_need_for_gaps [ 1 ] = true ;
cap - > meas_params . band_list_eutra [ 1 ] . inter_freq_need_for_gaps [ 2 ] = true ;
cap - > meas_params . band_list_eutra [ 2 ] . N_inter_freq_need_for_gaps = 3 ;
cap - > meas_params . band_list_eutra [ 2 ] . inter_freq_need_for_gaps [ 0 ] = true ;
cap - > meas_params . band_list_eutra [ 2 ] . inter_freq_need_for_gaps [ 1 ] = true ;
cap - > meas_params . band_list_eutra [ 2 ] . inter_freq_need_for_gaps [ 2 ] = true ;
cap - > rf_params . N_supported_band_eutras = args . nof_supported_bands ;
cap - > meas_params . N_band_list_eutra = args . nof_supported_bands ;
for ( uint32_t i = 0 ; i < args . nof_supported_bands ; i + + ) {
cap - > rf_params . supported_band_eutra [ i ] . band_eutra = args . supported_bands [ i ] ;
cap - > rf_params . supported_band_eutra [ i ] . half_duplex = false ;
cap - > meas_params . band_list_eutra [ i ] . N_inter_freq_need_for_gaps = 1 ;
cap - > meas_params . band_list_eutra [ i ] . inter_freq_need_for_gaps [ 0 ] = true ;
}
cap - > feature_group_indicator_present = true ;
cap - > feature_group_indicator = 0x62001000 ;
cap - > feature_group_indicator = args . feature_group ;
cap - > inter_rat_params . utra_fdd_present = false ;
cap - > inter_rat_params . utra_tdd128_present = false ;
cap - > inter_rat_params . utra_tdd384_present = false ;