Refactored NAS/RRC/PHY cell_search/selection procedures

master
Ismael Gomez 7 years ago
parent ef7b52045e
commit f88f465c97

@ -450,7 +450,12 @@ int main(int argc, char **argv) {
srslte_rf_close(&rf);
exit(0);
}
printf("stop\n");
srslte_rf_stop_rx_stream(&rf);
printf("flush\n");
srslte_rf_flush_buffer(&rf);
printf("ok\n");
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {

@ -88,7 +88,7 @@ public:
period_us = period_us_;
start(priority);
}
void stop() {
void stop_thread() {
run_enable = false;
wait_thread_finish();
}

@ -112,30 +112,28 @@ public:
class nas_interface_rrc
{
public:
virtual void rrc_connection_failure() = 0;
virtual void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) = 0;
virtual bool is_attached() = 0;
virtual bool is_attaching() = 0;
virtual void notify_connection_setup() = 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;
virtual bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
virtual void plmn_search_end() = 0;
};
// NAS interface for UE
class nas_interface_ue
{
public:
virtual void attach_request() = 0;
virtual void deattach_request() = 0;
virtual bool attach_request() = 0;
virtual bool deattach_request() = 0;
};
// NAS interface for UE
class nas_interface_gw
{
public:
virtual void attach_request() = 0;
virtual bool attach_request() = 0;
};
// RRC interface for MAC
@ -159,8 +157,6 @@ class rrc_interface_phy
public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
virtual void earfcn_end() = 0;
virtual void cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp = NAN) = 0;
virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn = -1, int pci = -1) = 0;
};
@ -168,12 +164,21 @@ public:
class rrc_interface_nas
{
public:
typedef struct {
LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id;
uint16_t tac;
} found_plmn_t;
const static int MAX_FOUND_PLMNS = 16;
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0;
virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request = false) = 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 is_connected() = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
@ -380,12 +385,7 @@ public:
/* Indicate successfull decoding of PCH TB through PDSCH */
virtual void pch_decoded_ok(uint32_t len) = 0;
/* Function called every start of a subframe (TTI). Warning, this function is called
* from a high priority thread and should terminate asap
*/
virtual void tti_clock(uint32_t tti) = 0;
};
/* Interface RRC -> MAC shared between different RATs */
@ -503,9 +503,7 @@ typedef struct {
class phy_interface_mac_common
{
public:
/* Start synchronization with strongest cell in the current carrier frequency */
virtual bool sync_status() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
@ -581,15 +579,22 @@ 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
} cell_search_ret_t;
typedef struct {
srslte_cell_t cell;
uint32_t earfcn;
} phy_cell_t;
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_next() = 0;
virtual void cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool cell_handover(srslte_cell_t cell) = 0;
/* Is the PHY downlink synchronized? */
virtual bool sync_status() = 0;
virtual void sync_reset() = 0;
virtual cell_search_ret_t cell_search(phy_cell_t *cell, float *rsrp) = 0;
virtual bool cell_select(phy_cell_t *cell = NULL) = 0;
virtual bool cell_is_camping() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;

@ -89,6 +89,7 @@ void radio::reset()
printf("Resetting Radio...\n");
srslte_rf_stop_rx_stream(&rf_device);
radio_is_streaming = false;
usleep(100000);
}
void radio::set_manual_calibration(rf_cal_t* calibration)

@ -50,7 +50,7 @@ class mac
,public mac_interface_rrc
,public srslte::timer_callback
,public srslte::mac_interface_timers
,public thread
,public periodic_thread
{
public:
mac();
@ -68,7 +68,6 @@ public:
void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid);
void bch_decoded_ok(uint8_t *payload, uint32_t len);
void pch_decoded_ok(uint32_t len);
void tti_clock(uint32_t tti);
/******** Interface from RLC (RLC -> MAC) ****************/
@ -110,15 +109,14 @@ public:
private:
void run_thread();
void run_period();
static const int MAC_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD
static const int MAC_PDU_THREAD_PRIO = DEFAULT_PRIORITY-5;
static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS;
// Interaction with PHY
srslte::tti_sync_cv ttisync;
phy_interface_mac *phy_h;
phy_interface_mac *phy_h;
rlc_interface_mac *rlc_h;
rrc_interface_mac *rrc_h;
srslte::log *log_h;
@ -130,11 +128,7 @@ private:
ue_rnti_t uernti;
uint32_t tti;
bool started;
bool is_synchronized;
uint16_t last_temporal_crnti;
uint16_t phy_rnti;
/* Multiplexing/Demultiplexing Units */
mux mux_unit;
demux demux_unit;
@ -168,19 +162,6 @@ private:
mac_metrics_t metrics;
/* Class to run Timers in a dedicated thread */
class mac_timers : public periodic_thread {
public:
void init(srslte::timers *timers, srslte::log *log_h);
private:
void run_period();
srslte::timers *timers;
bool running;
srslte::log *log_h;
};
mac_timers mactimers;
/* Class to process MAC PDUs from DEMUX unit */
class pdu_process : public thread {
public:

@ -28,6 +28,7 @@
#define UEPHYRECV_H
#include <map>
#include <pthread.h>
#include "srslte/srslte.h"
#include "srslte/common/log.h"
@ -50,29 +51,23 @@ class phch_recv : public thread, public chest_feedback_itf
public:
phch_recv();
~phch_recv();
void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc,
prach *prach_buffer, srslte::thread_pool *_workers_pool,
phch_common *_worker_com, srslte::log* _log_h, srslte::log *_log_phy_lib_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1);
void stop();
void set_agc_enable(bool enable);
void radio_overflow();
void set_earfcn(std::vector<uint32_t> earfcn);
void force_freq(float dl_freq, float ul_freq);
void reset_sync();
void cell_search_start();
void cell_search_next(bool reset = false);
void cell_select(uint32_t earfcn, srslte_cell_t cell);
bool cell_handover(srslte_cell_t cell);
// 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);
bool cell_select(phy_interface_rrc::phy_cell_t *cell);
bool cell_is_camping();
// RRC interface for controlling the neighbour cell measurement
void meas_reset();
int meas_start(uint32_t earfcn, int pci);
int meas_stop(uint32_t earfcn, int pci);
uint32_t get_current_tti();
bool status_is_sync();
// from chest_feedback_itf
void in_sync();
void out_of_sync();
@ -80,37 +75,21 @@ public:
void set_time_adv_sec(float time_adv_sec);
void get_current_cell(srslte_cell_t *cell, uint32_t *earfcn = NULL);
uint32_t get_current_tti();
// From UE configuration
void set_agc_enable(bool enable);
void set_earfcn(std::vector<uint32_t> earfcn);
void force_freq(float dl_freq, float ul_freq);
// Other functions
const static int MUTEX_X_WORKER = 4;
double set_rx_gain(double gain);
int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
int scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
private:
std::vector<uint32_t> earfcn;
void reset();
void radio_error();
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
void run_thread();
void set_sampling_rate();
bool set_frequency();
bool set_cell();
void cell_search_inc();
void cell_reselect();
float get_cfo();
uint32_t new_earfcn;
srslte_cell_t new_cell;
bool running;
// Class to run cell search
class search {
public:
@ -137,22 +116,23 @@ private:
// Class to synchronize system frame number
class sfn_sync {
public:
typedef enum {IDLE, SFN_FOUND, SFX0_FOUND, ERROR, TIMEOUT} ret_code;
typedef enum {IDLE, SFN_FOUND, SFX0_FOUND, SFN_NOFOUND, ERROR} ret_code;
~sfn_sync();
void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout = SYNC_SFN_TIMEOUT);
void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_subframes = SFN_SYNC_NOF_SUBFRAMES);
void reset();
bool set_cell(srslte_cell_t cell);
ret_code run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only = false);
private:
const static int SFN_SYNC_NOF_SUBFRAMES = 100;
uint32_t cnt;
uint32_t timeout;
srslte::log *log_h;
srslte_ue_sync_t *ue_sync;
cf_t *buffer[SRSLTE_MAX_PORTS];
srslte_ue_mib_t ue_mib;
uint32_t cnt;
uint32_t timeout;
const static uint32_t SYNC_SFN_TIMEOUT = 80;
};
// Class to perform cell measurements
@ -170,7 +150,7 @@ private:
void set_cell(srslte_cell_t cell);
ret_code run_subframe(uint32_t sf_idx);
ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx);
ret_code run_multiple_subframes(cf_t *buffer, int offset, uint32_t sf_idx, uint32_t nof_sf);
ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
float rssi();
float rsrp();
float rsrq();
@ -201,11 +181,11 @@ private:
uint32_t offset;
} cell_info_t;
void init(srslte::log *log_h, bool sic_pss_enabled, uint32_t max_sf_window);
void deinit();
void reset();
int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]);
private:
cf_t *input_cfo_corrected;
cf_t *sf_buffer[SRSLTE_MAX_PORTS];
srslte::log *log_h;
srslte_sync_t sync_find;
@ -222,7 +202,6 @@ private:
// Class to perform intra-frequency measurements
class intra_measure : public thread {
public:
~intra_measure();
void init(phch_common *common, rrc_interface_phy *rrc, srslte::log *log_h);
void stop();
void add_cell(int pci);
@ -233,6 +212,8 @@ private:
void write(uint32_t tti, cf_t *data, uint32_t nsamples);
private:
void run_thread();
const static int INTRA_FREQ_MEAS_LEN_MS = 50;
const static int INTRA_FREQ_MEAS_PERIOD_MS = 200;
const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
scell_recv scell;
@ -261,6 +242,23 @@ private:
// 36.133 9.1.2.1 for band 7
const static float ABSOLUTE_RSRP_THRESHOLD_DBM = -125;
std::vector<uint32_t> earfcn;
void reset();
void radio_error();
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
void run_thread();
void set_sampling_rate();
bool set_frequency();
bool set_cell();
uint32_t new_earfcn;
srslte_cell_t new_cell;
bool radio_is_overflow;
bool radio_overflow_return;
bool running;
// Objects for internal use
measure measure_p;
@ -298,19 +296,128 @@ private:
const static uint32_t NOF_OUT_OF_SYNC_SF = 200;
const static uint32_t NOF_IN_SYNC_SF = 100;
// State for primary cell
typedef enum {
IDLE = 0,
CELL_SEARCH,
CELL_SELECT,
CELL_RESELECT,
CELL_MEASURE,
CELL_CAMP,
} phy_state_t;
// State machine for SYNC thread
class sync_state {
public:
typedef enum {
IDLE = 0,
CELL_SEARCH,
SFN_SYNC,
MEASURE,
CAMPING,
} state_t;
/* Run_state is called by the main thread at the start of each loop. It updates the state
* and returns the current state
*/
state_t run_state() {
pthread_mutex_lock(&inside);
cur_state = next_state;
pthread_cond_broadcast(&cvar);
pthread_mutex_unlock(&inside);
return cur_state;
}
// Called by the main thread at the end of each state to indicate it has finished.
void state_exit() {
pthread_mutex_lock(&inside);
next_state = IDLE;
pthread_mutex_unlock(&inside);
}
void force_sfn_sync() {
pthread_mutex_lock(&inside);
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.
*
* These functions are mutexed and only 1 can be called at a time
*/
void go_idle() {
pthread_mutex_lock(&outside);
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();
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();
pthread_mutex_unlock(&outside);
}
/* Helpers below this */
bool is_idle() {
return cur_state == IDLE;
}
bool is_camping() {
return cur_state == CAMPING;
}
sync_state() {
pthread_mutex_init(&inside, NULL);
pthread_mutex_init(&outside, NULL);
pthread_cond_init(&cvar, NULL);
cur_state = IDLE;
next_state = IDLE;
}
private:
void go_state(state_t s) {
pthread_mutex_lock(&inside);
next_state = s;
while(cur_state != s) {
pthread_cond_wait(&cvar, &inside);
}
pthread_mutex_unlock(&inside);
}
/* Waits until there is a call to set_state() and then run_state(). Returns when run_state() returns */
void wait_idle() {
pthread_mutex_lock(&inside);
while(cur_state != IDLE) {
pthread_cond_wait(&cvar, &inside);
}
pthread_mutex_unlock(&inside);
}
state_t cur_state, next_state;
pthread_mutex_t inside, outside;
pthread_cond_t cvar;
};
pthread_mutex_t rrc_mutex;
phy_state_t phy_state, prev_state;
sync_state phy_state;
bool is_in_idle;
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 {
@ -330,8 +437,8 @@ private:
uint32_t tx_mutex_cnt;
float ul_dl_factor;
uint32_t current_earfcn;
int cur_earfcn_index;
int current_earfcn;
uint32_t cellsearch_earfcn_index;
float dl_freq;
float ul_freq;

@ -82,21 +82,18 @@ public:
/********** RRC INTERFACE ********************/
void reset();
void sync_reset();
void configure_ul_params(bool pregen_disabled = false);
void cell_search_start();
void cell_search_next();
void cell_select(uint32_t earfcn, srslte_cell_t phy_cell);
bool cell_handover(srslte_cell_t cell);
cell_search_ret_t cell_search(phy_cell_t *cell, float *rsrp);
bool cell_select(phy_cell_t *cell);
void meas_reset();
int meas_start(uint32_t earfcn, int pci);
int meas_stop(uint32_t earfcn, int pci);
/********** MAC INTERFACE ********************/
/* Functions to synchronize with a cell */
bool sync_status(); // this is also RRC interface
// also MAC interface
bool cell_is_camping();
/********** MAC INTERFACE ********************/
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
void set_crnti(uint16_t rnti);

@ -69,6 +69,8 @@ public:
bool init(all_args_t *args_);
void stop();
bool attach();
bool deattach();
bool is_attached();
void start_plot();

@ -155,6 +155,8 @@ public:
virtual bool init(all_args_t *args_) = 0;
virtual void stop() = 0;
virtual bool attach() = 0;
virtual bool deattach() = 0;
virtual bool is_attached() = 0;
virtual void start_plot() = 0;

@ -61,11 +61,6 @@ static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL",
static const bool eia_caps[8] = {false, true, true, false, false, false, false, false};
static const bool eea_caps[8] = {true, true, true, false, false, false, false, false};
typedef enum {
PLMN_NOT_SELECTED = 0,
PLMN_SELECTED
} plmn_selection_state_t;
class nas
: public nas_interface_rrc,
public nas_interface_ue,
@ -83,20 +78,17 @@ public:
emm_state_t get_state();
// RRC interface
void notify_connection_setup();
void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy);
void rrc_connection_failure();
void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
uint32_t get_ul_count();
bool is_attached();
bool is_attaching();
bool is_data_requested();
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);
bool get_k_asme(uint8_t *k_asme_, uint32_t n);
bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code);
void plmn_search_end();
// UE interface
void attach_request();
void deattach_request();
bool attach_request();
bool deattach_request();
// PCAP
void start_pcap(srslte::nas_pcap *pcap_);
@ -112,9 +104,9 @@ private:
emm_state_t state;
plmn_selection_state_t plmn_selection;
bool rrc_connection_is_failure;
bool plmn_is_selected;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT current_plmn;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selecting_plmn;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT home_plmn;
std::vector<LIBLTE_RRC_PLMN_IDENTITY_STRUCT > known_plmns;
@ -148,6 +140,9 @@ private:
// PCAP
srslte::nas_pcap *pcap = NULL;
bool rrc_connect();
bool attach(bool is_service_req);
void integrity_generate(uint8_t *key_128,
uint32_t count,
uint8_t direction,
@ -160,6 +155,8 @@ private:
bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps);
void select_plmn();
// Parsers
void parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu);
void parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu);

@ -52,18 +52,17 @@ using srslte::byte_buffer_t;
namespace srsue {
class cell_t
{
public:
bool is_valid() {
return earfcn != 0 && srslte_cell_isvalid(&phy_cell);
return phy_cell.earfcn != 0 && srslte_cell_isvalid(&phy_cell.cell);
}
bool equals(cell_t *x) {
return equals(x->earfcn, x->phy_cell.id);
return equals(x->phy_cell.earfcn, x->phy_cell.cell.id);
}
bool equals(uint32_t earfcn, uint32_t pci) {
return earfcn == this->earfcn && pci == phy_cell.id;
return earfcn == this->phy_cell.earfcn && pci == phy_cell.cell.id;
}
bool greater(cell_t *x) {
return rsrp > x->rsrp;
@ -78,11 +77,39 @@ class cell_t
}
return false;
}
uint32_t nof_plmns() {
if (has_valid_sib1) {
return sib1.N_plmn_ids;
} else {
return 0;
}
}
LIBLTE_RRC_PLMN_IDENTITY_STRUCT get_plmn(uint32_t idx) {
if (idx < sib1.N_plmn_ids && has_valid_sib1) {
return sib1.plmn_id[idx].id;
} else {
LIBLTE_RRC_PLMN_IDENTITY_STRUCT null;
null.mnc = 0;
null.mcc = 0;
return null;
}
}
uint16_t get_tac() {
if (has_valid_sib1) {
return sib1.tracking_area_code;
} else {
return 0;
}
}
cell_t() {
srslte_cell_t tmp = {};
cell_t(tmp, 0, 0);
phy_interface_rrc::phy_cell_t tmp = {};
cell_t(tmp, 0);
}
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
cell_t(phy_interface_rrc::phy_cell_t phy_cell, float rsrp) {
gettimeofday(&last_update, NULL);
this->has_valid_sib1 = false;
this->has_valid_sib2 = false;
@ -90,7 +117,6 @@ class cell_t
this->has_valid_sib13 = false;
this->phy_cell = phy_cell;
this->rsrp = rsrp;
this->earfcn = earfcn;
in_sync = true;
bzero(&sib1, sizeof(sib1));
bzero(&sib2, sizeof(sib2));
@ -99,11 +125,11 @@ class cell_t
}
uint32_t get_earfcn() {
return earfcn;
return phy_cell.earfcn;
}
uint32_t get_pci() {
return phy_cell.id;
return phy_cell.cell.id;
}
void set_rsrp(float rsrp) {
@ -170,6 +196,20 @@ class cell_t
return has_valid_sib13;
}
bool has_sib(uint32_t index) {
switch(index) {
case 0:
return has_sib1();
case 1:
return has_sib2();
case 2:
return has_sib3();
case 12:
return has_sib13();
}
return false;
}
uint16_t get_mcc() {
if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) {
@ -188,12 +228,11 @@ class cell_t
return 0;
}
srslte_cell_t phy_cell;
phy_interface_rrc::phy_cell_t phy_cell;
bool in_sync;
private:
float rsrp;
uint32_t earfcn;
struct timeval last_update;
bool has_valid_sib1;
@ -213,7 +252,6 @@ class rrc
,public rrc_interface_pdcp
,public rrc_interface_rlc
,public srslte::timer_callback
,public thread
{
public:
rrc();
@ -231,52 +269,40 @@ public:
void stop();
rrc_state_t get_state();
void set_args(rrc_args_t *args);
// Timeout callback interface
void timer_expired(uint32_t timeout_id);
void liblte_rrc_log(char *str);
// NAS interface
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
void enable_capabilities();
uint16_t get_mcc();
uint16_t get_mnc();
void enable_capabilities();
void plmn_search();
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request);
int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]);
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id);
bool connection_request();
// PHY interface
void in_sync();
void out_of_sync();
void earfcn_end();
void cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci);
// MAC interface
void ho_ra_completed(bool ra_successful);
void release_pucch_srs();
void run_tti(uint32_t tti);
void ra_problem();
// GW interface
bool is_connected();
bool is_connected(); // this is also NAS interface
bool have_drb();
// PDCP interface
void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
void write_pdu_bcch_bch(byte_buffer_t *pdu);
void write_pdu_bcch_dlsch(byte_buffer_t *pdu);
void write_pdu_pcch(byte_buffer_t *pdu);
@ -307,25 +333,16 @@ private:
bool drb_up;
rrc_args_t args;
bool first_stimsi_attempt;
uint32_t cell_clean_cnt;
uint16_t ho_src_rnti;
cell_t ho_src_cell;
uint32_t ho_target_pci;
bool ho_syncing;
phy_interface_rrc::phy_cfg_t ho_src_phy_cfg;
mac_interface_rrc::mac_cfg_t ho_src_mac_cfg;
phy_interface_rrc::phy_cfg_t previous_phy_cfg;
mac_interface_rrc::mac_cfg_t previous_mac_cfg;
bool pending_mob_reconf;
LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf;
// timeouts in ms
uint32_t connecting_timeout;
static const uint32_t RRC_CONNECTING_TIMEOUT = 5000;
uint32_t plmn_select_timeout;
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;
uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32];
uint8_t k_up_enc[32];
@ -376,42 +393,35 @@ private:
std::vector<cell_t*> neighbour_cells;
cell_t *serving_cell;
void set_serving_cell(uint32_t cell_idx);
void set_serving_cell(uint32_t earfcn, uint32_t pci);
void set_serving_cell(phy_interface_rrc::phy_cell_t phy_cell);
int find_neighbour_cell(uint32_t earfcn, uint32_t pci);
bool add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp);
bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
bool add_neighbour_cell(phy_interface_rrc::phy_cell_t phy_cell, float rsrp);
bool add_neighbour_cell(cell_t *cell);
void sort_neighbour_cells();
void clean_neighbours();
std::vector<cell_t*>::iterator delete_neighbour(std::vector<cell_t*>::iterator it);
void delete_neighbour(uint32_t cell_idx);
typedef enum {
SI_ACQUIRE_IDLE = 0,
SI_ACQUIRE_SIB1,
SI_ACQUIRE_SIB2
} si_acquire_state_t;
bool configure_serving_cell();
si_acquire_state_t si_acquire_state;
void run_si_acquisition_procedure();
bool si_acquire(uint32_t index);
uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf);
uint32_t nof_sib1_trials;
uint16_t sysinfo_index;
uint32_t last_win_start;
const static int SIB_SEARCH_TIMEOUT_MS = 5000;
bool select_next_cell_in_plmn();
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id;
const static uint32_t NOF_REQUIRED_SIBS = 3; // SIB1, SIB2 and SIB3
bool thread_running;
void run_thread();
bool initiated;
bool ho_start;
bool go_idle;
// Measurements sub-class
class rrc_meas {
public:
void init(rrc *parent);
void reset();
void parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config);
bool parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config);
void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti);
void run_tti(uint32_t tti);
bool timer_expired(uint32_t timer_id);
@ -510,25 +520,30 @@ private:
float s_intrasearchP;
float q_hyst;
float threshservinglow;
} cell_resel_cfg_t;
cell_resel_cfg_t cell_resel_cfg;
float get_srxlev(float Qrxlevmeas);
float get_squal(float Qqualmeas);
void cell_reselection_eval(float rsrp, float rsrq);
bool cell_selection_eval(float rsrp, float rsrq = 0);
bool connection_requested;
void plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id);
bool cell_selection();
bool cell_selection_criteria(float rsrp, float rsrq = 0);
void cell_reselection(float rsrp, float rsrq);
phy_interface_rrc::cell_search_ret_t cell_search();
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id;
bool plmn_is_selected;
bool security_is_activated;
// RLC interface
void max_retx_attempted();
// Senders
void send_con_request();
void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti);
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);
void send_ul_info_transfer(byte_buffer_t *nas_msg);
@ -542,16 +557,15 @@ private:
void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu);
// Helpers
void ho_failed();
bool con_reconfig(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig);
void con_reconfig_failed();
bool con_reconfig_ho(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig);
bool ho_prepare();
void ho_synced(uint32_t target_pci);
void ho_failed();
void rrc_connection_release();
void con_restablish_cell_reselected();
void radio_link_failure();
void leave_connected();
static void* start_sib_thread(void *rrc_);
void sib_search();
void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config);
void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config);
void handle_sib1();
@ -566,7 +580,7 @@ private:
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg);
void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg);
void release_drb(uint8_t lcid);
void apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg);
bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg);
void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults);
void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults);

@ -33,27 +33,11 @@ namespace srsue {
// RRC states (3GPP 36.331 v10.0.0)
typedef enum {
RRC_STATE_IDLE = 0,
RRC_STATE_PLMN_START,
RRC_STATE_PLMN_SELECTION,
RRC_STATE_CELL_SELECTING,
RRC_STATE_CELL_SELECTED,
RRC_STATE_CONNECTING,
RRC_STATE_CONNECTED,
RRC_STATE_HO_PREPARE,
RRC_STATE_HO_PROCESS,
RRC_STATE_LEAVE_CONNECTED,
RRC_STATE_N_ITEMS,
} rrc_state_t;
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE",
"PLMN SELECTED",
"PLMN SELECTION",
"CELL SELECTING",
"CELL SELECTED",
"CONNECTING",
"CONNECTED",
"HO PREPARE",
"HO PROCESS",
"LEAVE CONNECTED"};
"CONNECTED"};
} // namespace srsue

@ -41,27 +41,21 @@
namespace srsue {
mac::mac() : ttisync(10240),
timers(64),
mac::mac() : timers(64),
mux_unit(MAC_NOF_HARQ_PROC),
pdu_process_thread(&demux_unit)
{
started = false;
pcap = NULL;
bzero(&metrics, sizeof(mac_metrics_t));
}
bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac *rrc, srslte::log *log_h_)
{
started = false;
phy_h = phy;
rlc_h = rlc;
rrc_h = rrc;
log_h = log_h_;
tti = 0;
is_synchronized = false;
last_temporal_crnti = 0;
phy_rnti = 0;
srslte_softbuffer_rx_init(&pch_softbuffer, 100);
@ -79,23 +73,18 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac
reset();
started = true;
start(MAC_MAIN_THREAD_PRIO);
start_periodic(1000, MAC_MAIN_THREAD_PRIO);
mactimers.init(&timers, log_h);
return started;
return true;
}
void mac::stop()
{
srslte_softbuffer_rx_free(&pch_softbuffer);
started = false;
ttisync.increase();
pdu_process_thread.stop();
stop_thread();
wait_thread_finish();
mactimers.stop();
}
void mac::start_pcap(srslte::mac_pcap* pcap_)
@ -150,59 +139,38 @@ void mac::reset()
bzero(&uernti, sizeof(ue_rnti_t));
}
void mac::mac_timers::init(srslte::timers *timers, srslte::log *log_h) {
this->timers = timers;
running = true;
this->log_h = log_h;
start_periodic(1000);
}
void mac::mac_timers::run_period() {
timers->step_all();
}
void mac::run_thread() {
int cnt=0;
while (!phy_h->sync_status() && started) {
usleep(5000);
if (phy_h->sync_status()) {
Debug("Setting ttysync to %d\n", phy_h->get_current_tti());
ttisync.set_producer_cntr(phy_h->get_current_tti());
}
}
while(started) {
void mac::run_period() {
/* Warning: Here order of invocation of procedures is important!! */
tti = ttisync.wait();
/* Warning: Here order of invocation of procedures is important!! */
log_h->step(tti);
tti = phy_h->get_current_tti();
// Step all procedures
bsr_procedure.step(tti);
phr_procedure.step(tti);
log_h->step(tti);
// Check if BSR procedure need to start SR
// Step all procedures
bsr_procedure.step(tti);
phr_procedure.step(tti);
if (bsr_procedure.need_to_send_sr(tti)) {
Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", tti);
sr_procedure.start();
}
if (bsr_procedure.need_to_reset_sr()) {
Debug("Resetting SR procedure by BSR request\n");
sr_procedure.reset();
}
sr_procedure.step(tti);
// Check if BSR procedure need to start SR
// Check SR if we need to start RA
if (sr_procedure.need_random_access()) {
ra_procedure.start_mac_order();
}
ra_procedure.step(tti);
if (bsr_procedure.need_to_send_sr(tti)) {
Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", tti);
sr_procedure.start();
}
if (bsr_procedure.need_to_reset_sr()) {
Debug("Resetting SR procedure by BSR request\n");
sr_procedure.reset();
}
sr_procedure.step(tti);
rrc_h->run_tti(tti);
// Check SR if we need to start RA
if (sr_procedure.need_random_access()) {
ra_procedure.start_mac_order();
}
ra_procedure.step(tti);
timers.step_all();
rrc_h->run_tti(tti);
}
void mac::bcch_start_rx()
@ -237,12 +205,6 @@ void mac::pcch_stop_rx()
phy_h->pdcch_dl_search_reset();
}
void mac::tti_clock(uint32_t tti)
{
ttisync.increase(tti);
}
void mac::bch_decoded_ok(uint8_t* payload, uint32_t len)
{
// Send MIB to RLC

@ -483,9 +483,15 @@ int main(int argc, char *argv[])
ue->start_plot();
plot_started = true;
}
} else {
while (!ue->attach() && running) {
sleep(1);
}
}
if (running) {
ue->print_pool();
sleep(10);
}
ue->print_pool();
sleep(10);
}
pthread_cancel(input);
metricshub.stop();

File diff suppressed because it is too large Load Diff

@ -250,20 +250,6 @@ void phy::configure_ul_params(bool pregen_disabled)
}
}
void phy::cell_search_start()
{
sf_recv.cell_search_start();
}
void phy::cell_search_next()
{
sf_recv.cell_search_next();
}
void phy::sync_reset() {
sf_recv.reset_sync();
}
void phy::meas_reset() {
sf_recv.meas_reset();
}
@ -276,13 +262,16 @@ int phy::meas_stop(uint32_t earfcn, int pci) {
return sf_recv.meas_stop(earfcn, pci);
}
void phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
{
sf_recv.cell_select(earfcn, phy_cell);
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);
}
bool phy::cell_handover(srslte_cell_t cell) {
return sf_recv.cell_handover(cell);
bool phy::cell_is_camping() {
return sf_recv.cell_is_camping();
}
float phy::get_phr()
@ -348,7 +337,7 @@ int phy::prach_tx_tti()
// Handle the case of a radio overflow. Resynchronise inmediatly
void phy::radio_overflow() {
sf_recv.reset_sync();
sf_recv.radio_overflow();
}
void phy::reset()
@ -388,11 +377,6 @@ void phy::force_freq(float dl_freq, float ul_freq)
sf_recv.force_freq(dl_freq, ul_freq);
}
bool phy::sync_status()
{
return sf_recv.status_is_sync();
}
void phy::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{
workers_common.set_rar_grant(tti, grant_payload);

@ -226,7 +226,6 @@ bool ue::init(all_args_t *args_)
}
printf("...\n");
nas.attach_request();
started = true;
return true;
@ -273,9 +272,17 @@ void ue::stop()
}
}
bool ue::attach() {
return nas.attach_request();
}
bool ue::deattach() {
return nas.deattach_request();
}
bool ue::is_attached()
{
return rrc.is_connected();
return nas.is_attached();
}
void ue::start_plot() {

@ -45,7 +45,7 @@ namespace srsue {
********************************************************************/
nas::nas()
: state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), have_ctxt(false), ip_addr(0), eps_bearer_id(0)
: state(EMM_STATE_DEREGISTERED), have_guti(false), have_ctxt(false), ip_addr(0), eps_bearer_id(0)
{
ctxt.rx_count = 0;
ctxt.tx_count = 0;
@ -63,7 +63,6 @@ void nas::init(usim_interface_nas *usim_,
gw = gw_;
nas_log = nas_log_;
state = EMM_STATE_DEREGISTERED;
plmn_selection = PLMN_NOT_SELECTED;
if (!usim->get_home_plmn_id(&home_plmn)) {
nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n");
@ -94,105 +93,197 @@ emm_state_t nas::get_state() {
* UE interface
******************************************************************************/
void nas::attach_request() {
/** Blocking function to Attach to the network and establish RRC connection if not established.
* The function returns true if the UE could attach correctly or false in case of error or timeout during attachment.
*
*/
bool nas::attach_request() {
rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS];
int nof_plmns = 0;
uint32_t tout = 0;
nas_log->info("Attach Request\n");
if (state == EMM_STATE_DEREGISTERED) {
state = EMM_STATE_REGISTERED_INITIATED;
if (plmn_selection == PLMN_NOT_SELECTED) {
nas_log->info("Starting PLMN Search...\n");
rrc->plmn_search();
} else if (plmn_selection == PLMN_SELECTED) {
nas_log->info("Selecting PLMN %s\n", plmn_id_to_string(current_plmn).c_str());
rrc->plmn_select(current_plmn);
selecting_plmn = current_plmn;
}
} else if (state == EMM_STATE_REGISTERED) {
nas_log->info("NAS state is registered, selecting current PLMN\n");
rrc->plmn_select(current_plmn, true);
} else {
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
switch (state) {
case EMM_STATE_DEREGISTERED:
// Search PLMN is not selected
if (!plmn_is_selected) {
nas_log->info("No PLMN selected. Starting PLMN Search...\n");
nof_plmns = rrc->plmn_search(found_plmns);
if (nof_plmns > 0) {
// Save PLMNs
known_plmns.clear();
for (int i=0;i<nof_plmns;i++) {
known_plmns.push_back(found_plmns[i].plmn_id);
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(found_plmns[i].plmn_id).c_str(),
found_plmns[i].tac);
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(found_plmns[i].plmn_id).c_str(),
found_plmns[i].tac);
}
select_plmn();
} else if (nof_plmns == 0) {
nas_log->warning("Did not find any PLMN in the set of frequencies\n");
return false;
} else if (nof_plmns < 0) {
nas_log->error("Error while searching for PLMNs\n");
return false;
}
}
// Select PLMN in request establishment of RRC connection
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("PLMN is not selected because no suitable PLMN was found\n");
}
break;
case EMM_STATE_REGISTERED:
if (rrc->is_connected()) {
nas_log->info("NAS is already registered and RRC connected\n");
return true;
} 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;
}
}
}
break;
default:
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
}
return false;
}
void nas::deattach_request() {
bool nas::deattach_request() {
state = EMM_STATE_DEREGISTERED_INITIATED;
nas_log->info("Dettach request not supported\n");
return false;
}
/*******************************************************************************
* RRC interface
******************************************************************************/
bool nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
bool nas::is_attached() {
return state == EMM_STATE_REGISTERED;
}
// Check if already registered
for (uint32_t i=0;i<known_plmns.size();i++) {
if (plmn_id.mcc == known_plmns[i].mcc && plmn_id.mnc == known_plmns[i].mnc) {
nas_log->info("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED);
selecting_plmn = plmn_id;
return true;
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");
}
return false;
} else {
nas_log->error("Could not establish RRC connection\n");
}
}
}
// Save if new PLMN
known_plmns.push_back(plmn_id);
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(),
tracking_area_code);
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(),
tracking_area_code);
void nas::rrc_connection_failure() {
nas_log->debug("Received RRC Connection Failure\n");
rrc_connection_is_failure = true;
}
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED);
selecting_plmn = plmn_id;
/* Internal function that requests RRC connection, waits for positive or negative response and returns true/false
*/
bool nas::rrc_connect() {
if (rrc->is_connected()) {
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);
}
} else {
nas_log->warning("Could initiate RRC connection request\n");
}
return false;
}
// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection
void nas::plmn_search_end() {
if (known_plmns.size() > 0) {
if (home_plmn.mcc != known_plmns[0].mcc && home_plmn.mnc != known_plmns[0].mnc) {
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
}
rrc->plmn_select(known_plmns[0], state == EMM_STATE_REGISTERED_INITIATED);
/* 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 {
nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n");
if (state == EMM_STATE_REGISTERED_INITIATED && plmn_selection == PLMN_NOT_SELECTED) {
rrc->plmn_search();
}
send_attach_request();
}
}
bool nas::is_attached() {
return state == EMM_STATE_REGISTERED;
}
state = EMM_STATE_REGISTERED_INITIATED;
bool nas::is_attaching() {
return state == EMM_STATE_REGISTERED_INITIATED;
// Wait until NAS is registered
tout = 0;
while (tout < 10000 && state == EMM_STATE_REGISTERED_INITIATED) {
usleep(1000);
tout++;
}
if (state == EMM_STATE_REGISTERED) {
return true;
} else if (state == EMM_STATE_DEREGISTERED) {
nas_log->error("Received attach reject while trying to attach\n");
} else {
nas_log->error("Timed out while trying to attach\n");
}
return false;
}
void nas::notify_connection_setup() {
nas_log->debug("State = %s\n", emm_state_text[state]);
if (EMM_STATE_REGISTERED_INITIATED == state) {
send_attach_request();
} else {
send_service_request();
void nas::select_plmn() {
plmn_is_selected = false;
// First find if Home PLMN is available
for (uint32_t i=0;i<known_plmns.size();i++) {
if (known_plmns[i].mcc == home_plmn.mcc && known_plmns[i].mnc == home_plmn.mnc) {
nas_log->info("Selecting Home PLMN Id=%s\n", plmn_id_to_string(known_plmns[i]).c_str());
plmn_is_selected = true;
current_plmn = known_plmns[i];
return;
}
}
// If not, select the first available PLMN
if (known_plmns.size() > 0) {
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
plmn_is_selected = true;
current_plmn = known_plmns[0];
}
}
void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
uint8 pd = 0;
uint8 msg_type = 0;
@ -534,8 +625,6 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
// FIXME: Setup the default EPS bearer context
state = EMM_STATE_REGISTERED;
current_plmn = selecting_plmn;
plmn_selection = PLMN_SELECTED;
ctxt.rx_count++;

File diff suppressed because it is too large Load Diff

@ -380,7 +380,7 @@ int main(int argc, char *argv[])
radio.set_tx_freq(prog_args.rf_tx_freq);
// Instruct the PHY to configure PRACH parameters and sync to current cell
while(!my_phy.sync_status()) {
while(!my_phy.cell_is_camping()) {
usleep(20000);
}

@ -196,7 +196,7 @@ int main(int argc, char *argv[])
bool running = true;
while(running) {
if (bch_decoded && my_phy.sync_status()) {
if (bch_decoded && my_phy.cell_is_camping()) {
uint32_t tti = my_phy.get_current_tti();
// SIB1 is scheduled in subframe #5 of even frames, try to decode next frame SIB1
@ -206,7 +206,7 @@ int main(int argc, char *argv[])
total_pkts++;
}
usleep(30000);
if (bch_decoded && my_phy.sync_status() && total_pkts > 0) {
if (bch_decoded && my_phy.cell_is_camping() && total_pkts > 0) {
if (srslte_verbose == SRSLTE_VERBOSE_NONE && srsapps_verbose == 0) {
float gain = prog_args.rf_gain;
if (gain < 0) {

@ -81,8 +81,10 @@ public:
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
uint32_t get_last_sdu_len() { return last_sdu_len; }
void plmn_search() {};
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool con_req) {};
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;}
bool is_connected() {return true;}
uint16_t get_mcc() { return mcc; }
uint16_t get_mnc() { return mnc; }
@ -190,7 +192,6 @@ int mme_attach_request_test()
nas.init(&usim, &rrc_dummy, &gw, &nas_log, nas_cfg);
nas.attach_request();
nas.notify_connection_setup();
// check length of generated NAS SDU
if (rrc_dummy.get_last_sdu_len() > 3) {

Loading…
Cancel
Save