Attach and paging ok. Reselection on IDLE not working

master
Ismael Gomez 7 years ago
parent 2c3386a486
commit b3be54b274

@ -64,7 +64,7 @@ public:
return (counter < timeout) && running;
}
bool is_expired() {
return (timeout > 0) && (counter >= timeout || !running);
return (timeout > 0) && (counter >= timeout);
}
uint32_t get_timeout() {
return timeout;

@ -112,12 +112,18 @@ public:
class nas_interface_rrc
{
public:
virtual void rrc_connection_failure() = 0;
typedef enum {
BARRING_NONE = 0,
BARRING_MO_DATA,
BARRING_MO_SIGNALLING,
BARRING_MT,
BARRING_ALL
} barring_t;
virtual void set_barring(barring_t barring) = 0;
virtual void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) = 0;
virtual bool is_attached() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 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;
};
@ -177,7 +183,9 @@ public:
virtual void enable_capabilities() = 0;
virtual int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
virtual bool connection_request() = 0;
virtual bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause,
srslte::byte_buffer_t *dedicatedInfoNAS) = 0;
virtual void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) = 0;
virtual bool is_connected() = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
@ -420,14 +428,13 @@ public:
uint32_t prach_config_index;
} mac_cfg_t;
virtual void clear_rntis() = 0;
/* Instructs the MAC to start receiving BCCH */
virtual void bcch_start_rx() = 0;
virtual void bcch_stop_rx() = 0;
virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0;
/* Instructs the MAC to start receiving PCCH */
virtual void pcch_start_rx() = 0;
virtual void pcch_stop_rx() = 0;
/* RRC configures a logical channel */
virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0;
@ -487,7 +494,6 @@ typedef struct {
uint32_t cfo_loop_pss_conv;
uint32_t cfo_ref_mask;
bool average_subframe_enabled;
int time_correct_period;
std::string sss_algorithm;
float estimator_fil_w;
bool rssi_sensor_enabled;
@ -579,11 +585,9 @@ public:
virtual int meas_start(uint32_t earfcn, int pci = -1) = 0;
virtual int meas_stop(uint32_t earfcn, int pci = -1) = 0;
typedef enum {
CELL_NOT_FOUND = 0,
CELL_FOUND,
NO_MORE_FREQS,
ERROR
typedef struct {
enum {CELL_FOUND = 0, CELL_NOT_FOUND, ERROR} found;
enum {MORE_FREQS = 0, NO_MORE_FREQS} last_freq;
} cell_search_ret_t;
typedef struct {
@ -592,7 +596,7 @@ public:
} phy_cell_t;
/* Cell search and selection procedures */
virtual cell_search_ret_t cell_search(phy_cell_t *cell, float *rsrp) = 0;
virtual cell_search_ret_t cell_search(phy_cell_t *cell) = 0;
virtual bool cell_select(phy_cell_t *cell = NULL) = 0;
virtual bool cell_is_camping() = 0;

@ -765,6 +765,7 @@ int rf_uhd_recv_with_time_multi(void *h,
trials++;
if (error_code == UHD_RX_METADATA_ERROR_CODE_OVERFLOW) {
printf("OVERFLOW\n");
log_overflow(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) {
log_late(handler, true);

@ -72,10 +72,9 @@ public:
/******** Interface from RLC (RLC -> MAC) ****************/
void bcch_start_rx();
void bcch_stop_rx();
void bcch_start_rx(int si_window_start, int si_window_length);
void pcch_start_rx();
void pcch_stop_rx();
void clear_rntis();
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void reconfiguration();
void reset();

@ -76,7 +76,7 @@ public:
float avg_snr_db;
float avg_noise;
bool pcell_meas_enabled;
bool pcell_first_measurement;
uint32_t pcell_report_period;
// Save last TBS for mcs>28 cases

@ -59,7 +59,7 @@ public:
void radio_overflow();
// RRC interface for controling the SYNC state
phy_interface_rrc::cell_search_ret_t cell_search(phy_interface_rrc::phy_cell_t *cell, float *rsrpq);
phy_interface_rrc::cell_search_ret_t cell_search(phy_interface_rrc::phy_cell_t *cell);
bool cell_select(phy_interface_rrc::phy_cell_t *cell);
bool cell_is_camping();
@ -98,9 +98,7 @@ private:
~search();
void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, phch_recv *parent);
void reset();
float get_last_gain();
float get_last_cfo();
void set_N_id_2(int N_id_2);
void set_agc_enable(bool enable);
ret_code run(srslte_cell_t *cell);
@ -247,6 +245,7 @@ private:
void radio_error();
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
void run_thread();
float get_tx_cfo();
void set_sampling_rate();
bool set_frequency();
@ -302,7 +301,6 @@ private:
IDLE = 0,
CELL_SEARCH,
SFN_SYNC,
MEASURE,
CAMPING,
} state_t;
@ -318,9 +316,13 @@ private:
}
// Called by the main thread at the end of each state to indicate it has finished.
void state_exit() {
void state_exit(bool exit_ok = true) {
pthread_mutex_lock(&inside);
if (cur_state == SFN_SYNC && exit_ok == true) {
next_state = CAMPING;
} else {
next_state = IDLE;
}
pthread_mutex_unlock(&inside);
}
void force_sfn_sync() {
@ -328,11 +330,6 @@ private:
next_state = SFN_SYNC;
pthread_mutex_unlock(&inside);
}
void force_camping() {
pthread_mutex_lock(&inside);
next_state = CAMPING;
pthread_mutex_unlock(&inside);
}
/* Functions to be called from outside the STM thread to instruct the STM to switch state.
* The functions change the state and wait until it has changed it.
@ -344,27 +341,16 @@ private:
go_state(IDLE);
pthread_mutex_unlock(&outside);
}
void go_camping() {
pthread_mutex_lock(&outside);
go_state(CAMPING);
pthread_mutex_unlock(&outside);
}
void run_cell_search() {
pthread_mutex_lock(&outside);
go_state(CELL_SEARCH);
wait_idle();
wait_state_change(CELL_SEARCH);
pthread_mutex_unlock(&outside);
}
void run_sfn_sync() {
pthread_mutex_lock(&outside);
go_state(SFN_SYNC);
wait_idle();
pthread_mutex_unlock(&outside);
}
void run_measure() {
pthread_mutex_lock(&outside);
go_state(MEASURE);
wait_idle();
wait_state_change(SFN_SYNC);
pthread_mutex_unlock(&outside);
}
@ -377,6 +363,21 @@ private:
return cur_state == CAMPING;
}
const char *to_string() {
switch(cur_state) {
case IDLE:
return "IDLE";
case CELL_SEARCH:
return "SEARCH";
case SFN_SYNC:
return "SYNC";
case CAMPING:
return "CAMPING";
default:
return "UNKNOWN";
}
}
sync_state() {
pthread_mutex_init(&inside, NULL);
pthread_mutex_init(&outside, NULL);
@ -396,9 +397,9 @@ private:
}
/* Waits until there is a call to set_state() and then run_state(). Returns when run_state() returns */
void wait_idle() {
void wait_state_change(state_t prev_state) {
pthread_mutex_lock(&inside);
while(cur_state != IDLE) {
while(cur_state == prev_state) {
pthread_cond_wait(&cvar, &inside);
}
pthread_mutex_unlock(&inside);
@ -415,8 +416,6 @@ private:
sync_state phy_state;
search::ret_code cell_search_ret;
sfn_sync::ret_code sfn_sync_ret;
measure::ret_code measure_ret;
// Sampling rate mode (find is 1.96 MHz, camp is the full cell BW)
enum {
@ -426,7 +425,6 @@ private:
// This is the primary cell
srslte_cell_t cell;
bool cell_is_set;
bool started;
float time_adv_sec;
uint32_t tti;

@ -83,7 +83,7 @@ public:
/********** RRC INTERFACE ********************/
void reset();
void configure_ul_params(bool pregen_disabled = false);
cell_search_ret_t cell_search(phy_cell_t *cell, float *rsrp);
cell_search_ret_t cell_search(phy_cell_t *cell);
bool cell_select(phy_cell_t *cell);
void meas_reset();

@ -43,18 +43,14 @@ namespace srsue {
typedef enum {
EMM_STATE_NULL = 0,
EMM_STATE_DEREGISTERED,
EMM_STATE_REGISTERED_INITIATED,
EMM_STATE_REGISTERED,
EMM_STATE_SERVICE_REQUEST_INITIATED,
EMM_STATE_DEREGISTERED_INITIATED,
EMM_STATE_TAU_INITIATED,
EMM_STATE_N_ITEMS,
} emm_state_t;
static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL",
"DEREGISTERED",
"REGISTERED INITIATED",
"REGISTERED",
"SERVICE REQUEST INITIATED",
"DEREGISTERED INITIATED",
"TRACKING AREA UPDATE INITIATED"};
@ -79,11 +75,10 @@ public:
// RRC interface
void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy);
void rrc_connection_failure();
void set_barring(barring_t barring);
void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
uint32_t get_ul_count();
bool is_attached();
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);
bool get_k_asme(uint8_t *k_asme_, uint32_t n);
// UE interface
@ -104,7 +99,8 @@ private:
emm_state_t state;
bool rrc_connection_is_failure;
nas_interface_rrc::barring_t current_barring;
bool plmn_is_selected;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT current_plmn;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT home_plmn;
@ -140,8 +136,9 @@ private:
// PCAP
srslte::nas_pcap *pcap = NULL;
bool running;
bool rrc_connect();
bool attach(bool is_service_req);
void integrity_generate(uint8_t *key_128,
uint32_t count,
@ -168,10 +165,12 @@ private:
void parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu);
void parse_emm_information(uint32_t lcid, byte_buffer_t *pdu);
// Packet generators
void gen_attach_request(byte_buffer_t *msg);
void gen_service_request(byte_buffer_t *msg);
// Senders
void send_attach_request();
void send_identity_response();
void send_service_request();
void send_esm_information_response();
void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg);
void send_security_mode_reject(uint8_t cause);

@ -64,8 +64,9 @@ class cell_t
bool equals(uint32_t earfcn, uint32_t pci) {
return earfcn == this->phy_cell.earfcn && pci == phy_cell.cell.id;
}
// NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated
bool greater(cell_t *x) {
return rsrp > x->rsrp;
return rsrp > x->rsrp || isnan(rsrp);
}
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
if (has_valid_sib1) {
@ -282,7 +283,9 @@ public:
uint16_t get_mnc();
int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]);
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id);
bool connection_request();
bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause,
srslte::byte_buffer_t *dedicatedInfoNAS);
void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi);
// PHY interface
void in_sync();
@ -321,6 +324,8 @@ private:
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
byte_buffer_t *dedicatedInfoNAS;
byte_buffer_t* byte_align_and_pack();
void send_ul_ccch_msg();
void send_ul_dcch_msg();
@ -330,6 +335,9 @@ private:
rrc_state_t state;
uint8_t transaction_id;
LIBLTE_RRC_S_TMSI_STRUCT ueIdentity;
bool ueIdentity_configured;
bool drb_up;
rrc_args_t args;
@ -358,7 +366,7 @@ private:
srslte::mac_interface_timers *mac_timers;
uint32_t n310_cnt, N310;
uint32_t n311_cnt, N311;
uint32_t t300, t301, t310, t311, t304;
uint32_t t300, t301, t302, t310, t311, t304;
// Radio bearers
typedef enum{
@ -408,7 +416,7 @@ private:
bool si_acquire(uint32_t index);
uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf);
const static int SIB_SEARCH_TIMEOUT_MS = 5000;
const static int SIB_SEARCH_TIMEOUT_MS = 1000;
const static uint32_t NOF_REQUIRED_SIBS = 3; // SIB1, SIB2 and SIB3
@ -510,6 +518,18 @@ private:
rrc_meas measurements;
// Measurement object from phy
typedef struct {
float rsrp;
float rsrq;
uint32_t tti;
uint32_t earfcn;
uint32_t pci;
} phy_meas_t;
void process_phy_meas();
void process_new_phy_meas(phy_meas_t meas);
std::queue<phy_meas_t> phy_meas_q;
// Cell selection/reselection functions/variables
typedef struct {
@ -542,7 +562,7 @@ private:
void max_retx_attempted();
// Senders
void send_con_request();
void send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause);
void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause);
void send_con_restablish_complete();
void send_con_setup_complete(byte_buffer_t *nas_msg);

@ -189,18 +189,13 @@ void mac::bcch_start_rx(int si_window_start, int si_window_length)
Info("SCHED: Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length);
}
void mac::bcch_stop_rx()
{
phy_h->pdcch_dl_search_reset();
}
void mac::pcch_start_rx()
{
phy_h->pdcch_dl_search(SRSLTE_RNTI_PCH, SRSLTE_PRNTI);
Info("SCHED: Searching for DL grant for P-RNTI\n");
}
void mac::pcch_stop_rx()
void mac::clear_rntis()
{
phy_h->pdcch_dl_search_reset();
}

@ -261,10 +261,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<bool>(&args->expert.phy.average_subframe_enabled)->default_value(true),
"Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.")
("expert.time_correct_period",
bpo::value<int>(&args->expert.phy.time_correct_period)->default_value(5),
"Period for sampling time offset correction.")
("expert.sss_algorithm",
bpo::value<string>(&args->expert.phy.sss_algorithm)->default_value("full"),
"Selects the SSS estimation algorithm.")

@ -346,7 +346,6 @@ void phch_common::reset() {
avg_rsrp_dbm = 0;
avg_rsrq_db = 0;
pcell_meas_enabled = false;
pcell_report_period = 20;
bzero(pending_ack, sizeof(pending_ack_t)*TTIMOD_SZ);

@ -134,7 +134,6 @@ void phch_recv::reset()
tx_mutex_cnt = 0;
time_adv_sec = 0;
next_offset = 0;
cell_is_set = false;
srate_mode = SRATE_NONE;
current_earfcn = -1;
sfn_p.reset();
@ -183,9 +182,12 @@ void phch_recv::reset()
* If no cells are found in any frequency it returns 0. If error returns -1.
*/
phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::phy_cell_t *found_cell, float *rsrp)
phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::phy_cell_t *found_cell)
{
phy_interface_rrc::cell_search_ret_t ret = phy_interface_rrc::ERROR;
phy_interface_rrc::cell_search_ret_t ret;
ret.found = phy_interface_rrc::cell_search_ret_t::ERROR;
ret.last_freq = phy_interface_rrc::cell_search_ret_t::NO_MORE_FREQS;
pthread_mutex_lock(&rrc_mutex);
@ -213,51 +215,24 @@ phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::p
set_sampling_rate();
phy_state.run_sfn_sync();
switch (sfn_sync_ret)
{
case sfn_sync::SFN_FOUND:
log_h->info("Cell Search. Sync OK. Measuring PCI=%d...\n", cell.id);
measure_p.reset();
phy_state.run_measure();
ret = phy_interface_rrc::CELL_FOUND;
if (phy_state.is_camping()) {
log_h->info("Cell Search: Sync OK. Camping on cell PCI=%d\n", cell.id);
if (found_cell) {
found_cell->earfcn = current_earfcn;
found_cell->cell = cell;
}
switch(measure_ret) {
case measure::MEASURE_OK:
log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id);
if (rsrp) {
*rsrp = measure_p.rsrp() - worker_com->args->rx_gain_offset;
}
phy_state.go_camping();
break;
default:
log_h->error("Cell Search: Error running cell measurement\n");
break;
}
break;
case sfn_sync::ERROR:
log_h->error("Cell Search: Error running SFN synchronization\n");
break;
default:
ret.found = phy_interface_rrc::cell_search_ret_t::CELL_FOUND;
} else {
log_h->info("Cell Search: Could not synchronize with cell\n");
ret = phy_interface_rrc::CELL_NOT_FOUND;
break;
ret.found = phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND;
}
} else {
Error("Cell Search: Setting cell PCI=%d, nof_prb=%d\n", cell.id, cell.nof_prb);
}
break;
case search::CELL_NOT_FOUND:
cellsearch_earfcn_index++;
if (cellsearch_earfcn_index >= earfcn.size()) {
Info("Cell Search: No cells were found in the current set\n");
cellsearch_earfcn_index = 0;
ret = phy_interface_rrc::NO_MORE_FREQS;
} else {
ret = phy_interface_rrc::CELL_NOT_FOUND;
}
Info("Cell Search: No cell found in this frequency\n");
ret.found = phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND;
break;
default:
Error("Cell Search: while receiving samples\n");
@ -265,6 +240,15 @@ phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::p
break;
}
cellsearch_earfcn_index++;
if (cellsearch_earfcn_index >= earfcn.size()) {
Info("Cell Search: No more frequencies in the current EARFCN set\n");
cellsearch_earfcn_index = 0;
ret.last_freq = phy_interface_rrc::cell_search_ret_t::NO_MORE_FREQS;
} else {
ret.last_freq = phy_interface_rrc::cell_search_ret_t::MORE_FREQS;
}
pthread_mutex_unlock(&rrc_mutex);
return ret;
}
@ -337,22 +321,13 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) {
}
/* SFN synchronization */
phy_state.run_sfn_sync();
bool ret = false;
switch(sfn_sync_ret) {
case sfn_sync::SFN_FOUND:
Info("Cell Select: SFN syncrhonized, going to CAMPING\n");
phy_state.go_camping();
phy_state.run_sfn_sync();
if (phy_state.is_camping()) {
Info("Cell Select: SFN synchronized. CAMPING...\n");
ret = true;
break;
case sfn_sync::ERROR:
Error("Cell Select: Error receiving samples when synchronizing SFN\n");
radio_error();
break;
default:
} else {
Info("Cell Select: Could not synchronize SFN\n");
break;
}
pthread_mutex_unlock(&rrc_mutex);
@ -398,7 +373,7 @@ void phch_recv::run_thread()
while (running)
{
Debug("SYNC: state=%d\n", phy_state);
Debug("SYNC: state=%s\n", phy_state.to_string());
log_phy_lib_h->step(tti);
@ -416,15 +391,15 @@ void phch_recv::run_thread()
/* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe
* and returns
*/
sfn_sync_ret = sfn_p.run_subframe(&cell, &tti);
if (sfn_sync_ret != sfn_sync::IDLE) {
switch(sfn_p.run_subframe(&cell, &tti)) {
case sfn_sync::SFN_FOUND:
phy_state.state_exit();
}
break;
case sync_state::MEASURE:
measure_ret = measure_p.run_subframe_sync(&ue_sync, sf_idx);
if (measure_ret != measure::IDLE) {
phy_state.state_exit();
case sfn_sync::IDLE:
break;
default:
phy_state.state_exit(false);
break;
}
break;
case sync_state::CAMPING:
@ -452,7 +427,7 @@ void phch_recv::run_thread()
metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync);
metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync);
worker->set_cfo(ul_dl_factor * metrics.cfo / 15000);
worker->set_cfo(get_tx_cfo());
worker_com->set_sync_metrics(metrics);
/* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */
@ -478,7 +453,7 @@ void phch_recv::run_thread()
if (prach_buffer->is_ready_to_send(tti)) {
srslte_timestamp_copy(&tx_time_prach, &rx_time);
srslte_timestamp_add(&tx_time_prach, 0, prach::tx_advance_sf * 1e-3);
prach_buffer->send(radio_h, ul_dl_factor * metrics.cfo / 15000, worker_com->pathloss, tx_time_prach);
prach_buffer->send(radio_h, get_tx_cfo(), worker_com->pathloss, tx_time_prach);
radio_h->tx_end();
worker_com->p0_preamble = prach_buffer->get_p0_preamble();
worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble);
@ -514,6 +489,7 @@ void phch_recv::run_thread()
if (current_srate > 0) {
nsamples = current_srate/1000;
}
Debug("Discarting %d samples\n", nsamples);
if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) {
printf("SYNC: Receiving from radio while in IDLE_RX\n");
}
@ -527,38 +503,30 @@ void phch_recv::run_thread()
* SFN is found again go back to camping
*/
if (radio_is_overflow) {
// Overflow has occurred now while camping
// If we are coming back from an overflow
if (radio_overflow_return) {
if (phy_state.is_camping()) {
log_h->info("Detected radio overflow while camping. Resynchronizing cell\n");
sfn_p.reset();
phy_state.force_sfn_sync();
radio_overflow_return = true;
// This means that it finished running sfn_sync
} else if (phy_state.is_idle() && radio_overflow_return) {
switch (sfn_sync_ret) {
case sfn_sync::SFN_FOUND:
log_h->info("Successfully resynchronized after overflow. Returning to CAMPING\n");
radio_overflow_return = false;
radio_is_overflow = false;
phy_state.force_camping();
break;
case sfn_sync::ERROR:
log_h->error("Error while recovering from overflow. Trying again\n");
radio_error();
rrc->out_of_sync();
phy_state.force_sfn_sync();
break;
case sfn_sync::SFN_NOFOUND:
log_h->warning("Could not syncrhonize SFN after radio overflow. Trying again\n");
} else if (phy_state.is_idle()) {
log_h->warning("Could not synchronize SFN after radio overflow. Trying again\n");
rrc->out_of_sync();
phy_state.force_sfn_sync();
break;
default:
break;
}
} else {
// Overflow has occurred now while camping
if (phy_state.is_camping()) {
log_h->warning("Detected radio overflow while camping. Resynchronizing cell\n");
sfn_p.reset();
phy_state.force_sfn_sync();
radio_overflow_return = true;
} else {
radio_is_overflow = false;
}
// If overflow occurs in any other state, it does not harm
}
}
// Increase TTI counter
tti = (tti+1) % 10240;
@ -582,6 +550,7 @@ void phch_recv::run_thread()
*
*/
void phch_recv::radio_overflow() {
log_h->warning("Overflow\n");
radio_is_overflow = true;
}
@ -639,6 +608,25 @@ void phch_recv::set_time_adv_sec(float time_adv_sec)
this->time_adv_sec = time_adv_sec;
}
float phch_recv::get_tx_cfo()
{
float cfo = srslte_ue_sync_get_cfo(&ue_sync);
float ret = cfo*ul_dl_factor;
if (worker_com->args->cfo_is_doppler) {
ret *= -1;
}
if (radio_h->get_freq_offset() != 0.0f) {
/* Compensates the radio frequency offset applied equally to DL and UL */
const float offset_hz = (float) radio_h->get_freq_offset() * (1.0f - ul_dl_factor);
ret = cfo - offset_hz;
}
return ret/15000;
}
void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo)
{
if (worker_com->args->cfo_integer_enabled) {
@ -663,11 +651,6 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo)
srslte_sync_set_cfo_cp_enable(&q->sfind, false, 0);
}
int time_correct_period = worker_com->args->time_correct_period;
if (time_correct_period > 0) {
srslte_ue_sync_set_sample_offset_correct_period(q, time_correct_period);
}
sss_alg_t sss_alg = SSS_FULL;
if (!worker_com->args->sss_algorithm.compare("diff")) {
sss_alg = SSS_DIFF;
@ -689,8 +672,6 @@ bool phch_recv::set_cell() {
return false;
}
cell_is_set = false;
// Set cell in all objects
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
Error("SYNC: Setting cell: initiating ue_sync\n");
@ -714,9 +695,7 @@ bool phch_recv::set_cell() {
// Reset ue_sync and set CFO/gain from search procedure
srslte_ue_sync_reset(&ue_sync);
cell_is_set = true;
return cell_is_set;
return true;
}
void phch_recv::set_earfcn(std::vector<uint32_t> earfcn) {
@ -864,20 +843,11 @@ void phch_recv::search::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h,
force_N_id_2 = -1;
}
void phch_recv::search::set_N_id_2(int N_id_2) {
force_N_id_2 = N_id_2;
}
void phch_recv::search::reset()
{
srslte_ue_sync_reset(&ue_mib_sync.ue_sync);
}
float phch_recv::search::get_last_gain()
{
return srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc);
}
float phch_recv::search::get_last_cfo()
{
return srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync);
@ -1072,7 +1042,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
}
}
} else {
Debug("SYNC: PSS/SSS not found...\n");
Info("SYNC: PSS/SSS not found...\n");
}
cnt++;
@ -1296,7 +1266,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3
sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size);
if (!sf_buffer[0]) {
fprintf(stderr, "Error allocating %d bytes for scell\n", sizeof(cf_t)*max_sf_size);
fprintf(stderr, "Error allocating %d samples for scell\n", max_sf_size);
return;
}
measure_p.init(sf_buffer, log_h, 1, max_sf_window);
@ -1475,14 +1445,10 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
void phch_recv::meas_reset() {
// Stop all measurements
intra_freq_meas.clear_cells();
if (worker_com) {
worker_com->pcell_meas_enabled = false;
}
}
int phch_recv::meas_start(uint32_t earfcn, int pci) {
if ((int) earfcn == current_earfcn) {
worker_com->pcell_meas_enabled = true;
if (pci != (int) cell.id) {
intra_freq_meas.add_cell(pci);
}

@ -164,6 +164,8 @@ bool phch_worker::set_cell(srslte_cell_t cell_)
srslte_ue_ul_set_normalization(&ue_ul, true);
srslte_ue_ul_set_cfo_enable(&ue_ul, true);
phy->pcell_first_measurement = true;
cell_initiated = true;
}
ret = true;
@ -439,8 +441,7 @@ void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
bool phch_worker::extract_fft_and_pdcch_llr() {
bool decode_pdcch = true;
/* Without a grant, we might need to do fft processing if need to decode PHICH */
if (phy->get_pending_ack(tti) || decode_pdcch) {
// Do always channel estimation to keep track of out-of-sync and send measurements to RRC
// Setup estimator filter
float w_coeff = phy->args->estimator_fil_w;
@ -462,10 +463,9 @@ bool phch_worker::extract_fft_and_pdcch_llr() {
Error("Getting PDCCH FFT estimate\n");
return false;
}
chest_done = true;
} else {
chest_done = false;
}
if (chest_done && decode_pdcch) { /* and not in DRX mode */
float noise_estimate = phy->avg_noise;
@ -1427,7 +1427,8 @@ void phch_worker::update_measurements()
} else {
phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff);
}
if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) {
if ((tti%phy->pcell_report_period) == 0 || phy->pcell_first_measurement) {
phy->pcell_first_measurement = false;
phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti);
}
}

@ -96,7 +96,6 @@ void phy::set_default_args(phy_args_t *args)
args->equalizer_mode = "mmse";
args->cfo_integer_enabled = false;
args->cfo_correct_tol_hz = 50;
args->time_correct_period = 5;
args->sss_algorithm = "full";
args->estimator_fil_w = 0.1;
}
@ -266,8 +265,8 @@ bool phy::cell_select(phy_cell_t *cell) {
return sf_recv.cell_select(cell);
}
phy_interface_rrc::cell_search_ret_t phy::cell_search(phy_cell_t *cell, float *rsrp) {
return sf_recv.cell_search(cell, rsrp);
phy_interface_rrc::cell_search_ret_t phy::cell_search(phy_cell_t *cell) {
return sf_recv.cell_search(cell);
}
bool phy::cell_is_camping() {

@ -248,9 +248,8 @@ void gw::run_thread()
return;
}
const static uint32_t ATTACH_TIMEOUT_MS = 10000;
const static uint32_t ATTACH_TIMEOUT_S = 4;
const static uint32_t ATTACH_MAX_ATTEMPTS = 3;
uint32_t attach_cnt = 0;
uint32_t attach_attempts = 0;
gw_log->info("GW IP packet receiver thread run_enable\n");
@ -279,16 +278,13 @@ void gw::run_thread()
gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU");
while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_attempts < ATTACH_MAX_ATTEMPTS) {
if (attach_cnt == 0) {
gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_attempts, ATTACH_MAX_ATTEMPTS);
nas->attach_request();
if (!nas->attach_request()) {
attach_attempts++;
sleep(ATTACH_TIMEOUT_S);
} else {
attach_attempts = 0;
}
attach_cnt++;
if (attach_cnt == ATTACH_TIMEOUT_MS) {
attach_cnt = 0;
}
usleep(1000);
}
if (attach_attempts == ATTACH_MAX_ATTEMPTS) {
@ -296,7 +292,6 @@ void gw::run_thread()
}
attach_attempts = 0;
attach_cnt = 0;
if (!run_enable) {
break;

@ -79,9 +79,11 @@ void nas::init(usim_interface_nas *usim_,
have_guti = true;
have_ctxt = true;
}
running = true;
}
void nas::stop() {
running = false;
write_ctxt_file(ctxt);
}
@ -133,11 +135,10 @@ bool nas::attach_request() {
if (plmn_is_selected) {
rrc->plmn_select(current_plmn);
if (rrc_connect()) {
nas_log->info("RRC connection established. Sending NAS attach request\n");
if (attach(false)) {
nas_log->info("NAS attached successfully.\n");
return true;
}
} else {
nas_log->error("Could not attach\n");
}
} else {
nas_log->error("PLMN is not selected because no suitable PLMN was found\n");
@ -150,11 +151,9 @@ bool nas::attach_request() {
} else {
nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n");
if (rrc_connect()) {
nas_log->info("RRC connection established. Sending NAS attach request\n");
if (attach(true)) {
nas_log->info("NAS attached successfully.\n");
return true;
}
} else {
nas_log->error("Could not attach\n");
}
}
break;
@ -179,21 +178,17 @@ void nas::paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) {
if (state == EMM_STATE_REGISTERED) {
nas_log->info("Received paging: requesting RRC connection establishment\n");
if (rrc_connect()) {
nas_log->info("Connected successfully. Initiating service request\n");
if (attach(true)) {
nas_log->info("Attached successfully\n");
} else {
nas_log->error("Could not attach\n");
}
} else {
nas_log->error("Could not establish RRC connection\n");
}
nas_log->warning("Received paging while in state %s\n", emm_state_text[state]);
}
}
void nas::rrc_connection_failure() {
nas_log->debug("Received RRC Connection Failure\n");
rrc_connection_is_failure = true;
void nas::set_barring(barring_t barring) {
current_barring = barring;
}
/* Internal function that requests RRC connection, waits for positive or negative response and returns true/false
@ -203,55 +198,50 @@ bool nas::rrc_connect() {
nas_log->info("Already connected\n");
return true;
}
uint32_t tout;
rrc_connection_is_failure = false;
if (rrc->connection_request()) {
// Wait until RRCConnected or connection error
tout = 0;
while (tout < 10000 && !rrc->is_connected() && !rrc_connection_is_failure) {
usleep(1000);
tout++;
}
if (rrc->is_connected()) {
rrc_connection_is_failure = false;
return true;
} else if (rrc_connection_is_failure) {
nas_log->info("Failed to establish RRC connection\n");
} else {
nas_log->error("Timed out while establishing RRC connection (%d s)\n", tout/1000);
}
// Generate service request or attach request message
byte_buffer_t *dedicatedInfoNAS = pool_allocate;
if (state == EMM_STATE_REGISTERED) {
gen_service_request(dedicatedInfoNAS);
} else {
nas_log->warning("Could initiate RRC connection request\n");
gen_attach_request(dedicatedInfoNAS);
}
return false;
}
/* Internal function that requests NAS attach, waits for positive or negative response and returns true/false
*/
bool nas::attach(bool is_service_req) {
uint32_t tout;
if (is_service_req) {
send_service_request();
} else {
send_attach_request();
// Provide UE-Identity to RRC if have one
if (have_guti) {
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi;
s_tmsi.mmec = ctxt.guti.mme_code;
s_tmsi.m_tmsi = ctxt.guti.m_tmsi;
rrc->set_ue_idenity(s_tmsi);
}
state = EMM_STATE_REGISTERED_INITIATED;
// Set establishment cause
LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establish_cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
// Wait until NAS is registered
tout = 0;
while (tout < 10000 && state == EMM_STATE_REGISTERED_INITIATED) {
if (rrc->connection_request(establish_cause, dedicatedInfoNAS))
{
nas_log->info("Connection established correctly. Waiting for Attach\n");
// Wait until attachment. If doing a service request is already attached
uint32_t tout = 0;
while (tout < 5000 && state != EMM_STATE_REGISTERED && running && rrc->is_connected()) {
usleep(1000);
tout++;
}
if (state == EMM_STATE_REGISTERED) {
nas_log->info("EMM Registered correctly\n");
return true;
} else if (state == EMM_STATE_DEREGISTERED) {
nas_log->error("Received attach reject while trying to attach\n");
nas_log->console("Failed to Attach\n");
} else if (!rrc->is_connected()) {
nas_log->error("Was disconnected while attaching\n");
} else {
nas_log->error("Timed out while trying to attach\n");
}
} else {
nas_log->error("Could not establish RRC connection\n");
}
return false;
}
@ -362,16 +352,6 @@ uint32_t nas::get_ul_count() {
return ctxt.tx_count;
}
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) {
if (have_guti) {
s_tmsi->mmec = ctxt.guti.mme_code;
s_tmsi->m_tmsi = ctxt.guti.m_tmsi;
return true;
} else {
return false;
}
}
bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) {
if(!have_ctxt) {
nas_log->error("K_asme requested before security context established\n");
@ -560,6 +540,11 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
if (attach_accept.guti_present) {
memcpy(&ctxt.guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
have_guti = true;
// Update RRC UE-Idenity
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi;
s_tmsi.mmec = ctxt.guti.mme_code;
s_tmsi.m_tmsi = ctxt.guti.m_tmsi;
rrc->set_ue_idenity(s_tmsi);
}
if (attach_accept.lai_present) {}
if (attach_accept.ms_id_present) {}
@ -896,19 +881,18 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
* Senders
******************************************************************************/
void nas::send_attach_request() {
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req;
byte_buffer_t *msg = pool_allocate;
void nas::gen_attach_request(byte_buffer_t *msg) {
if (!msg) {
nas_log->error("Fatal Error: Couldn't allocate PDU in send_attach_request().\n");
nas_log->error("Fatal Error: Couldn't allocate PDU in gen_attach_request().\n");
return;
}
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req;
u_int32_t i;
nas_log->info("Generating attach request\n");
attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH;
for (i = 0; i < 8; i++) {
for (u_int32_t i = 0; i < 8; i++) {
attach_req.ue_network_cap.eea[i] = eea_caps[i];
attach_req.ue_network_cap.eia[i] = eia_caps[i];
}
@ -967,14 +951,47 @@ void nas::send_attach_request() {
pcap->write_nas(msg->msg, msg->N_bytes);
}
nas_log->info("Sending attach request\n");
rrc->write_sdu(cfg.lcid, msg);
if (have_ctxt) {
ctxt.tx_count++;
}
}
void nas::gen_service_request(byte_buffer_t *msg) {
if (!msg) {
nas_log->error("Fatal Error: Couldn't allocate PDU in gen_service_request().\n");
return;
}
nas_log->info("Generating service request\n");
// Pack the service request message directly
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg->N_bytes++;
msg->msg[1] = (ctxt.ksi & 0x07) << 5;
msg->msg[1] |= ctxt.tx_count & 0x1F;
msg->N_bytes++;
uint8_t mac[4];
integrity_generate(&k_nas_int[16],
ctxt.tx_count,
SECURITY_DIRECTION_UPLINK,
&msg->msg[0],
2,
&mac[0]);
// Set the short MAC
msg->msg[2] = mac[2];
msg->N_bytes++;
msg->msg[3] = mac[3];
msg->N_bytes++;
if(pcap != NULL) {
pcap->write_nas(msg->msg, msg->N_bytes);
}
ctxt.tx_count++;
}
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req;
@ -1022,42 +1039,6 @@ void nas::send_security_mode_reject(uint8_t cause) {
void nas::send_identity_response() {}
void nas::send_service_request() {
byte_buffer_t *msg = pool_allocate;
if (!msg) {
nas_log->error("Fatal Error: Couldn't allocate PDU in send_service_request().\n");
return;
}
// Pack the service request message directly
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg->N_bytes++;
msg->msg[1] = (ctxt.ksi & 0x07) << 5;
msg->msg[1] |= ctxt.tx_count & 0x1F;
msg->N_bytes++;
uint8_t mac[4];
integrity_generate(&k_nas_int[16],
ctxt.tx_count,
SECURITY_DIRECTION_UPLINK,
&msg->msg[0],
2,
&mac[0]);
// Set the short MAC
msg->msg[2] = mac[2];
msg->N_bytes++;
msg->msg[3] = mac[3];
msg->N_bytes++;
if(pcap != NULL) {
pcap->write_nas(msg->msg, msg->N_bytes);
}
nas_log->info("Sending service request\n");
rrc->write_sdu(cfg.lcid, msg);
ctxt.tx_count++;
}
void nas::send_esm_information_response() {}

@ -110,10 +110,14 @@ void rrc::init(phy_interface_rrc *phy_,
t300 = mac_timers->timer_get_unique_id();
t301 = mac_timers->timer_get_unique_id();
t302 = mac_timers->timer_get_unique_id();
t310 = mac_timers->timer_get_unique_id();
t311 = mac_timers->timer_get_unique_id();
t304 = mac_timers->timer_get_unique_id();
dedicatedInfoNAS = NULL;
ueIdentity_configured = false;
transaction_id = 0;
// Register logging handler with liblte_rrc
@ -167,15 +171,44 @@ void rrc::run_tti(uint32_t tti) {
return;
}
/* We can not block in this thread because it is called from
* the MAC TTI timer and needs to return immediatly to perform other
* tasks. Therefore in this function we use trylock() instead of lock() and
* skip function if currently locked, since none of the functions here is urgent
*/
if (!pthread_mutex_trylock(&mutex)) {
// Process pending PHY measurements in IDLE/CONNECTED
process_phy_meas();
// Run state machine
rrc_log->debug("State %s\n", rrc_state_text[state]);
switch(state) {
switch (state) {
case RRC_STATE_IDLE:
/* CAUTION: The execution of cell_search() and cell_selection() take more than 1 ms
* and will slow down MAC TTI ticks. This has no major effect at the moment because
* the UE is in IDLE but we could consider splitting MAC and RRC threads to avoid this
*/
// If attached but not camping on the cell, perform cell reselection
if (nas->is_attached()) {
rrc_log->info("Running cell selection and reselection in IDLE\n");
rrc_log->debug("Running cell selection and reselection in IDLE\n");
if (!cell_selection()) {
if (!serving_cell->in_sync) {
rrc_log->info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n");
// If can not camp on any cell, search again for new cells
cell_search();
phy_interface_rrc::cell_search_ret_t ret = cell_search();
// TODO: Should not camp on it until we have checked is a valid PLMN
if (ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND) {
// New cell has been selected, start receiving PCCH
mac->pcch_start_rx();
}
}
} else {
// New cell has been selected, start receiving PCCH
mac->pcch_start_rx();
}
}
break;
@ -188,17 +221,21 @@ void rrc::run_tti(uint32_t tti) {
}
measurements.run_tti(tti);
if (go_idle) {
go_idle = false;
leave_connected();
}
break;
default:
break;
default:break;
}
// Clean old neighbours
cell_clean_cnt++;
if (cell_clean_cnt==1000) {
if (cell_clean_cnt == 1000) {
clean_neighbours();
cell_clean_cnt = 0;
}
pthread_mutex_unlock(&mutex);
} // Skip TTI if mutex is locked
}
@ -244,7 +281,7 @@ int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS])
phy_interface_rrc::cell_search_ret_t ret;
do {
ret = cell_search();
if (ret == phy_interface_rrc::CELL_FOUND) {
if (ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND) {
if (serving_cell->has_sib1()) {
// Save PLMN and TAC to NAS
for (uint32_t i = 0; i < serving_cell->nof_plmns(); i++) {
@ -260,11 +297,15 @@ int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS])
rrc_log->error("SIB1 not acquired\n");
}
}
} while (ret == phy_interface_rrc::CELL_NOT_FOUND || ret == phy_interface_rrc::CELL_FOUND);
} while (ret.last_freq == phy_interface_rrc::cell_search_ret_t::MORE_FREQS &&
ret.found != phy_interface_rrc::cell_search_ret_t::ERROR);
// Process all pending measurements before returning
process_phy_meas();
pthread_mutex_unlock(&mutex);
if (ret == phy_interface_rrc::ERROR) {
if (ret.found == phy_interface_rrc::cell_search_ret_t::ERROR) {
return -1;
} else {
return nof_plmns;
@ -277,6 +318,8 @@ int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS])
void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
plmn_is_selected = true;
selected_plmn_id = plmn_id;
rrc_log->info("PLMN Selected %s\n", plmn_id_to_string(plmn_id).c_str());
}
/* 5.3.3.2 Initiation of RRC Connection Establishment procedure
@ -287,7 +330,9 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
* it. Sends connectionRequest message and returns if message transmitted successfully.
* It does not wait until completition of Connection Establishment procedure
*/
bool rrc::connection_request() {
bool rrc::connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause,
srslte::byte_buffer_t *dedicatedInfoNAS)
{
if (!plmn_is_selected) {
rrc_log->error("Trying to connect but PLMN not selected.\n");
@ -295,7 +340,13 @@ bool rrc::connection_request() {
}
if (state != RRC_STATE_IDLE) {
rrc_log->warning("Requested RRC connection establishment while in state %s\n", rrc_state_text[state]);
rrc_log->warning("Requested RRC connection establishment while not in IDLE\n");
return false;
}
if (mac_timers->timer_get(t302)->is_running()) {
rrc_log->info("Requested RRC connection establishment while T302 is running\n");
nas->set_barring(nas_interface_rrc::BARRING_MO_DATA);
return false;
}
@ -303,16 +354,13 @@ bool rrc::connection_request() {
pthread_mutex_lock(&mutex);
// Perform cell re-selection
int cnt = 0;
while(!(serving_cell->plmn_equals(selected_plmn_id) && phy->cell_is_camping()) && cnt<10) {
rrc_log->info("Not camping on any suitable cell. Selecting another cell\n");
rrc_log->info("Initiation of Connection establishment procedure\n");
// Perform cell selection & reselection for the selected PLMN
cell_selection();
cnt++;
}
// .. and SI acquisition
if (cnt<10) {
if (phy->cell_is_camping()) {
// Set default configurations
set_phy_default();
@ -327,9 +375,37 @@ bool rrc::connection_request() {
mac_timers->timer_get(t300)->reset();
mac_timers->timer_get(t300)->run();
rrc_log->info("Sending ConnectionRequest\n");
send_con_request();
// Send connectionRequest message to lower layers
send_con_request(cause);
// Save dedicatedInfoNAS SDU
if (this->dedicatedInfoNAS) {
rrc_log->warning("Received a new dedicatedInfoNAS SDU but there was one still in queue. Removing it\n");
pool->deallocate(this->dedicatedInfoNAS);
}
this->dedicatedInfoNAS = dedicatedInfoNAS;
// Wait until t300 stops due to RRCConnectionSetup/Reject or expiry
while (mac_timers->timer_get(t300)->is_running()) {
usleep(1000);
}
if (state == RRC_STATE_CONNECTED) {
// Received ConnectionSetup
ret = true;
} else if (mac_timers->timer_get(t300)->is_expired()) {
// T300 is expired: 5.3.3.6
rrc_log->info("Timer T300 expired: ConnectionRequest timed out\n");
mac->reset();
set_mac_default();
rlc->reestablish();
} else {
// T300 is stopped but RRC not Connected is because received Reject: Section 5.3.3.8
rrc_log->info("Timer T300 stopped: Received ConnectionReject\n");
mac->reset();
set_mac_default();
}
} else {
rrc_log->error("Configuring serving cell\n");
}
@ -341,6 +417,12 @@ bool rrc::connection_request() {
return ret;
}
void rrc::set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) {
ueIdentity_configured = true;
ueIdentity = s_tmsi;
rrc_log->info("Set ue-Identity to 0x%x:0x%x\n", ueIdentity.mmec, ueIdentity.m_tmsi);
}
/* Retrieves all required SIB or configures them if already retrieved before
*/
bool rrc::configure_serving_cell() {
@ -349,15 +431,20 @@ bool rrc::configure_serving_cell() {
rrc_log->error("Trying to configure Cell while not camping on it\n");
return false;
}
// Apply configurations if already retrieved SIB2
if (serving_cell->has_sib2()) {
apply_sib2_configs(serving_cell->sib2ptr());
}
// Obtain the rest of required SIBs (configuration is applied when received)
for (uint32_t i = 0; i < NOF_REQUIRED_SIBS; i++) {
if (!serving_cell->has_sib(i)) {
rrc_log->info("Cell has no SIB%d. Obtaining SIB%d\n", i+1, i+1);
if (!si_acquire(i)) {
rrc_log->info("Timeout while acquiring SIB%d\n", i + 1);
rrc_log->info("Timeout while acquiring SIB%d\n", i+1);
return false;
}
} else if (i == 1) {
// Re-apply SIB2 configuration acquired previously
apply_sib2_configs(serving_cell->sib2ptr());
} else {
rrc_log->info("Cell has SIB%d\n", i+1);
}
}
return true;
@ -378,19 +465,41 @@ bool rrc::configure_serving_cell() {
*
*******************************************************************************/
/* This function is called from a PHY worker thus must return very quickly.
* Queue the values of the measurements and process them from the RRC thread
*/
void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) {
if (earfcn_i < 0) {
earfcn_i = (int) serving_cell->get_earfcn();
}
if (pci_i < 0) {
pci_i = (int) serving_cell->get_pci();
}
pthread_mutex_lock(&mutex);
phy_meas_t new_meas = {rsrp, rsrq, tti, (uint32_t) earfcn_i, (uint32_t) pci_i};
phy_meas_q.push(new_meas);
rrc_log->info("MEAS: New measurement pci=%d, rsrp=%.1f dBm.\n", pci_i, rsrp);
}
if (earfcn_i < 0 || pci_i < 0) {
earfcn_i = serving_cell->get_earfcn();
pci_i = serving_cell->get_pci();
/* Processes all pending PHY measurements in queue. Must be called from a mutexed function
*/
void rrc::process_phy_meas() {
while(!phy_meas_q.empty()) {
rrc_log->debug("MEAS: Processing measurement. %d measurements in queue\n", phy_meas_q.size());
process_new_phy_meas(phy_meas_q.front());
phy_meas_q.pop();
}
}
uint32_t earfcn = (uint32_t) earfcn_i;
uint32_t pci = (uint32_t) pci_i;
void rrc::process_new_phy_meas(phy_meas_t meas)
{
float rsrp = meas.rsrp;
float rsrq = meas.rsrq;
uint32_t tti = meas.tti;
uint32_t earfcn = meas.earfcn;
uint32_t pci = meas.pci;
// Measurements in RRC_CONNECTED go through measuremnt class to log reports etc.
// Measurements in RRC_CONNECTED go through measurement class to log reports etc.
if (state != RRC_STATE_IDLE) {
measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti);
@ -399,24 +508,20 @@ 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(rsrp, rsrq);
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
} else {
if (add_neighbour_cell(earfcn, pci, rsrp)) {
rrc_log->info("MEAS: New measurement neighbour in IDLE, PCI=%d, RSRP=%.1f dBm.\n", pci, rsrp);
} else {
rrc_log->info("MEAS: Neighbour Cell in IDLE PCI=%d, RSRP=%.1f dBm not added. Worse than current neighbours\n", pci, rsrp);
add_neighbour_cell(earfcn, pci, rsrp);
}
}
}
pthread_mutex_unlock(&mutex);
}
// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1)
void rrc::out_of_sync() {
void rrc::out_of_sync()
{
// CAUTION: We do not lock in this function since they are called from real-time threads
serving_cell->in_sync = false;
rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n",
rrc_state_text[state], n310_cnt,
@ -433,17 +538,15 @@ void rrc::out_of_sync() {
n310_cnt = 0;
}
}
} else {
if (!mac_timers->timer_get(t311)->is_running()) {
rrc_log->info("Detected out-of-sync while in IDLE\n");
} else {
rrc_log->info("Detected out-of-sync while in IDLE and T311 running\n");
}
}
}
// Recovery of physical layer problems (5.3.11.2)
void rrc::in_sync() {
void rrc::in_sync()
{
// CAUTION: We do not lock in this function since they are called from real-time threads
serving_cell->in_sync = true;
if (mac_timers->timer_get(t310)->is_running()) {
n311_cnt++;
@ -582,41 +685,37 @@ bool rrc::si_acquire(uint32_t sib_index)
phy_interface_rrc::cell_search_ret_t rrc::cell_search()
{
phy_interface_rrc::phy_cell_t new_cell;
float rsrp;
phy_interface_rrc::cell_search_ret_t ret = phy->cell_search(&new_cell, &rsrp);
phy_interface_rrc::cell_search_ret_t ret = phy->cell_search(&new_cell);
switch(ret) {
case phy_interface_rrc::CELL_FOUND:
switch(ret.found) {
case phy_interface_rrc::cell_search_ret_t::CELL_FOUND:
rrc_log->info("Cell found in this frequency. Setting new serving cell...\n");
if (!add_neighbour_cell(new_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);
// Create cell with NaN RSRP. Will be updated by new_phy_meas() during SIB search.
if (!add_neighbour_cell(new_cell, NAN)) {
rrc_log->info("No more space for neighbour cells\n");
break;
}
set_serving_cell(new_cell);
rrc_log->info("Camping on cell...\n");
if (phy->cell_select(&new_cell)) {
if (phy->cell_is_camping()) {
if (!serving_cell->has_sib1()) {
rrc_log->info("Camping OK. Obtaining SIB1\n");
rrc_log->info("Cell has no SIB1. Obtaining SIB1\n");
if (!si_acquire(0)) {
rrc_log->error("Timeout while acquiring SIB1\n");
}
} else {
rrc_log->info("Camping OK. Already has SIB1\n");
rrc_log->info("Cell has SIB1\n");
}
} else {
rrc_log->warning("Could not camp on found cell. Trying next one...\n");
}
break;
case phy_interface_rrc::CELL_NOT_FOUND:
rrc_log->info("No cells found. Trying next frequency\n");
break;
case phy_interface_rrc::NO_MORE_FREQS:
rrc_log->info("Finished searching for cells in current EARFCN set\n");
case phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND:
rrc_log->info("No cells found.\n");
break;
case phy_interface_rrc::ERROR:
case phy_interface_rrc::cell_search_ret_t::ERROR:
rrc_log->error("In cell search. Finishing PLMN search\n");
break;
}
@ -774,8 +873,6 @@ 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) {
@ -785,7 +882,6 @@ void rrc::clean_neighbours()
++it;
}
}
pthread_mutex_unlock(&mutex);
}
// Sort neighbour cells by decreasing order of RSRP
@ -807,7 +903,7 @@ void rrc::sort_neighbour_cells()
if (neighbour_cells.size() > 0) {
char ordered[512];
int n=0;
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.cell.id, neighbour_cells[0]->get_rsrp());
n += snprintf(ordered, 512, "[pci=%d, rsrp=%.2f", neighbour_cells[0]->phy_cell.cell.id, neighbour_cells[0]->get_rsrp());
for (uint32_t i=1;i<neighbour_cells.size();i++) {
n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp());
}
@ -854,8 +950,8 @@ bool rrc::add_neighbour_cell(phy_interface_rrc::phy_cell_t phy_cell, float rsrp)
rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.cell.id, phy_cell.earfcn, cell_idx);
// If exists, update RSRP, sort again and return
if (cell_idx >= 0) {
// If exists, update RSRP if provided, sort again and return
if (cell_idx >= 0 && isnormal(rsrp)) {
neighbour_cells[cell_idx]->set_rsrp(rsrp);
sort_neighbour_cells();
return true;
@ -934,13 +1030,11 @@ void rrc::timer_expired(uint32_t timeout_id) {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
go_idle = true;
}
} else if (timeout_id == t302) {
rrc_log->info("Timer T302 expired. Informing NAS about barrier alleviation\n");
nas->set_barring(nas_interface_rrc::BARRING_NONE);
} else if (timeout_id == t300) {
// 5.3.3.6
rrc_log->info("Timer T300 expired: ConnectionRequest timed out\n");
mac->reset();
set_mac_default();
rlc->reestablish();
nas->rrc_connection_failure();
// Do nothing, handled in connection_request()
} else if (timeout_id == t304) {
rrc_log->console("Timer T304 expired: Handover failed\n");
ho_failed();
@ -967,16 +1061,16 @@ void rrc::timer_expired(uint32_t timeout_id) {
*
*******************************************************************************/
void rrc::send_con_request() {
void rrc::send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause) {
rrc_log->debug("Preparing RRC Connection Request\n");
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi;
// Prepare ConnectionRequest packet
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
if (nas->get_s_tmsi(&s_tmsi)) {
if (ueIdentity_configured) {
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;
ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi.m_tmsi = ueIdentity.m_tmsi;
ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi.mmec = ueIdentity.mmec;
} else {
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
// TODO use proper RNG
@ -987,10 +1081,9 @@ void rrc::send_con_request() {
ul_ccch_msg.msg.rrc_con_req.ue_id.random = random_id;
}
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
ul_ccch_msg.msg.rrc_con_req.cause = cause;
send_ul_ccch_msg();
}
/* RRC connection re-establishment procedure (5.3.7) */
@ -1067,7 +1160,8 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause)
set_mac_default();
// Perform cell selection in accordance to 36.304
if (cell_selection()) {
if (cell_selection_criteria(serving_cell->get_rsrp()) && serving_cell->in_sync) {
if (phy->cell_select(&serving_cell->phy_cell)) {
if (mac_timers->timer_get(t311)->is_running()) {
// Actions following cell reselection while T311 is running 5.3.7.3
@ -1079,12 +1173,16 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause)
mac_timers->timer_get(t311)->stop();
send_ul_ccch_msg();
} else {
rrc_log->info("T311 expired while selecting cell. Going to IDLE\n");
go_idle = true;
}
} else {
rrc_log->warning("Could not re-synchronize with cell.\n");
}
} else {
rrc_log->info("Selected cell no longer suitable for camping. Going to IDLE\n");
go_idle = true;
}
}
void rrc::send_con_restablish_complete() {
@ -1102,9 +1200,6 @@ void rrc::send_con_restablish_complete() {
void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) {
rrc_log->debug("Preparing RRC Connection Setup Complete\n");
state = RRC_STATE_CONNECTED;
rrc_log->console("RRC Connected\n");
// Prepare ConnectionSetupComplete packet
ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE;
ul_dcch_msg.msg.rrc_con_setup_complete.registered_mme_present = false;
@ -1179,7 +1274,7 @@ bool rrc::ho_prepare() {
ho_src_rnti = uernti.crnti;
// Reset/Reestablish stack
mac->bcch_stop_rx(); // FIXME: change function name
mac->clear_rntis();
phy->meas_reset();
mac->wait_uplink();
pdcp->reestablish();
@ -1331,7 +1426,8 @@ void rrc::con_reconfig_failed()
}
void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) {
uint32_t i;
pthread_mutex_lock(&mutex);
phy->get_config(&previous_phy_cfg);
mac->get_config(&previous_mac_cfg);
@ -1345,6 +1441,8 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
con_reconfig_failed();
}
}
pthread_mutex_unlock(&mutex);
}
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
@ -1372,8 +1470,10 @@ void rrc::leave_connected()
mac_timers->timer_get(t310)->stop();
mac_timers->timer_get(t311)->stop();
mac_timers->timer_get(t304)->stop();
rrc_log->info("Going RRC_IDLE\n");
state = RRC_STATE_IDLE;
if (phy->cell_is_camping()) {
// Instruct MAC to look for P-RNTI
// Receive paging
mac->pcch_start_rx();
// Instruct PHY to measure serving cell for cell reselection
phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci());
@ -1401,7 +1501,7 @@ void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu) {
}
void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
mac->bcch_stop_rx();
mac->clear_rntis();
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH DLSCH message received.");
rrc_log->info("BCCH DLSCH message Stack latency: %ld us\n", pdu->get_latency_us());
@ -1523,12 +1623,10 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) {
pcch_msg.paging_record_list_size = LIBLTE_RRC_MAX_PAGE_REC;
}
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi;
if (!nas->get_s_tmsi(&s_tmsi)) {
rrc_log->info("No S-TMSI present in NAS\n");
if (!ueIdentity_configured) {
rrc_log->warning("Received paging message but no ue-Identity is configured\n");
return;
}
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;
@ -1538,12 +1636,16 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) {
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) {
if (ueIdentity.mmec == s_tmsi_paged->mmec && ueIdentity.m_tmsi == s_tmsi_paged->m_tmsi) {
if (RRC_STATE_IDLE == state) {
rrc_log->info("S-TMSI match in paging message\n");
rrc_log->console("S-TMSI match in paging message\n");
nas->paging(s_tmsi_paged);
} else {
rrc_log->warning("Received paging while in CONNECT\n");
}
} else {
rrc_log->info("Received paging for unknown identity\n");
}
}
}
@ -1621,18 +1723,12 @@ void rrc::send_ul_dcch_msg()
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
if (state == RRC_STATE_IDLE) {
rrc_log->warning("Received ULInformationTransfer SDU when in IDLE\n");
return;
}
rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str());
switch (state) {
case RRC_STATE_IDLE:
send_con_setup_complete(sdu);
break;
case RRC_STATE_CONNECTED:
send_ul_info_transfer(sdu);
break;
default:
rrc_log->error("SDU received from NAS while RRC state = %s\n", rrc_state_text[state]);
break;
}
}
void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
@ -1665,28 +1761,37 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
// 5.3.3.8
rrc_log->info("Connection Reject received. Wait time: %d\n",
rrc_log->info("Received ConnectionReject. Wait time: %d\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time);
rrc_log->console("Received ConnectionReject. Wait time: %d\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time);
mac_timers->timer_get(t300)->stop();
mac->reset();
set_mac_default();
nas->rrc_connection_failure();
if (dl_ccch_msg.msg.rrc_con_rej.wait_time) {
nas->set_barring(nas_interface_rrc::BARRING_ALL);
mac_timers->timer_get(t302)->set(this, dl_ccch_msg.msg.rrc_con_rej.wait_time*1000);
mac_timers->timer_get(t302)->run();
} else {
// Perform the actions upon expiry of T302 if wait time is zero
nas->set_barring(nas_interface_rrc::BARRING_NONE);
go_idle = true;
}
break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
rrc_log->info("Connection Setup received\n");
rrc_log->info("ConnectionSetup received\n");
transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id;
handle_con_setup(&dl_ccch_msg.msg.rrc_con_setup);
rrc_log->info("Notifying NAS of connection setup\n");
break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST:
rrc_log->info("Connection Reestablishment received\n");
rrc_log->info("ConnectionReestablishment received\n");
rrc_log->console("Reestablishment OK\n");
transaction_id = dl_ccch_msg.msg.rrc_con_reest.rrc_transaction_id;
handle_con_reest(&dl_ccch_msg.msg.rrc_con_reest);
break;
/* Reception of RRCConnectionReestablishmentReject 5.3.7.8 */
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ:
rrc_log->info("Connection Reestablishment Reject received\n");
rrc_log->info("ConnectionReestablishmentReject received\n");
rrc_log->console("Reestablishment Reject\n");
go_idle = true;
break;
@ -2229,22 +2334,34 @@ bool rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg)
void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) {
// Apply the Radio Resource configuration
apply_rr_config_dedicated(&setup->rr_cnfg);
// Must enter CONNECT before stopping T300
state = RRC_STATE_CONNECTED;
rrc_log->console("RRC Connected\n");
mac_timers->timer_get(t300)->stop();
mac_timers->timer_get(t302)->stop();
nas->set_barring(nas_interface_rrc::BARRING_NONE);
if (dedicatedInfoNAS) {
send_con_setup_complete(dedicatedInfoNAS);
dedicatedInfoNAS = NULL; // deallocated Inside!
} else {
rrc_log->error("Pending to transmit a ConnectionSetupComplete but no dedicatedInfoNAS was in queue\n");
}
}
/* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */
void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) {
// TODO: Reestablish DRB1. Not done because never was suspended
mac_timers->timer_get(t301)->stop();
pdcp->reestablish();
rlc->reestablish();
// Apply the Radio Resource configuration
apply_rr_config_dedicated(&setup->rr_cnfg);
mac_timers->timer_get(t300)->stop();
// Enter RRC_CONNECTED
state = RRC_STATE_CONNECTED;
// Send ConnectionSetupComplete message
send_con_restablish_complete();
}
@ -2466,7 +2583,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
// This indicates serving cell
if (parent->serving_cell->equals(earfcn, pci)) {
log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
log_h->debug("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
L3_filter(&pcell_measurement, values);
@ -2478,7 +2595,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
// Add to list of neighbour cells
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",
log_h->debug("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

@ -406,13 +406,13 @@ public:
printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n",
nof_bytes, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period);
sib1_decoded = true;
mac.bcch_stop_rx();
mac.clear_rntis();
} else if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2) {
printf("SIB2 received %d bytes\n", nof_bytes);
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy);
sib2_decoded = true;
mac.bcch_stop_rx();
mac.clear_rntis();
}
}
}

@ -83,7 +83,9 @@ public:
int plmn_search(srsue::rrc_interface_nas::found_plmn_t*) { return 0; };
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {};
bool connection_request() {return true;}
void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) {}
bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause,
srslte::byte_buffer_t *dedicatedInfoNAS) {return true;}
bool is_connected() {return true;}
uint16_t get_mcc() { return mcc; }

Loading…
Cancel
Save