From f88f465c9718542cefaa18b80206301d399e158d Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 19 Mar 2018 14:14:51 +0100 Subject: [PATCH 01/52] Refactored NAS/RRC/PHY cell_search/selection procedures --- lib/examples/pdsch_ue.c | 7 +- lib/include/srslte/common/threads.h | 2 +- lib/include/srslte/interfaces/ue_interfaces.h | 61 +- lib/src/radio/radio.cc | 1 + srsue/hdr/mac/mac.h | 27 +- srsue/hdr/phy/phch_recv.h | 219 ++- srsue/hdr/phy/phy.h | 13 +- srsue/hdr/ue.h | 2 + srsue/hdr/ue_base.h | 2 + srsue/hdr/upper/nas.h | 25 +- srsue/hdr/upper/rrc.h | 158 +- srsue/hdr/upper/rrc_common.h | 18 +- srsue/src/mac/mac.cc | 94 +- srsue/src/main.cc | 10 +- srsue/src/phy/phch_recv.cc | 997 ++++++------ srsue/src/phy/phy.cc | 34 +- srsue/src/ue.cc | 11 +- srsue/src/upper/nas.cc | 237 ++- srsue/src/upper/rrc.cc | 1359 ++++++++--------- srsue/test/phy/ue_itf_test_prach.cc | 2 +- srsue/test/phy/ue_itf_test_sib1.cc | 4 +- srsue/test/upper/nas_test.cc | 7 +- 22 files changed, 1734 insertions(+), 1556 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index fc99fdc9a..084dc682b 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -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) { diff --git a/lib/include/srslte/common/threads.h b/lib/include/srslte/common/threads.h index 949ece195..3a2b78d2b 100644 --- a/lib/include/srslte/common/threads.h +++ b/lib/include/srslte/common/threads.h @@ -88,7 +88,7 @@ public: period_us = period_us_; start(priority); } - void stop() { + void stop_thread() { run_enable = false; wait_thread_finish(); } diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index bea0cb05c..c05ab4231 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -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; diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 7008790a3..7ef925f60 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -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) diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index f4b0ffe3a..1f41c5bc0 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -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: diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 378dfb8f9..cf4a8f860 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -28,6 +28,7 @@ #define UEPHYRECV_H #include +#include #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 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 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 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 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; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 95140f8cd..a00cfd5a5 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -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); diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index 2aa7157e2..c7cb7c9c8 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -69,6 +69,8 @@ public: bool init(all_args_t *args_); void stop(); + bool attach(); + bool deattach(); bool is_attached(); void start_plot(); diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 8e1a41478..863d3b71b 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -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; diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 8a1fd6ae3..afa9b3343 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -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 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); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 5c9899eab..f91d35354 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -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 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::iterator delete_neighbour(std::vector::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); diff --git a/srsue/hdr/upper/rrc_common.h b/srsue/hdr/upper/rrc_common.h index 259d08fd7..2339a08a2 100644 --- a/srsue/hdr/upper/rrc_common.h +++ b/srsue/hdr/upper/rrc_common.h @@ -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 diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 2531faafc..4f49d6d01 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -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 diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 8753e7630..2912f7cd1 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -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(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 8227a2882..4695c3946 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -96,6 +96,8 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma // Start intra-frequency measurement intra_freq_meas.init(worker_com, rrc, log_h); + pthread_mutex_init(&rrc_mutex, NULL); + reset(); running = true; // Start main thread @@ -112,6 +114,7 @@ phch_recv::~phch_recv() { free(sf_buffer[i]); } } + pthread_mutex_destroy(&rrc_mutex); srslte_ue_sync_free(&ue_sync); } @@ -124,391 +127,240 @@ void phch_recv::stop() void phch_recv::reset() { + radio_is_overflow = false; + radio_overflow_return = false; in_sync_cnt = 0; out_of_sync_cnt = 0; tx_mutex_cnt = 0; - phy_state = IDLE; time_adv_sec = 0; next_offset = 0; cell_is_set = false; srate_mode = SRATE_NONE; - current_earfcn = 0; + current_earfcn = -1; sfn_p.reset(); measure_p.reset(); search_p.reset(); + phy_state.go_idle(); } -void phch_recv::radio_error() -{ - log_h->error("SYNC: Receiving from radio.\n"); - reset(); - phy_state = CELL_SEARCH; - // Need to find a method to effectively reset radio, reloading the driver does not work - radio_h->reset(); -} -void phch_recv::set_cfo(float cfo) { - srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); -} -void phch_recv::set_agc_enable(bool enable) -{ - do_agc = enable; - if (do_agc) { - if (running && radio_h) { - srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, radio_h->get_rx_gain()); - search_p.set_agc_enable(true); - } else { - fprintf(stderr, "Error setting AGC: PHY not initiatec\n"); - } - } else { - fprintf(stderr, "Error stopping AGC: not implemented\n"); - } -} -void phch_recv::set_time_adv_sec(float time_adv_sec) -{ - this->time_adv_sec = time_adv_sec; -} -void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) -{ - if (worker_com->args->cfo_integer_enabled) { - srslte_ue_sync_set_cfo_i_enable(q, true); - } - srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_pss_ema); - srslte_ue_sync_set_cfo_tol(q, worker_com->args->cfo_correct_tol_hz); - srslte_ue_sync_set_cfo_loop_bw(q, worker_com->args->cfo_loop_bw_pss, worker_com->args->cfo_loop_bw_ref, - worker_com->args->cfo_loop_pss_tol, - worker_com->args->cfo_loop_ref_min, - worker_com->args->cfo_loop_pss_tol, - worker_com->args->cfo_loop_pss_conv); - q->strack.pss.chest_on_filter = worker_com->args->sic_pss_enabled; +/** + * Higher layers API. + * + * These functions are called by higher layers (RRC) to control the Cell search and cell selection procedures. + * They manipulate the SYNC state machine to switch states and perform different actions. In order to ensure mutual + * exclusion any change of state variables such as cell configuration, MIB decoder, etc. must be done while the + * SYNC thread is in IDLE. + * + * Functions will manipulate the SYNC state machine (sync_state class) to jump to states and wait for result then + * return the result to the higher layers. + * + * Cell Search: + * It's the process of searching for cells in the bands or set of EARFCNs supported by the UE. Cell search is performed + * at 1.92 MHz sampling rate and involves PSS/SSS synchronization (PCI extraction) and MIB decoding for number of Ports and PRB. + * + * + * Cell Select: + * It's the process of moving the cell state from IDLE->CAMPING or from CAMPING->IDLE->CAMPING when RRC indicates to + * select a different cell. + * + * If it is a new cell, the reconfiguration must take place while sync_state is on IDLE. + * + * cell_search() and cell_select() functions can not be called concurrently. A mutex is used to prevent it from happening. + * + */ - // Disable CP based CFO estimation during find - if (cfo != 0) { - q->cfo_current_value = cfo/15000; - q->cfo_is_copied = true; - q->cfo_correct_enable_find = true; - 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); - } +/* A call to cell_search() finds the strongest cell in the set of supported EARFCNs. When the first cell is found, + * returns 1 and stores cell information and RSRP values in the pointers (if provided). If a cell is not found in the current + * frequency it moves to the next one and the next call to cell_search() will look in the next EARFCN in the set. + * If no cells are found in any frequency it returns 0. If error returns -1. + */ - sss_alg_t sss_alg = SSS_FULL; - if (!worker_com->args->sss_algorithm.compare("diff")) { - sss_alg = SSS_DIFF; - } else if (!worker_com->args->sss_algorithm.compare("partial")) { - sss_alg = SSS_PARTIAL_3; - } else if (!worker_com->args->sss_algorithm.compare("full")) { - sss_alg = SSS_FULL; - } else { - Warning("SYNC: Invalid SSS algorithm %s. Using 'full'\n", worker_com->args->sss_algorithm.c_str()); - } - srslte_sync_set_sss_algorithm(&q->strack, (sss_alg_t) sss_alg); - srslte_sync_set_sss_algorithm(&q->sfind, (sss_alg_t) sss_alg); -} +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 ret = phy_interface_rrc::ERROR; -bool phch_recv::set_cell() { - cell_is_set = false; + pthread_mutex_lock(&rrc_mutex); - // Set cell in all objects - if (srslte_ue_sync_set_cell(&ue_sync, cell)) { - Error("SYNC: Setting cell: initiating ue_sync\n"); - return false; - } - measure_p.set_cell(cell); - sfn_p.set_cell(cell); - worker_com->set_cell(cell); - intra_freq_meas.set_primay_cell(current_earfcn, cell); + // Move state to IDLE + Info("Cell Search: Start EARFCN index=%d/%d\n", cellsearch_earfcn_index, earfcn.size()); + phy_state.go_idle(); - for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { - if (!((phch_worker *) workers_pool->get_worker(i))->set_cell(cell)) { - Error("SYNC: Setting cell: initiating PHCH worker\n"); - return false; - } + if (current_earfcn != (int) earfcn[cellsearch_earfcn_index]) { + current_earfcn = (int) earfcn[cellsearch_earfcn_index]; + Info("Cell Search: changing frequency to EARFCN=%d\n", current_earfcn); + set_frequency(); } - // Set options defined in expert section - set_ue_sync_opts(&ue_sync, search_p.get_last_cfo()); - - // Reset ue_sync and set CFO/gain from search procedure - srslte_ue_sync_reset(&ue_sync); - - cell_is_set = true; - - return cell_is_set; -} - -void phch_recv::set_earfcn(std::vector earfcn) { - this->earfcn = earfcn; -} - -void phch_recv::force_freq(float dl_freq, float ul_freq) { - this->dl_freq = dl_freq; - this->ul_freq = ul_freq; -} + // Move to CELL SEARCH and wait to finish + Info("Cell Search: Setting Cell search state\n"); + phy_state.run_cell_search(); -void phch_recv::reset_sync() { + // Check return state + switch(cell_search_ret) { + case search::CELL_FOUND: + // If a cell is found, configure it, synchronize and measure it + if (set_cell()) { - Info("SYNC: Reset. Going to Cell Select\n"); - sfn_p.reset(); - search_p.reset(); - measure_p.reset(); - srslte_ue_sync_reset(&ue_sync); - phy_state = CELL_SELECT; -} + Info("Cell Search: Setting sampling rate and synchronizing SFN...\n"); + set_sampling_rate(); + phy_state.run_sfn_sync(); -void phch_recv::cell_search_inc() -{ - cur_earfcn_index++; - if (cur_earfcn_index >= 0) { - if (cur_earfcn_index >= (int) earfcn.size()) { - Info("SYNC: Cell Search finished. Going to IDLE\n"); - cur_earfcn_index = 0; - phy_state = IDLE; - rrc->earfcn_end(); - } else { - Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); - if (current_earfcn != earfcn[cur_earfcn_index]) { - current_earfcn = earfcn[cur_earfcn_index]; - set_frequency(); + 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 (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: + log_h->info("Cell Search: Could not synchronize with cell\n"); + ret = phy_interface_rrc::CELL_NOT_FOUND; + break; + } + } else { + Error("Cell Search: Setting cell PCI=%d, nof_prb=%d\n", cell.id, cell.nof_prb); } - phy_state = CELL_SEARCH; - } + 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; + } + break; + default: + Error("Cell Search: while receiving samples\n"); + radio_error(); + break; } -} -void phch_recv::cell_search_next(bool reset) { - if (reset) { - cur_earfcn_index = -1; - } - cell_search_inc(); + pthread_mutex_unlock(&rrc_mutex); + return ret; } -void phch_recv::cell_search_start() { - if (phy_state == CELL_CAMP) { - Warning("SYNC: Can't start cell search procedure while camping on cell\n"); +/* Cell select synchronizes to a new cell (e.g. during HO or during cell reselection on IDLE) or + * re-synchronizes with the current cell if cell argument is NULL + */ +bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { + pthread_mutex_lock(&rrc_mutex); + + // Move state to IDLE + if (!new_cell) { + Info("Cell Select: Starting cell resynchronization\n"); } else { - if (earfcn.size() > 0) { - Info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); - cell_search_next(true); - } else { - Info("SYNC: Empty EARFCN list. Stopping cell search...\n"); - log_h->console("Empty EARFCN list. Stopping cell search...\n"); + if (!srslte_cell_isvalid(&cell)) { + log_h->error("Cell Select: Invalid cell. ID=%d, PRB=%d, ports=%d\n", cell.id, cell.nof_prb, cell.nof_ports); + return false; } - } -} - -bool phch_recv::cell_handover(srslte_cell_t cell) -{ - if (!srslte_cell_isvalid(&cell)) { - log_h->error("Received HO command to invalid cell. ID=%d, PRB=%d, ports=%d\n", cell.id, cell.nof_prb, cell.nof_ports); - return false; + Info("Cell Select: Starting cell selection for PCI=%d, EARFCN=%d\n", new_cell->cell.id, new_cell->earfcn); } + // Wait for any pending PHICH int cnt = 0; while(worker_com->is_any_pending_ack() && cnt < 10) { usleep(1000); cnt++; - log_h->info("Cell HO: Waiting pending PHICH\n"); + Info("Cell Select: waiting pending PHICH (cnt=%d)\n", cnt); } - bool ret = false; - this->cell = cell; - Info("Cell HO: Stopping sync with current cell\n"); - phy_state = IDLE; - cnt = 0; - while(!is_in_idle && cnt<20) { - usleep(1000); - cnt++; - } + Info("Cell Select: Going to IDLE\n"); + phy_state.go_idle(); + + /* Reset everything */ for(uint32_t i=0;iget_nof_workers();i++) { ((phch_worker*) workers_pool->get_worker(i))->reset(); } - worker_com->reset(); - if (is_in_idle) { - Info("Cell HO: Reconfiguring cell\n"); - if (set_cell()) { - Info("Cell HO: Synchronizing with new cell\n"); - phy_state = CELL_SELECT; - ret = true; - } else { - log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id); - ret = false; - } - } else { - log_h->error("Cell HO: Could not stop sync\n"); - ret = false; - } - return ret; -} - -/* interface from higher layers to select a new cell */ -void phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) -{ - Info("SYNC: Cell Reselect to EARFCN=%d, PCI=%d\n", earfcn, cell.id); - new_earfcn = earfcn; - new_cell = cell; - phy_state = CELL_RESELECT; -} -/* Perform cell (re)-selection on IDLE or CAMP */ -void phch_recv::cell_reselect() -{ - uint32_t earfcn = new_earfcn; - srslte_cell_t cell = new_cell; - - reset_sync(); + worker_com->reset(); + sfn_p.reset(); + search_p.reset(); + measure_p.reset(); + srslte_ue_sync_reset(&ue_sync); - // If we are already in the new cell, just resynchronize - if (earfcn == current_earfcn && this->cell.id == cell.id) { - log_h->info("Cell Select: Already in cell EARFCN=%d, PCI=%d\n", earfcn, cell.id); - if (srate_mode != SRATE_CAMP) { - set_sampling_rate(); - log_h->info("Cell Select: Setting Camping sampling rate\n"); + /* Reconfigure cell if necessary */ + if (new_cell) { + if (new_cell->cell.id != cell.id) { + Info("Cell Select: Reconfiguring cell\n"); + cell = new_cell->cell; + if (!set_cell()) { + Error("Cell Select: Reconfiguring cell\n"); + return false; + } } - } else { - if (earfcn != current_earfcn) { + /* Select new frequency if necessary */ + if ((int) new_cell->earfcn != current_earfcn) { + Info("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); if (set_frequency()) { - log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); + Error("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); + return false; } - current_earfcn = earfcn; - } - - this->cell = cell; - log_h->info("Cell Select: Configuring cell...\n"); - - if (set_cell()) { - log_h->info("Cell Select: Synchronizing on cell...\n"); + current_earfcn = new_cell->earfcn; } } -} - -bool phch_recv::set_frequency() -{ - double set_dl_freq = 0; - double set_ul_freq = 0; - if (this->dl_freq > 0 && this->ul_freq > 0) { - set_dl_freq = this->dl_freq; - set_ul_freq = this->ul_freq; - } else { - set_dl_freq = 1e6*srslte_band_fd(current_earfcn); - set_ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn)); + /* Change sampling rate if necessary */ + if (srate_mode != SRATE_CAMP) { + set_sampling_rate(); + log_h->info("Cell Select: Setting CAMPING sampling rate\n"); } - if (set_dl_freq > 0 && set_ul_freq > 0) { - log_h->info("SYNC: Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", - current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); - - log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", - current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); - radio_h->set_rx_freq(set_dl_freq); - radio_h->set_tx_freq(set_ul_freq); - ul_dl_factor = radio_h->get_tx_freq()/radio_h->get_rx_freq(); - - srslte_ue_sync_reset(&ue_sync); + /* SFN synchronization */ + phy_state.run_sfn_sync(); - return true; - } else { - log_h->error("SYNC: Cell Search: Invalid EARFCN=%d\n", current_earfcn); - return false; - } -} - -float phch_recv::get_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_sampling_rate() -{ - current_srate = (float) srslte_sampling_freq_hz(cell.nof_prb); - current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); - if (current_srate != -1) { - Info("SYNC: Setting sampling rate %.2f MHz\n", current_srate/1000000); - -#if 0 - if (((int) current_srate / 1000) % 3072 == 0) { - radio_h->set_master_clock_rate(30.72e6); - } else { - radio_h->set_master_clock_rate(23.04e6); - } -#else - if (current_srate < 10e6) { - radio_h->set_master_clock_rate(4 * current_srate); - } else { - radio_h->set_master_clock_rate(current_srate); - } -#endif - - srate_mode = SRATE_CAMP; - radio_h->set_rx_srate(current_srate); - radio_h->set_tx_srate(current_srate); - } else { - Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb); - } -} - -uint32_t phch_recv::get_current_tti() { - return tti; -} - -bool phch_recv::status_is_sync() { - return phy_state == CELL_CAMP; -} - -void phch_recv::get_current_cell(srslte_cell_t *cell_, uint32_t *earfcn) { - if (cell_) { - memcpy(cell_, &cell, sizeof(srslte_cell_t)); - } - if (earfcn) { - *earfcn = current_earfcn; + 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(); + ret = true; + break; + case sfn_sync::ERROR: + Error("Cell Select: Error receiving samples when synchronizing SFN\n"); + radio_error(); + break; + default: + Info("Cell Select: Could not synchronize SFN\n"); + break; } -} -int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) -{ - if (radio_h->rx_now(data, nsamples, rx_time)) { - int offset = nsamples - current_sflen; - if (abs(offset) < 10 && offset != 0) { - next_offset = offset; - } else if (nsamples < 10) { - next_offset = nsamples; - } - - log_h->debug("SYNC: received %d samples from radio\n", nsamples); - - return nsamples; - } else { - return -1; - } + pthread_mutex_unlock(&rrc_mutex); + return ret; } -double phch_recv::set_rx_gain(double gain) { - return radio_h->set_rx_gain_th(gain); +bool phch_recv::cell_is_camping() { + return phy_state.is_camping(); } @@ -516,6 +368,19 @@ double phch_recv::set_rx_gain(double gain) { /** * MAIN THREAD + * + * The main thread process the SYNC state machine. Every state except IDLE must have exclusive access to + * all variables. If any change of cell configuration must be done, the thread must be in IDLE. + * + * On each state except campling, 1 function is called and the thread jumps to the next state based on the output. + * + * It has 3 states: Cell search, SFN syncrhonization, intial measurement and camping. + * - CELL_SEARCH: Initial Cell id and MIB acquisition. Uses 1.92 MHz sampling rate + * - CELL_SFN_SYNC: Full sampling rate, uses MIB to obtain SFN. When SFN is obtained, moves to CELL_MEASURE or CELL_CAMP + * - CELL_MEASURE: RSRP/SNR measurement to determine suitability for camping. + * - CELL_CAMP: Cell camping state. Calls the PHCH workers to process subframes and mantains cell synchronization. + * - IDLE: Receives and discards received samples. Does not mantain synchronization. + * */ void phch_recv::run_thread() @@ -524,8 +389,6 @@ void phch_recv::run_thread() phch_worker *last_worker = NULL; cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; uint32_t sf_idx = 0; - phy_state = IDLE; - is_in_idle = true; cf_t *dummy_buffer[SRSLTE_MAX_PORTS]; @@ -535,95 +398,36 @@ void phch_recv::run_thread() while (running) { - if (phy_state != IDLE) { - is_in_idle = false; - } Debug("SYNC: state=%d\n", phy_state); - log_h->step(tti); log_phy_lib_h->step(tti); - - sf_idx = tti%10; - prev_state = phy_state; - - switch (phy_state) { - case CELL_SEARCH: - switch(search_p.run(&cell)) - { - case search::CELL_FOUND: - if (!srslte_cell_isvalid(&cell)) { - Error("SYNC: Detected invalid cell. Going to IDLE\n"); - phy_state = IDLE; - break; - } - if (set_cell()) { - Info("SYNC: Setting sampling rate and going to Cell Select\n"); - set_sampling_rate(); - phy_state = CELL_SELECT; - } - break; - case search::CELL_NOT_FOUND: - cell_search_inc(); - break; - default: - radio_error(); - break; - } - break; - case CELL_RESELECT: - cell_reselect(); - break; - case CELL_SELECT: - switch (sfn_p.run_subframe(&cell, &tti)) - { - case sfn_sync::SFN_FOUND: - if (prev_state != CELL_SEARCH) { - log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id); - phy_state = CELL_CAMP; - rrc->cell_camping(earfcn[cur_earfcn_index], cell); - } else { - log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id); - measure_p.reset(); - phy_state = CELL_MEASURE; - } - break; - case sfn_sync::TIMEOUT: - log_h->warning("SYNC: Timeout while synchronizing SFN\n"); - rrc->out_of_sync(); - break; - case sfn_sync::IDLE: - break; - default: - radio_error(); - break; - } - break; - case CELL_MEASURE: - - switch(measure_p.run_subframe_sync(&ue_sync, sf_idx)) - { - case measure::MEASURE_OK: - - // Calibrate measure object since worker not yet calibrated - if (worker_com->args->rssi_sensor_enabled) { - measure_p.set_rx_gain_offset(measure_p.rssi() - radio_h->get_rssi() + 30); - } else { - measure_p.set_rx_gain_offset(worker_com->args->rx_gain_offset + radio_h->get_rx_gain()); - } - - log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id); - phy_state = CELL_CAMP; - rrc->cell_camping(earfcn[cur_earfcn_index], cell, measure_p.rsrp()); - break; - case measure::IDLE: - break; - default: - radio_error(); - break; + sf_idx = tti%10; + + switch (phy_state.run_state()) { + case sync_state::CELL_SEARCH: + /* Search for a cell in the current frequency and go to IDLE. + * The function search_p.run() will not return until the search finishes + */ + cell_search_ret = search_p.run(&cell); + phy_state.state_exit(); + break; + case sync_state::SFN_SYNC: + /* 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) { + 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(); } break; - case CELL_CAMP: + case sync_state::CAMPING: worker = (phch_worker *) workers_pool->wait_worker(tti); if (worker) { @@ -648,7 +452,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(get_cfo()); + worker->set_cfo(ul_dl_factor * metrics.cfo / 15000); worker_com->set_sync_metrics(metrics); /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ @@ -674,7 +478,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, get_cfo(), worker_com->pathloss, tx_time_prach); + prach_buffer->send(radio_h, ul_dl_factor * metrics.cfo / 15000, 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); @@ -704,7 +508,7 @@ void phch_recv::run_thread() running = false; } break; - case IDLE: + case sync_state::IDLE: if (radio_h->is_init()) { uint32_t nsamples = 1920; if (current_srate > 0) { @@ -716,20 +520,76 @@ void phch_recv::run_thread() } else { usleep(1000); } - is_in_idle = true; break; } - // Increase TTI counter and trigger MAC clock (lower priority) - mac->tti_clock(tti); + /* Radio overflow detected. If CAMPING, go through SFN sync again and when + * SFN is found again go back to camping + */ + if (radio_is_overflow) { + // Overflow has occurred now while camping + 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"); + rrc->out_of_sync(); + phy_state.force_sfn_sync(); + break; + default: + break; + } + } + // If overflow occurs in any other state, it does not harm + } + + // Increase TTI counter tti = (tti+1) % 10240; } +} - for (int i=0;ierror("SYNC: Receiving from radio.\n"); + // Need to find a method to effectively reset radio, reloading the driver does not work + radio_h->reset(); } void phch_recv::in_sync() { @@ -747,7 +607,7 @@ void phch_recv::out_of_sync() { // Send RRC out-of-sync signal after 200 ms consecutive subframes Info("Out-of-sync %d/%d\n", out_of_sync_cnt, NOF_OUT_OF_SYNC_SF); out_of_sync_cnt++; - if (out_of_sync_cnt >= NOF_OUT_OF_SYNC_SF) { + if (out_of_sync_cnt == NOF_OUT_OF_SYNC_SF) { Info("Sending to RRC\n"); rrc->out_of_sync(); out_of_sync_cnt = 0; @@ -755,10 +615,214 @@ void phch_recv::out_of_sync() { } } +void phch_recv::set_cfo(float cfo) { + srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); +} + +void phch_recv::set_agc_enable(bool enable) +{ + do_agc = enable; + if (do_agc) { + if (running && radio_h) { + srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, radio_h->get_rx_gain()); + search_p.set_agc_enable(true); + } else { + fprintf(stderr, "Error setting AGC: PHY not initiatec\n"); + } + } else { + fprintf(stderr, "Error stopping AGC: not implemented\n"); + } +} + +void phch_recv::set_time_adv_sec(float time_adv_sec) +{ + this->time_adv_sec = time_adv_sec; +} + +void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) +{ + if (worker_com->args->cfo_integer_enabled) { + srslte_ue_sync_set_cfo_i_enable(q, true); + } + + srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_pss_ema); + srslte_ue_sync_set_cfo_tol(q, worker_com->args->cfo_correct_tol_hz); + srslte_ue_sync_set_cfo_loop_bw(q, worker_com->args->cfo_loop_bw_pss, worker_com->args->cfo_loop_bw_ref, + worker_com->args->cfo_loop_pss_tol, + worker_com->args->cfo_loop_ref_min, + worker_com->args->cfo_loop_pss_tol, + worker_com->args->cfo_loop_pss_conv); + + q->strack.pss.chest_on_filter = worker_com->args->sic_pss_enabled; + + // Disable CP based CFO estimation during find + if (cfo != 0) { + q->cfo_current_value = cfo/15000; + q->cfo_is_copied = true; + q->cfo_correct_enable_find = true; + 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; + } else if (!worker_com->args->sss_algorithm.compare("partial")) { + sss_alg = SSS_PARTIAL_3; + } else if (!worker_com->args->sss_algorithm.compare("full")) { + sss_alg = SSS_FULL; + } else { + Warning("SYNC: Invalid SSS algorithm %s. Using 'full'\n", worker_com->args->sss_algorithm.c_str()); + } + srslte_sync_set_sss_algorithm(&q->strack, (sss_alg_t) sss_alg); + srslte_sync_set_sss_algorithm(&q->sfind, (sss_alg_t) sss_alg); +} + +bool phch_recv::set_cell() { + + if (!phy_state.is_idle()) { + Warning("Can not change Cell while not in IDLE\n"); + 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"); + return false; + } + measure_p.set_cell(cell); + sfn_p.set_cell(cell); + worker_com->set_cell(cell); + intra_freq_meas.set_primay_cell(current_earfcn, cell); + + for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { + if (!((phch_worker *) workers_pool->get_worker(i))->set_cell(cell)) { + Error("SYNC: Setting cell: initiating PHCH worker\n"); + return false; + } + } + + // Set options defined in expert section + set_ue_sync_opts(&ue_sync, search_p.get_last_cfo()); + + // Reset ue_sync and set CFO/gain from search procedure + srslte_ue_sync_reset(&ue_sync); + + cell_is_set = true; + + return cell_is_set; +} + +void phch_recv::set_earfcn(std::vector earfcn) { + this->earfcn = earfcn; +} + +void phch_recv::force_freq(float dl_freq, float ul_freq) { + this->dl_freq = dl_freq; + this->ul_freq = ul_freq; +} + +bool phch_recv::set_frequency() +{ + double set_dl_freq = 0; + double set_ul_freq = 0; + + if (this->dl_freq > 0 && this->ul_freq > 0) { + set_dl_freq = this->dl_freq; + set_ul_freq = this->ul_freq; + } else { + set_dl_freq = 1e6*srslte_band_fd(current_earfcn); + set_ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn)); + } + if (set_dl_freq > 0 && set_ul_freq > 0) { + log_h->info("SYNC: Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", + current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); + + log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", + current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); + + radio_h->set_rx_freq(set_dl_freq); + radio_h->set_tx_freq(set_ul_freq); + ul_dl_factor = radio_h->get_tx_freq()/radio_h->get_rx_freq(); + + srslte_ue_sync_reset(&ue_sync); + + return true; + } else { + log_h->error("SYNC: Cell Search: Invalid EARFCN=%d\n", current_earfcn); + return false; + } +} + +void phch_recv::set_sampling_rate() +{ + current_srate = (float) srslte_sampling_freq_hz(cell.nof_prb); + current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); + if (current_srate != -1) { + Info("SYNC: Setting sampling rate %.2f MHz\n", current_srate/1000000); + +#if 0 + if (((int) current_srate / 1000) % 3072 == 0) { + radio_h->set_master_clock_rate(30.72e6); + } else { + radio_h->set_master_clock_rate(23.04e6); + } +#else + if (current_srate < 10e6) { + radio_h->set_master_clock_rate(4 * current_srate); + } else { + radio_h->set_master_clock_rate(current_srate); + } +#endif + + srate_mode = SRATE_CAMP; + radio_h->set_rx_srate(current_srate); + radio_h->set_tx_srate(current_srate); + } else { + Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb); + } +} + +uint32_t phch_recv::get_current_tti() { + return tti; +} + +void phch_recv::get_current_cell(srslte_cell_t *cell_, uint32_t *earfcn) { + if (cell_) { + memcpy(cell_, &cell, sizeof(srslte_cell_t)); + } + if (earfcn) { + *earfcn = current_earfcn; + } +} +int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) +{ + if (radio_h->rx_now(data, nsamples, rx_time)) { + int offset = nsamples - current_sflen; + if (abs(offset) < 10 && offset != 0) { + next_offset = offset; + } else if (nsamples < 10) { + next_offset = nsamples; + } + log_h->debug("SYNC: received %d samples from radio\n", nsamples); + return nsamples; + } else { + return -1; + } +} +double phch_recv::set_rx_gain(double gain) { + return radio_h->set_rx_gain_th(gain); +} @@ -901,6 +965,10 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) Info("SYNC: MIB Decoded: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", cell->id, cell->nof_prb, cell->nof_ports, cfo/1000); + if (!srslte_cell_isvalid(cell)) { + Error("SYNC: Detected invalid cell.\n"); + return CELL_NOT_FOUND; + } return CELL_FOUND; } else if (ret == 0) { Warning("SYNC: Found PSS but could not decode PBCH\n"); @@ -927,11 +995,11 @@ phch_recv::sfn_sync::~sfn_sync() srslte_ue_mib_free(&ue_mib); } -void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout) +void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_subframes) { this->log_h = log_h; this->ue_sync = ue_sync; - this->timeout = timeout; + this->timeout = nof_subframes; for (int i=0;ibuffer[i] = buffer[i]; @@ -954,8 +1022,8 @@ bool phch_recv::sfn_sync::set_cell(srslte_cell_t cell) void phch_recv::sfn_sync::reset() { - srslte_ue_mib_reset(&ue_mib); cnt = 0; + srslte_ue_mib_reset(&ue_mib); } phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only) @@ -1010,7 +1078,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c cnt++; if (cnt >= timeout) { cnt = 0; - return TIMEOUT; + return SFN_NOFOUND; } return IDLE; @@ -1037,7 +1105,6 @@ void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h Error("SYNC: Initiating ue_dl_measure\n"); return; } - srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); reset(); } @@ -1101,7 +1168,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn } phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer, - int offset, + uint32_t offset, uint32_t sf_idx, uint32_t max_sf) { @@ -1110,18 +1177,17 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in ret_code ret = IDLE; offset = offset-sf_len/2; - while (offset < 0 && sf_idx < max_sf) { + if (offset < 0) { offset += sf_len; sf_idx ++; } - - // Fine-tune offset using RS -#ifdef FINE_TUNE_OFFSET_WITH_RS float max_rsrp = -200; int best_test_offset = 0; int test_offset = 0; bool found_best = false; + + // Fine-tune offset using RS for (uint32_t n=0;n<5;n++) { test_offset = offset-2+n; @@ -1145,14 +1211,11 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in } } - Debug("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); - offset = found_best?best_test_offset:offset; -#endif - - if (offset >= 0 && offset < (int) sf_len*max_sf) { + if (offset >= 0 && offset < sf_len*max_sf) { uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; + Debug("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); final_offset = offset; @@ -1180,25 +1243,25 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) return ERROR; } - float rsrp = srslte_chest_dl_get_rsrp_neighbour(&ue_dl.chest); + float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); float snr = srslte_chest_dl_get_snr(&ue_dl.chest); float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb)); if (cnt == 0) { - mean_rsrp = rsrp; - mean_rsrq = rsrq; - mean_snr = snr; - mean_rssi = rssi; + mean_rsrp = rsrp; + mean_rsrq = rsrq; + mean_snr = snr; + mean_rssi = rssi; } else { - mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); - mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); - mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); - mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); + mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); + mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); + mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); + mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); } cnt++; - log_h->debug("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, corr-RSRP=%.1f dBm, SNR=%.1f dB\n", + log_h->debug("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", cnt, nof_subframes, sf_idx, rsrp, snr); if (cnt >= nof_subframes) { @@ -1228,6 +1291,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 uint32_t max_sf_size = SRSLTE_SF_LEN(max_fft_sz); sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size); + input_cfo_corrected = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*15*max_sf_size); measure_p.init(sf_buffer, log_h, 1, max_sf_window); @@ -1236,7 +1300,6 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 fprintf(stderr, "Error initiating sync_find\n"); return; } - srslte_sync_set_sss_algorithm(&sync_find, SSS_FULL); srslte_sync_cp_en(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_threshold(&sync_find, 1.7); @@ -1250,7 +1313,8 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 srslte_sync_set_sss_eq_enable(&sync_find, true); sync_find.pss.chest_on_filter = true; - sync_find.sss_channel_equalize = false; + + sync_find.sss_channel_equalize = true; reset(); } @@ -1261,12 +1325,6 @@ void phch_recv::scell_recv::reset() measure_p.reset(); } -void phch_recv::scell_recv::deinit() -{ - srslte_sync_free(&sync_find); - free(sf_buffer[0]); -} - int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS]) { uint32_t fft_sz = srslte_symbol_sz(cell.nof_prb); @@ -1341,21 +1399,28 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, found_cell.nof_ports = 1; // Use port 0 only for measurement measure_p.set_cell(found_cell); + // Correct CFO + /* + srslte_cfo_correct(&sync_find.cfo_corr_frame, + input_buffer, + input_cfo_corrected, + -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); + */ + switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { case measure::MEASURE_OK: // Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) { - cells[nof_cells].pci = found_cell.id; cells[nof_cells].rsrp = measure_p.rsrp(); cells[nof_cells].rsrq = measure_p.rsrq(); cells[nof_cells].offset = measure_p.frame_st_idx(); Info( - "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, nof_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", + "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, - sf_idx, nof_sf, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); + sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); nof_cells++; @@ -1405,7 +1470,7 @@ void phch_recv::meas_reset() { } int phch_recv::meas_start(uint32_t earfcn, int pci) { - if (earfcn == current_earfcn) { + if ((int) earfcn == current_earfcn) { worker_com->pcell_meas_enabled = true; if (pci != (int) cell.id) { intra_freq_meas.add_cell(pci); @@ -1419,7 +1484,7 @@ int phch_recv::meas_start(uint32_t earfcn, int pci) { } int phch_recv::meas_stop(uint32_t earfcn, int pci) { - if (earfcn == current_earfcn) { + if ((int) earfcn == current_earfcn) { intra_freq_meas.rem_cell(pci); return 0; } else { @@ -1436,11 +1501,11 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, receive_enabled = false; // Start scell - scell.init(log_h, common->args->sic_pss_enabled, common->args->intra_freq_meas_len_ms); + scell.init(log_h, common->args->sic_pss_enabled, INTRA_FREQ_MEAS_LEN_MS); - search_buffer = (cf_t*) srslte_vec_malloc(common->args->intra_freq_meas_len_ms*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); + search_buffer = (cf_t*) srslte_vec_malloc(INTRA_FREQ_MEAS_LEN_MS*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); - if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*common->args->intra_freq_meas_len_ms*2*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { + if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*INTRA_FREQ_MEAS_LEN_MS*2*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { return; } @@ -1455,12 +1520,6 @@ void phch_recv::intra_measure::stop() { wait_thread_finish(); } -phch_recv::intra_measure::~intra_measure() { - srslte_ringbuffer_free(&ring_buffer); - scell.deinit(); - free(search_buffer); -} - void phch_recv::intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t cell) { this->current_earfcn = earfcn; current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); @@ -1510,7 +1569,7 @@ void phch_recv::intra_measure::rem_cell(int pci) { void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples) { if (receive_enabled) { - if ((tti%common->args->intra_freq_meas_period_ms) == 0) { + if ((tti%INTRA_FREQ_MEAS_PERIOD_MS) == 0) { receiving = true; receive_cnt = 0; measure_tti = tti; @@ -1522,7 +1581,7 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples receiving = false; } else { receive_cnt++; - if (receive_cnt == common->args->intra_freq_meas_len_ms) { + if (receive_cnt == INTRA_FREQ_MEAS_LEN_MS) { tti_sync.increase(); receiving = false; } @@ -1541,8 +1600,8 @@ void phch_recv::intra_measure::run_thread() if (running) { // Read data from buffer and find cells in it - srslte_ringbuffer_read(&ring_buffer, search_buffer, common->args->intra_freq_meas_len_ms*current_sflen*sizeof(cf_t)); - int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, common->args->intra_freq_meas_len_ms, info); + srslte_ringbuffer_read(&ring_buffer, search_buffer, INTRA_FREQ_MEAS_LEN_MS*current_sflen*sizeof(cf_t)); + int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, INTRA_FREQ_MEAS_LEN_MS, info); receiving = false; for (int i=0;iget_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;iinfo("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;iinfo("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;iinfo("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++; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index e419ea710..d3ae1e341 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -48,13 +48,13 @@ namespace srsue { rrc::rrc() :state(RRC_STATE_IDLE) ,drb_up(false) - ,sysinfo_index(0) ,serving_cell(NULL) { n310_cnt = 0; n311_cnt = 0; serving_cell = new cell_t(); neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); + initiated = false; } rrc::~rrc() @@ -97,18 +97,12 @@ void rrc::init(phy_interface_rrc *phy_, // Use MAC timers mac_timers = mac_timers_; state = RRC_STATE_IDLE; - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; + plmn_is_selected = false; - ho_syncing = false; - - thread_running = true; - start(); + security_is_activated = false; pthread_mutex_init(&mutex, NULL); - first_stimsi_attempt = false; - args.ue_category = SRSLTE_UE_CATEGORY; args.supported_bands[0] = 7; args.nof_supported_bands = 1; @@ -125,12 +119,11 @@ void rrc::init(phy_interface_rrc *phy_, // Register logging handler with liblte_rrc liblte_rrc_log_register_handler(this, liblte_rrc_handler); - nof_sib1_trials = 0; - last_win_start = 0; + cell_clean_cnt = 0; - pending_mob_reconf = false; + ho_start = false; - connection_requested = false; + pending_mob_reconf = false; // Set default values for all layers set_rrc_default(); @@ -140,15 +133,11 @@ void rrc::init(phy_interface_rrc *phy_, measurements.init(this); // set seed for rand (used in attach) srand(time(NULL)); -} -void rrc::stop() { - thread_running = false; - wait_thread_finish(); + initiated = true; } -void rrc::run_tti(uint32_t tti) { - measurements.run_tti(tti); +void rrc::stop() { } rrc_state_t rrc::get_state() { @@ -156,7 +145,7 @@ rrc_state_t rrc::get_state() { } bool rrc::is_connected() { - return (state >= RRC_STATE_CONNECTED && state < RRC_STATE_LEAVE_CONNECTED); + return (RRC_STATE_CONNECTED == state); } bool rrc::have_drb() { @@ -172,143 +161,43 @@ void rrc::set_args(rrc_args_t *args) { * RRC State Machine * */ -void rrc::run_thread() { - - uint32_t failure_test = 0; - uint32_t cell_clean_cnt = 0; - - while (thread_running) { - - switch(state) { - /* Procedures in IDLE state 36.304 Sec 4 */ - case RRC_STATE_IDLE: - // If camping on the cell, it will receive SI and paging from PLMN - if (phy->sync_status()) { - // If attempting to attach, reselect cell - if (nas->is_attaching()) { - rrc_log->info("RRC IDLE: NAS has pending data and camping on cell, connecting...\n"); - plmn_select_rrc(selected_plmn_id); - } - // If not camping on a cell - } else { - // If NAS is attached, perform cell reselection on current PLMN - if (nas->is_attached()) { - rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n"); - plmn_select_rrc(selected_plmn_id); - } else if (nas->is_attaching()) { - rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n"); - plmn_search(); - } - // If not attached, PLMN selection will be triggered from higher layers - } - break; - case RRC_STATE_PLMN_START: - rrc_log->info("RRC PLMN Search: Starting cell search\n"); - plmn_select_timeout = 0; - phy->cell_search_start(); - state = RRC_STATE_PLMN_SELECTION; - break; - case RRC_STATE_PLMN_SELECTION: - plmn_select_timeout++; - if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { - rrc_log->info("RRC PLMN Search: timeout expired\n"); - rrc_log->console("\nRRC PLMN Search: timeout expired.\n"); - state = RRC_STATE_IDLE; - } - break; - case RRC_STATE_CELL_SELECTING: - - /* During cell selection, apply SIB configurations if available or receive them if not. - * Cell is selected when all SIBs downloaded or applied. - */ - if (phy->sync_status()) { - if (!serving_cell->has_sib1()) { - si_acquire_state = SI_ACQUIRE_SIB1; - sysinfo_index = 0; - } else if (!serving_cell->has_sib2()) { - si_acquire_state = SI_ACQUIRE_SIB2; - } else { - apply_sib2_configs(serving_cell->sib2ptr()); - state = RRC_STATE_CELL_SELECTED; - } - run_si_acquisition_procedure(); - } - break; - case RRC_STATE_CELL_SELECTED: - - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - - /* The cell is selected when the SIBs are received and applied. - * If we were in RRC_CONNECTED and arrive here it means a RLF occurred and we are in Reestablishment procedure. - * If T311 is running means there is a reestablishment in progress, send ConnectionReestablishmentRequest. - * If not, do a ConnectionRequest if NAS is established or go to IDLE an camp on cell otherwise. - */ - if (mac_timers->timer_get(t311)->is_running()) { - // - rrc_log->info("RRC Cell Selected: Sending connection reestablishment...\n"); - con_restablish_cell_reselected(); - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; - } else if (nas->is_attaching() || connection_requested) { - rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - connection_requested = false; - send_con_request(); - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; - } else { - rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n"); - mac->pcch_start_rx(); - state = RRC_STATE_LEAVE_CONNECTED; - } - break; - case RRC_STATE_CONNECTING: - connecting_timeout++; - if (connecting_timeout >= RRC_CONNECTING_TIMEOUT) { - // Select another cell - rrc_log->info("RRC Connecting: timeout expired. Selecting next cell\n"); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; +void rrc::run_tti(uint32_t tti) { + + if (!initiated) { + return; + } + + rrc_log->debug("State %s\n", rrc_state_text[state]); + switch(state) { + case RRC_STATE_IDLE: + // 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"); + if (!cell_selection()) { + // If can not camp on any cell, search again for new cells + cell_search(); } - break; - case RRC_STATE_CONNECTED: - /* - failure_test++; - if (failure_test >= 100) { - mac_interface_rrc::ue_rnti_t ue_rnti; - mac->get_rntis(&ue_rnti); - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, ue_rnti.crnti); - }*/ - // Take measurements, cell reselection, etc - break; - case RRC_STATE_HO_PREPARE: - if (ho_prepare()) { - state = RRC_STATE_HO_PROCESS; - } else { - state = RRC_STATE_CONNECTED; + } + break; + case RRC_STATE_CONNECTED: + if (ho_start) { + ho_start = false; + if (!ho_prepare()) { + con_reconfig_failed(); } - break; - case RRC_STATE_HO_PROCESS: - // wait for HO to finish - break; - case RRC_STATE_LEAVE_CONNECTED: - usleep(60000); + } + measurements.run_tti(tti); + if (go_idle) { leave_connected(); - // Move to RRC_IDLE - state = RRC_STATE_IDLE; - break; - default: - break; - } - if (state == RRC_STATE_CONNECTED || RRC_STATE_IDLE) { - cell_clean_cnt++; - if (cell_clean_cnt==1000) { - clean_neighbours(); - cell_clean_cnt = 0; } - } - usleep(1000); + break; + default: + break; + } + cell_clean_cnt++; + if (cell_clean_cnt==1000) { + clean_neighbours(); + cell_clean_cnt = 0; } } @@ -318,95 +207,161 @@ void rrc::run_thread() { + + /******************************************************************************* * * * -* System Information Acquisition procedure +* NAS interface: PLMN search and RRC connection establishment * * * *******************************************************************************/ +uint16_t rrc::get_mcc() { + return serving_cell->get_mcc(); +} -// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message -uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf) { - return (period*10*(1+tti/(period*10))+(offset*10)+sf)%10240; // the 1 means next opportunity +uint16_t rrc::get_mnc() { + return serving_cell->get_mnc(); } -void rrc::run_si_acquisition_procedure() +/* NAS interface to search for available PLMNs. + * It goes through all known frequencies, synchronizes and receives SIB1 for each to extract PLMN. + * The function is blocking and waits until all frequencies have been + * searched and PLMNs are obtained. + * + * This function is thread-safe with connection_request() + */ +int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) { - uint32_t tti; - uint32_t si_win_start=0, si_win_len=0; - uint16_t period; - uint32_t x, sf, offset; - const int SIB1_SEARCH_TIMEOUT = 30; - - switch (si_acquire_state) { - case SI_ACQUIRE_SIB1: - // Instruct MAC to look for SIB1 - tti = mac->get_current_tti(); - si_win_start = sib_start_tti(tti, 2, 0, 5); - if (last_win_start == 0 || - (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000)) - { + // Mutex with connect + pthread_mutex_lock(&mutex); - last_win_start = si_win_start; - mac->bcch_start_rx(si_win_start, 1); - rrc_log->info("Instructed MAC to search for SIB1, win_start=%d, win_len=%d, interval=%d\n", - si_win_start, 1, srslte_tti_interval(last_win_start, tti)); - nof_sib1_trials++; - if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) { - if (state == RRC_STATE_CELL_SELECTING) { - select_next_cell_in_plmn(); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - } else if (state == RRC_STATE_PLMN_SELECTION) { - phy->cell_search_next(); + rrc_log->info("Starting PLMN search\n"); + uint32_t nof_plmns = 0; + phy_interface_rrc::cell_search_ret_t ret; + do { + ret = cell_search(); + if (ret == phy_interface_rrc::CELL_FOUND) { + if (serving_cell->has_sib1()) { + // Save PLMN and TAC to NAS + for (uint32_t i = 0; i < serving_cell->nof_plmns(); i++) { + if (nof_plmns < MAX_FOUND_PLMNS) { + found_plmns[nof_plmns].plmn_id = serving_cell->get_plmn(i); + found_plmns[nof_plmns].tac = serving_cell->get_tac(); + nof_plmns++; + } else { + rrc_log->error("No more space for plmns (%d)\n", nof_plmns); } - nof_sib1_trials = 0; } - } - break; - case SI_ACQUIRE_SIB2: - // Instruct MAC to look for next SIB - if(sysinfo_index < serving_cell->sib1ptr()->N_sched_info) { - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; - x = sysinfo_index*si_win_len; - sf = x%10; - offset = x/10; - - tti = mac->get_current_tti(); - period = liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[sysinfo_index].si_periodicity]; - si_win_start = sib_start_tti(tti, period, offset, sf); - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; - - if (last_win_start == 0 || - (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000)) - { - last_win_start = si_win_start; - - mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->info("Instructed MAC to search for system info=%d, win_start=%d, win_len=%d\n", - sysinfo_index, si_win_start, si_win_len); - } - } else { - // We've received all SIBs, move on to connection request - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTED; + rrc_log->error("SIB1 not acquired\n"); } - break; - default: - break; + } + } while (ret == phy_interface_rrc::CELL_NOT_FOUND || ret == phy_interface_rrc::CELL_FOUND); + + pthread_mutex_unlock(&mutex); + + if (ret == phy_interface_rrc::ERROR) { + return -1; + } else { + return nof_plmns; } } +/* This is the NAS interface. When NAS requests to select a PLMN we have to + * connect to either register or because there is pending higher layer traffic. + */ +void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { + plmn_is_selected = true; + selected_plmn_id = plmn_id; +} + +/* 5.3.3.2 Initiation of RRC Connection Establishment procedure + * + * Higher layers request establishment of RRC connection while UE is in RRC_IDLE + * + * This procedure selects a suitable cell for transmission of RRCConnectionRequest and configures + * it. Sends connectionRequest message and returns if message transmitted successfully. + * It does not wait until completition of Connection Establishment procedure + */ +bool rrc::connection_request() { + if (!plmn_is_selected) { + rrc_log->error("Trying to connect but PLMN not selected.\n"); + return false; + } + if (state != RRC_STATE_IDLE) { + rrc_log->warning("Requested RRC connection establishment while in state %s\n", rrc_state_text[state]); + return false; + } + bool ret = false; + 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"); + cell_selection(); + cnt++; + } + + // .. and SI acquisition + if (cnt<10) { + + // Set default configurations + set_phy_default(); + set_mac_default(); + + // CCCH configuration applied already at start + // timeAlignmentCommon applied in configure_serving_cell + + rrc_log->info("Configuring serving cell...\n"); + if (configure_serving_cell()) { + + mac_timers->timer_get(t300)->reset(); + mac_timers->timer_get(t300)->run(); + + rrc_log->info("Sending ConnectionRequest\n"); + send_con_request(); + ret = true; + } else { + rrc_log->error("Configuring serving cell\n"); + } + } else { + rrc_log->error("Could not find any suitable cell to connect\n"); + } + + pthread_mutex_unlock(&mutex); + return ret; +} + +/* Retrieves all required SIB or configures them if already retrieved before + */ +bool rrc::configure_serving_cell() { + + if (!phy->cell_is_camping()) { + rrc_log->error("Trying to configure Cell while not camping on it\n"); + return false; + } + for (uint32_t i = 0; i < NOF_REQUIRED_SIBS; i++) { + if (!serving_cell->has_sib(i)) { + if (!si_acquire(i)) { + 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()); + } + } + return true; +} @@ -417,262 +372,383 @@ void rrc::run_si_acquisition_procedure() * * * -* PLMN selection, cell selection/reselection and acquisition of SI procedures +* PHY interface: neighbour and serving cell measurements and out-of-sync/in-sync * * * *******************************************************************************/ -uint16_t rrc::get_mcc() { - return serving_cell->get_mcc(); -} +void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { -uint16_t rrc::get_mnc() { - return serving_cell->get_mnc(); -} + pthread_mutex_lock(&mutex); -void rrc::plmn_search() { - state = RRC_STATE_PLMN_START; -} + if (earfcn_i < 0 || pci_i < 0) { + earfcn_i = serving_cell->get_earfcn(); + pci_i = serving_cell->get_pci(); + } -/* This is the NAS interface. When NAS requests to select a PLMN we have to - * connect to either register or because there is pending higher layer traffic. - */ -void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request) { - connection_requested = connect_request; - plmn_select_rrc(plmn_id); -} + uint32_t earfcn = (uint32_t) earfcn_i; + uint32_t pci = (uint32_t) pci_i; -/* This is called by RRC only. In this case, we do not want to connect, just camp on the - * selected PLMN - */ -void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { - pthread_mutex_lock(&mutex); + // Measurements in RRC_CONNECTED go through measuremnt class to log reports etc. + if (state != RRC_STATE_IDLE) { + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + + // Measurements in RRC_IDLE update serving cell + } else { + + // 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); - // If already camping on the selected PLMN, select this cell - if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) { - if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) { - rrc_log->info("Already camping on selected PLMN\n"); + // Or update/add neighbour cell } else { - selected_plmn_id = plmn_id; - - if (serving_cell->plmn_equals(selected_plmn_id) && serving_cell->in_sync) { - rrc_log->info("PLMN Id=%s selected, Selecting serving cell earfcn=%d, pci=%d, status=%d\n", - plmn_id_to_string(plmn_id).c_str(), serving_cell->get_earfcn(), serving_cell->phy_cell.id, - phy->sync_status()); - if (!phy->sync_status()) { - phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); - } + 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 { - bool found = false; - for (uint32_t i=0;iplmn_equals(selected_plmn_id)) { - rrc_log->info("PLMN Id=%s selected, Selecting neighbour cell PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci()); - phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell); - found = true; - } - } - if (!found) { - rrc_log->warning("Could not find any cell for the selected PLMN. Searching another PLMN\n"); - plmn_search(); - pthread_mutex_unlock(&mutex); - return; - } + rrc_log->info("MEAS: Neighbour Cell in IDLE PCI=%d, RSRP=%.1f dBm not added. Worse than current neighbours\n", pci, rsrp); } } - - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; - } else { - rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]); } pthread_mutex_unlock(&mutex); } -void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) { - int cell_idx = find_neighbour_cell(earfcn, pci); - if (cell_idx >= 0) { - set_serving_cell(cell_idx); +// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1) +void rrc::out_of_sync() { + serving_cell->in_sync = false; + rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n", + rrc_state_text[state], n310_cnt, + mac_timers->timer_get(t311)->is_running()?"running":"stop", + mac_timers->timer_get(t310)->is_running()?"running":"stop"); + if (state == RRC_STATE_CONNECTED) { + if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { + n310_cnt++; + if (n310_cnt == N310) { + rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", + N310, mac_timers->timer_get(t310)->get_timeout()); + mac_timers->timer_get(t310)->reset(); + mac_timers->timer_get(t310)->run(); + n310_cnt = 0; + } + } } else { - rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", earfcn, pci); + 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"); + } } } -void rrc::set_serving_cell(uint32_t cell_idx) { - - if (cell_idx < neighbour_cells.size()) - { - // Remove future serving cell from neighbours to make space for current serving cell - cell_t *new_serving_cell = neighbour_cells[cell_idx]; - if (!new_serving_cell) { - rrc_log->error("Setting serving cell. Index %d is empty\n", cell_idx); - return; +// Recovery of physical layer problems (5.3.11.2) +void rrc::in_sync() { + serving_cell->in_sync = true; + if (mac_timers->timer_get(t310)->is_running()) { + n311_cnt++; + if (n311_cnt == N311) { + mac_timers->timer_get(t310)->stop(); + n311_cnt = 0; + rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); } - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end()); + } +} - // Move serving cell to neighbours list - if (serving_cell->is_valid()) { - // Make sure it does not exist already - int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->phy_cell.id); - if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { - printf("Error serving cell is already in the neighbour list. Removing it\n"); - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); + + + + + + + + + + + + + + + +/******************************************************************************* +* +* +* +* System Information Acquisition procedure +* +* +* +*******************************************************************************/ + + +// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message +uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf) { + return (period*10*(1+tti/(period*10))+(offset*10)+sf)%10240; // the 1 means next opportunity +} + +/* Implemnets the SI acquisition procedure + * Configures the MAC/PHY scheduling to retrieve SI messages. The function is blocking and will not + * return until SIB is correctly received or timeout + */ +bool rrc::si_acquire(uint32_t sib_index) +{ + uint32_t tti; + uint32_t si_win_start=0, si_win_len=0; + uint16_t period; + uint32_t x, sf, offset; + + uint32_t last_win_start = 0; + uint32_t timeout = 0; + + while(timeout < SIB_SEARCH_TIMEOUT_MS && !serving_cell->has_sib(sib_index)) { + + bool instruct_phy = false; + + if (sib_index == 0) { + + // Instruct MAC to look for SIB1 + tti = mac->get_current_tti(); + si_win_start = sib_start_tti(tti, 2, 0, 5); + if (last_win_start == 0 || + (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000)) { + + last_win_start = si_win_start; + si_win_len = 1; + instruct_phy = true; } - // If not in the list, add it to the list of neighbours (sorted inside the function) - if (!add_neighbour_cell(serving_cell)) { - rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + } else { + // Instruct MAC to look for SIB2..13 + if (serving_cell->has_sib1()) { + uint32_t sysinfo_index = sib_index-1; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = serving_cell->sib1ptr(); + if(sysinfo_index < sib1->N_sched_info) { + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; + x = sysinfo_index*si_win_len; + sf = x%10; + offset = x/10; + + tti = mac->get_current_tti(); + period = liblte_rrc_si_periodicity_num[sib1->sched_info[sysinfo_index].si_periodicity]; + si_win_start = sib_start_tti(tti, period, offset, sf); + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; + + if (last_win_start == 0 || + (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000)) + { + last_win_start = si_win_start; + instruct_phy = true; + } + } else { + rrc_log->warning("Trying to receive SIB%d but only %d available\n", sysinfo_index, sib1->N_sched_info); + return false; + } + } else { + rrc_log->error("Trying to receive SIB%d but SIB1 not received\n", sib_index+1); } } - // Set new serving cell - serving_cell = new_serving_cell; + // Instruct MAC to decode SIB + if (instruct_phy && !serving_cell->has_sib(sib_index)) { + mac->bcch_start_rx(si_win_start, si_win_len); + rrc_log->info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d\n", + sib_index+1, si_win_start, si_win_len); + } + usleep(1000); + timeout++; + } + return serving_cell->has_sib(sib_index); +} - rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n", - cell_idx, serving_cell->get_earfcn(), serving_cell->phy_cell.id, neighbour_cells.size()); - } else { - rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); + + + + + + + +/******************************************************************************* +* +* +* +* Cell selection, reselection and neighbour cell database management +* +* +* +*******************************************************************************/ + +/* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet + */ +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); + + switch(ret) { + case phy_interface_rrc::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); + break; + } + set_serving_cell(new_cell); + + rrc_log->info("Camping on cell...\n"); + if (phy->cell_select(&new_cell)) { + if (!serving_cell->has_sib1()) { + rrc_log->info("Camping OK. 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"); + } + } 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"); + break; + case phy_interface_rrc::ERROR: + rrc_log->error("In cell search. Finishing PLMN search\n"); + break; } + return ret; } -bool rrc::select_next_cell_in_plmn() { +/* Cell selection procedure 36.304 5.2.3 + * Select the best cell to camp on among the list of known cells + */ +bool rrc::cell_selection() +{ + int candidates = 0; // Neighbour cells are sorted in descending order of RSRP for (uint32_t i = 0; i < neighbour_cells.size(); i++) { if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ neighbour_cells[i]->in_sync) // matches S criteria { + candidates++; // If currently connected, verify cell selection criteria if (!serving_cell->in_sync || - (cell_selection_eval(neighbour_cells[i]->get_rsrp()) && - neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5)) + (cell_selection_criteria(neighbour_cells[i]->get_rsrp()) && + neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5)) { // Try to select Cell set_serving_cell(i); rrc_log->info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n", - i, serving_cell->phy_cell.id, serving_cell->get_earfcn()); + i, serving_cell->get_pci(), serving_cell->get_earfcn()); rrc_log->console("Selected cell PCI=%d, EARFCN=%d\n", - serving_cell->phy_cell.id, serving_cell->get_earfcn()); - phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; - return true; + serving_cell->get_pci(), serving_cell->get_earfcn()); + + if (phy->cell_select(&serving_cell->phy_cell)) { + if (configure_serving_cell()) { + rrc_log->info("Selected and configured cell successfully\n"); + return true; + } else { + rrc_log->error("While configuring serving cell\n"); + } + } else { + serving_cell->in_sync = false; + rrc_log->warning("Could not camp on selected cell\n"); + } } } } return false; } -void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { - - pthread_mutex_lock(&mutex); - - if (earfcn_i < 0 || pci_i < 0) { - earfcn_i = serving_cell->get_earfcn(); - pci_i = serving_cell->phy_cell.id; - } - - uint32_t earfcn = (uint32_t) earfcn_i; - uint32_t pci = (uint32_t) pci_i; - - // Measurements in RRC_CONNECTED go through measuremnt class to log reports etc. - if (state != RRC_STATE_IDLE) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); - - // Measurements in RRC_IDLE update serving cell and check for reselection +// Cell selection criteria Section 5.2.3.2 of 36.304 +bool rrc::cell_selection_criteria(float rsrp, float rsrq) +{ + if (get_srxlev(rsrp) > 0) { + return true; } else { + return false; + } +} - // Update serving cell - if (serving_cell->equals(earfcn, pci)) { - cell_reselection_eval(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); - } - } +float rrc::get_srxlev(float Qrxlevmeas) { + // TODO: Do max power limitation + float Pcompensation = 0; + return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; +} - // Evaluate if we need to select a new cell - select_next_cell_in_plmn(); - } - pthread_mutex_unlock(&mutex); +float rrc::get_squal(float Qqualmeas) { + return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); } -// PHY indicates that has gone through all known EARFCN -void rrc::earfcn_end() { - rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); +// Cell reselection in IDLE Section 5.2.4 of 36.304 +void rrc::cell_reselection(float rsrp, float rsrq) +{ + // Intra-frequency cell-reselection criteria - // If searching for PLMN, indicate NAS we scanned all frequencies - if (state == RRC_STATE_PLMN_SELECTION) { - nas->plmn_search_end(); + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -95.0) { + // UE may not perform intra-frequency measurements. + phy->meas_reset(); + // keep measuring serving cell + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); } else { - rrc_log->info("Restarting Cell search...\n"); - phy->cell_search_start(); + // UE must start intra-frequency measurements + phy->meas_start(phy->get_current_earfcn(), -1); } -} -/* PHY begins camping in a cell. RRC updates RSRP measurement, - * proceeds with PLMN selection/cell search if applicable and sets - * new cell as current serving cell */ -void rrc::cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { - - int cell_idx = -1; - bool found = true; - - pthread_mutex_lock(&mutex); + // TODO: Inter-frequency cell reselection +} - if (serving_cell->equals(earfcn, phy_cell.id)) { - serving_cell->set_rsrp(rsrp); +// Set new serving cell +void rrc::set_serving_cell(phy_interface_rrc::phy_cell_t phy_cell) { + int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); + if (cell_idx >= 0) { + set_serving_cell(cell_idx); } else { - // Check if cell is in our list of neighbour cells - cell_idx = find_neighbour_cell(earfcn, phy_cell.id); - if (cell_idx >= 0) { - set_serving_cell(cell_idx); - serving_cell->set_rsrp(rsrp); - } else { - found = false; - if (!add_neighbour_cell(earfcn, phy_cell, rsrp)) { - rrc_log->info( - "No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours)\n", - rsrp, - NOF_NEIGHBOUR_CELLS); - } else { - set_serving_cell(earfcn, phy_cell.id); - serving_cell->set_rsrp(rsrp); - } - } + rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); } +} - pthread_mutex_unlock(&mutex); +// Set new serving cell +void rrc::set_serving_cell(uint32_t cell_idx) { - if (state == RRC_STATE_PLMN_SELECTION && serving_cell->has_sib1()) { - bool ret = false; - for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) { - ret |= nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code); + if (cell_idx < neighbour_cells.size()) + { + // Remove future serving cell from neighbours to make space for current serving cell + cell_t *new_serving_cell = neighbour_cells[cell_idx]; + if (!new_serving_cell) { + rrc_log->error("Setting serving cell. Index %d is empty\n", cell_idx); + return; } - // If any of the PLMNs in this cell is selected, search next cell - if (!ret) { - phy->cell_search_next(); + neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end()); + + // Move serving cell to neighbours list + if (serving_cell->is_valid()) { + // Make sure it does not exist already + int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci()); + if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { + printf("Error serving cell is already in the neighbour list. Removing it\n"); + neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); + } + // If not in the list, add it to the list of neighbours (sorted inside the function) + if (!add_neighbour_cell(serving_cell)) { + rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + } } - } else if (state < RRC_STATE_CONNECTING) { - state = RRC_STATE_CELL_SELECTING; - } - rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", - found?"Updating":"Adding", - cell_idx>=0?"neighbour":"serving", earfcn, phy_cell.id, rsrp); + // Set new serving cell + serving_cell = new_serving_cell; - if (ho_syncing && phy_cell.id == ho_target_pci) { - ho_synced(ho_target_pci); - } + rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n", + cell_idx, serving_cell->get_earfcn(), serving_cell->get_pci(), neighbour_cells.size()); + } else { + rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); + } } bool sort_rsrp(cell_t *u1, cell_t *u2) { @@ -691,6 +767,8 @@ std::vector::iterator rrc::delete_neighbour(std::vector::itera return neighbour_cells.erase(it); } +/* Called by main RRC thread to remove neighbours from which measurements have not been received in a while + */ void rrc::clean_neighbours() { struct timeval now; @@ -729,7 +807,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.id, neighbour_cells[0]->get_rsrp()); + n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.cell.id, neighbour_cells[0]->get_rsrp()); for (uint32_t i=1;iget_pci(), neighbour_cells[i]->get_rsrp()); } @@ -759,21 +837,22 @@ bool rrc::add_neighbour_cell(cell_t *new_cell) { // If only neighbour PCI is provided, copy full cell from serving cell bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { - srslte_cell_t serving_phy; - serving_phy = serving_cell->phy_cell; - serving_phy.id = pci; - return add_neighbour_cell(earfcn, serving_phy, rsrp); + phy_interface_rrc::phy_cell_t phy_cell; + phy_cell = serving_cell->phy_cell; + phy_cell.earfcn = earfcn; + phy_cell.cell.id = pci; + return add_neighbour_cell(phy_cell, rsrp); } -bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { - if (earfcn == 0) { - earfcn = serving_cell->get_earfcn(); +bool rrc::add_neighbour_cell(phy_interface_rrc::phy_cell_t phy_cell, float rsrp) { + if (phy_cell.earfcn == 0) { + phy_cell.earfcn = serving_cell->get_earfcn(); } // First check if already exists - int cell_idx = find_neighbour_cell(earfcn, phy_cell.id); + int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.id, earfcn, cell_idx); + 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) { @@ -783,7 +862,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp } // If not, create a new one - cell_t *new_cell = new cell_t(phy_cell, earfcn, rsrp); + cell_t *new_cell = new cell_t(phy_cell, rsrp); return add_neighbour_cell(new_cell); } @@ -797,105 +876,17 @@ int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) { return -1; } -// Cell reselection in IDLE Section 5.2.4 of 36.304 -void rrc::cell_reselection_eval(float rsrp, float rsrq) -{ - // Intra-frequency cell-reselection criteria - - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -95.0) { - // UE may not perform intra-frequency measurements. - phy->meas_reset(); - // keep measuring serving cell - phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); - } else { - // UE must start intra-frequency measurements - phy->meas_start(phy->get_current_earfcn(), -1); - } - - // TODO: Inter-frequency cell reselection -} - -// Cell selection in IDLE Section 5.2.3.2 of 36.304 -bool rrc::cell_selection_eval(float rsrp, float rsrq) -{ - if (get_srxlev(rsrp) > 0) { - return true; - } else { - return false; - } -} - -float rrc::get_srxlev(float Qrxlevmeas) { - // TODO: Do max power limitation - float Pcompensation = 0; - return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; -} - -float rrc::get_squal(float Qqualmeas) { - return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); -} - - /******************************************************************************* * * * -* Detection of Radio-Link Failures +* Other functions * * * *******************************************************************************/ -// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1) -void rrc::out_of_sync() { - rrc_log->info("Received out-of-sync state %s. n310=%d, t311=%s, t310=%s\n", - rrc_state_text[state], n310_cnt, - mac_timers->timer_get(t311)->is_running()?"running":"stop", - mac_timers->timer_get(t310)->is_running()?"running":"stop"); - if (state == RRC_STATE_CONNECTED) { - if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { - n310_cnt++; - if (n310_cnt == N310) { - rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", - N310, mac_timers->timer_get(t310)->get_timeout()); - mac_timers->timer_get(t310)->reset(); - mac_timers->timer_get(t310)->run(); - n310_cnt = 0; - } - } - } else if (state != RRC_STATE_LEAVE_CONNECTED) { - if (!mac_timers->timer_get(t311)->is_running()) { - if (serving_cell->in_sync) { - rrc_log->info("Detected out-of-sync while in IDLE. Resetting sync\n"); - phy->sync_reset(); - } else { - rrc_log->info("Detected out-of-sync while in IDLE. Selecting another cell in the PLMN\n"); - if (!select_next_cell_in_plmn()) { - rrc_log->info("Could not find any available cell in this PLMN. Searching PLMN again.\n"); - plmn_search(); - } - } - } else { - rrc_log->info("Detected out-of-sync while T311 is running\n"); - } - } - serving_cell->in_sync = false; -} - -// Recovery of physical layer problems (5.3.11.2) -void rrc::in_sync() { - serving_cell->in_sync = true; - if (mac_timers->timer_get(t310)->is_running()) { - n311_cnt++; - if (n311_cnt == N311) { - mac_timers->timer_get(t310)->stop(); - n311_cnt = 0; - rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); - } - } -} - /* Detection of radio link failure (5.3.11.3) * Upon T310 expiry, RA problem or RLC max retx */ @@ -904,12 +895,9 @@ void rrc::radio_link_failure() { rrc_log->warning("Detected Radio-Link Failure\n"); rrc_log->console("Warning: Detected Radio-Link Failure\n"); - if (state != RRC_STATE_CONNECTED) { - state = RRC_STATE_LEAVE_CONNECTED; - } else { - mac_interface_rrc::ue_rnti_t uernti; - mac->get_rntis(&uernti); - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, uernti.crnti); + if (state == RRC_STATE_CONNECTED) { + // Initiate connection re-establishment procedure + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE); } } @@ -938,21 +926,21 @@ void rrc::timer_expired(uint32_t timeout_id) { radio_link_failure(); } else if (timeout_id == t311) { rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); - state = RRC_STATE_LEAVE_CONNECTED; - } else if (timeout_id == t300) { - rrc_log->info("Timer T300 expired: ConnectionRequest failed. Reset MAC and restablished RLC.\n"); - rlc->reestablish(); - mac->reset(); - set_mac_default(); - state = RRC_STATE_IDLE; - nas->plmn_search_end(); + go_idle = true; } else if (timeout_id == t301) { if (state == RRC_STATE_IDLE) { rrc_log->info("Timer T301 expired: Already in IDLE.\n"); } else { rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); - state = RRC_STATE_LEAVE_CONNECTED; + go_idle = true; } + } 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(); } else if (timeout_id == t304) { rrc_log->console("Timer T304 expired: Handover failed\n"); ho_failed(); @@ -1001,15 +989,23 @@ void rrc::send_con_request() { ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; - mac_timers->timer_get(t300)->reset(); - mac_timers->timer_get(t300)->run(); send_ul_ccch_msg(); } /* RRC connection re-establishment procedure (5.3.7) */ -void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti) +void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause) { + + uint16_t crnti; + if (cause == LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE) { + crnti = ho_src_rnti; + } else { + mac_interface_rrc::ue_rnti_t uernti; + mac->get_rntis(&uernti); + crnti = uernti.crnti; + } + // Compute shortMAC-I uint8_t varShortMAC[128], varShortMAC_packed[16]; bzero(varShortMAC, 128); @@ -1069,31 +1065,32 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, set_phy_default(); mac->reset(); set_mac_default(); - phy->sync_reset(); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; -} - -// Actions following cell reselection 5.3.7.3 -void rrc::con_restablish_cell_reselected() -{ - liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); - mac_timers->timer_get(t301)->reset(); - mac_timers->timer_get(t301)->run(); - mac_timers->timer_get(t311)->stop(); + // Perform cell selection in accordance to 36.304 + if (cell_selection()) { - send_ul_ccch_msg(); + if (mac_timers->timer_get(t311)->is_running()) { + // Actions following cell reselection while T311 is running 5.3.7.3 + rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + mac_timers->timer_get(t301)->reset(); + mac_timers->timer_get(t301)->run(); + mac_timers->timer_get(t311)->stop(); + send_ul_ccch_msg(); + } else { + go_idle = true; + } + } else { + rrc_log->warning("Could not re-synchronize with cell.\n"); + } + } void rrc::send_con_restablish_complete() { rrc_log->debug("Preparing RRC Connection Reestablishment Complete\n"); rrc_log->console("RRC Connected\n"); - state = RRC_STATE_CONNECTED; // Prepare ConnectionSetupComplete packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE; @@ -1171,13 +1168,12 @@ bool rrc::ho_prepare() { mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present && mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->get_earfcn()) { - rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); + rrc_log->error("Received mobilityControlInfo for inter-frequency handover\n"); + return false; } // Save serving cell and current configuration ho_src_cell = *serving_cell; - phy->get_config(&ho_src_phy_cfg); - mac->get_config(&ho_src_mac_cfg); mac_interface_rrc::ue_rnti_t uernti; mac->get_rntis(&uernti); ho_src_rnti = uernti.crnti; @@ -1194,23 +1190,11 @@ bool rrc::ho_prepare() { mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci()); - if (!phy->cell_handover(neighbour_cells[target_cell_idx]->phy_cell)) { + if (!phy->cell_select(&neighbour_cells[target_cell_idx]->phy_cell)) { rrc_log->error("Could not synchronize with target cell pci=%d. Trying to return to source PCI\n", neighbour_cells[target_cell_idx]->get_pci()); - ho_failed(); return false; } - ho_target_pci = neighbour_cells[target_cell_idx]->phy_cell.id; - ho_syncing = true; - } - return true; -} - -void rrc::ho_synced(uint32_t current_pci) -{ - ho_syncing = false; - if (current_pci == ho_target_pci) { if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, @@ -1227,14 +1211,14 @@ void rrc::ho_synced(uint32_t current_pci) ncc = mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count; if (mob_reconf.sec_cnfg_ho.intra_lte.key_change_ind) { rrc_log->console("keyChangeIndicator in securityConfigHO not supported\n"); - return; + return false; } if (mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) { cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.cipher_alg; integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.int_alg; rrc_log->info("Changed Ciphering to %s and Integrity to %s\n", - ciphering_algorithm_id_text[cipher_algo], - integrity_algorithm_id_text[integ_algo]); + ciphering_algorithm_id_text[cipher_algo], + integrity_algorithm_id_text[integ_algo]); } } @@ -1244,23 +1228,20 @@ void rrc::ho_synced(uint32_t current_pci) pdcp->config_security_all(k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(); - } else { - rrc_log->error("HO: Synchronized with incorrect cell. Target PCI=%d, current PCI=%d\n", ho_target_pci, current_pci); - ho_failed(); } - return; + return true; } void rrc::ho_ra_completed(bool ra_successful) { if (pending_mob_reconf) { - measurements.ho_finish(); + if (ra_successful) { + measurements.ho_finish(); - if (mob_reconf.meas_cnfg_present) { - measurements.parse_meas_config(&mob_reconf.meas_cnfg); - } + if (mob_reconf.meas_cnfg_present) { + measurements.parse_meas_config(&mob_reconf.meas_cnfg); + } - if (ra_successful) { mac_timers->timer_get(t304)->stop(); apply_rr_config_common_ul(&mob_reconf.mob_ctrl_info.rr_cnfg_common); @@ -1268,79 +1249,100 @@ void rrc::ho_ra_completed(bool ra_successful) { apply_rr_config_dedicated(&mob_reconf.rr_cnfg_ded); } } + // T304 will expiry and send ho_failure rrc_log->info("HO %ssuccessful\n", ra_successful?"":"un"); rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un"); pending_mob_reconf = false; - if (ra_successful) { - state = RRC_STATE_CONNECTED; - } } else { rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n"); } } -// This is T304 expiry 5.3.5.6 -void rrc::ho_failed() { - - // Instruct PHY to resync with source PCI - if (!phy->cell_handover(ho_src_cell.phy_cell)) { - rrc_log->error("Could not synchronize with target cell pci=%d. Going to PLMN Search\n", ho_src_cell.get_pci()); - plmn_search(); - return; +bool rrc::con_reconfig_ho(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) +{ + if (reconfig->mob_ctrl_info.target_pci == phy->get_current_pci()) { + rrc_log->warning("Received HO command to own cell\n"); + return false; } - // Set previous PHY/MAC configuration - phy->set_config(&ho_src_phy_cfg); - mac->set_config(&ho_src_mac_cfg); + rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", + reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); + + // store mobilityControlInfo + memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); + pending_mob_reconf = true; - // Start the Reestablishment Procedure - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE, ho_src_rnti); + ho_start = true; + + return true; } -void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { - uint32_t i; +// Handle RRC Reconfiguration without MobilityInformation Section 5.3.5.3 +bool rrc::con_reconfig(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { + if (reconfig->rr_cnfg_ded_present) { + if (!apply_rr_config_dedicated(&reconfig->rr_cnfg_ded)) { + return false; + } + } + if (reconfig->meas_cnfg_present) { + if (!measurements.parse_meas_config(&reconfig->meas_cnfg)) { + return false; + } + } - if (reconfig->mob_ctrl_info_present) { + send_rrc_con_reconfig_complete(); - if (reconfig->mob_ctrl_info.target_pci == phy->get_current_pci()) { - rrc_log->warning("Received HO command to own cell\n"); - send_rrc_con_reconfig_complete(); + byte_buffer_t *nas_sdu; + for (uint32_t i = 0; i < reconfig->N_ded_info_nas; i++) { + nas_sdu = pool_allocate; + if (nas_sdu) { + memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); + nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; + nas->write_pdu(RB_ID_SRB1, nas_sdu); } else { - rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); - rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", - reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); + rrc_log->error("Fatal Error: Couldn't allocate PDU in handle_rrc_con_reconfig().\n"); + return false; + } + } + return true; +} - // store mobilityControlInfo - memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); - pending_mob_reconf = true; +// HO failure from T304 expiry 5.3.5.6 +void rrc::ho_failed() { + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE); +} - state = RRC_STATE_HO_PREPARE; - } +// Reconfiguration failure or Section 5.3.5.5 +void rrc::con_reconfig_failed() +{ + // Set previous PHY/MAC configuration + phy->set_config(&previous_phy_cfg); + mac->set_config(&previous_mac_cfg); + if (security_is_activated) { + // Start the Reestablishment Procedure + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE); } else { - // Section 5.3.5.3 - if (reconfig->rr_cnfg_ded_present) { - apply_rr_config_dedicated(&reconfig->rr_cnfg_ded); - } - if (reconfig->meas_cnfg_present) { - measurements.parse_meas_config(&reconfig->meas_cnfg); - } + go_idle = true; + } +} - send_rrc_con_reconfig_complete(); +void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { + uint32_t i; - byte_buffer_t *nas_sdu; - for (i = 0; i < reconfig->N_ded_info_nas; i++) { - nas_sdu = pool_allocate; - if (nas_sdu) { - memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); - nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; - nas->write_pdu(lcid, nas_sdu); - } else { - rrc_log->error("Fatal Error: Couldn't allocate PDU in handle_rrc_con_reconfig().\n"); - return; - } + phy->get_config(&previous_phy_cfg); + mac->get_config(&previous_mac_cfg); + + if (reconfig->mob_ctrl_info_present) { + if (!con_reconfig_ho(reconfig)) { + con_reconfig_failed(); + } + } else { + if (!con_reconfig(reconfig)) { + con_reconfig_failed(); } } } @@ -1348,8 +1350,8 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ void rrc::rrc_connection_release() { // Save idleModeMobilityControlInfo, etc. - state = RRC_STATE_LEAVE_CONNECTED; rrc_log->console("Received RRC Connection Release\n"); + go_idle = true; } /* Actions upon leaving RRC_CONNECTED 5.3.12 */ @@ -1357,9 +1359,8 @@ void rrc::leave_connected() { rrc_log->console("RRC IDLE\n"); rrc_log->info("Leaving RRC_CONNECTED state\n"); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; drb_up = false; + security_is_activated = false; measurements.reset(); pdcp->reset(); rlc->reset(); @@ -1371,7 +1372,7 @@ void rrc::leave_connected() mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); mac_timers->timer_get(t304)->stop(); - if (phy->sync_status()) { + if (phy->cell_is_camping()) { // Instruct MAC to look for P-RNTI mac->pcch_start_rx(); // Instruct PHY to measure serving cell for cell reselection @@ -1394,13 +1395,9 @@ void rrc::leave_connected() * *******************************************************************************/ void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu) { - if (state == RRC_STATE_PLMN_SELECTION) { - // Do we need to do something with BCH? - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received."); - pool->deallocate(pdu); - } else { - rrc_log->warning("Received BCCH BCH in incorrect state\n"); - } + // Do we need to do something with BCH? + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received."); + pool->deallocate(pdu); } void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { @@ -1417,7 +1414,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { for(uint32_t i=0; iinfo("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); - if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { + if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type) { serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1); handle_sib1(); } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) { @@ -1431,28 +1428,22 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { handle_sib13(); } } - - last_win_start = 0; - - if(serving_cell->has_sib2()) { - sysinfo_index++; - rrc_log->info("Increasing sysinfo_index=%d\n", sysinfo_index); - } } void rrc::handle_sib1() { + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = serving_cell->sib1ptr(); rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", serving_cell->get_cell_id()&0xfff, - liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length], - liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[0].si_periodicity]); + liblte_rrc_si_window_length_num[sib1->si_window_length], + liblte_rrc_si_periodicity_num[sib1->sched_info[0].si_periodicity]); // Print SIB scheduling info uint32_t i,j; - for(i=0;isib1ptr()->N_sched_info;i++){ - for(j=0;jsib1ptr()->sched_info[i].N_sib_mapping_info;j++){ - LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1ptr()->sched_info[i].sib_mapping_info[j].sib_type; - LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1ptr()->sched_info[i].si_periodicity; + for(i=0;iN_sched_info;i++){ + for(j=0;jsched_info[i].N_sib_mapping_info;j++){ + LIBLTE_RRC_SIB_TYPE_ENUM t = sib1->sched_info[i].sib_mapping_info[j].sib_type; + LIBLTE_RRC_SI_PERIODICITY_ENUM p = sib1->sched_info[i].si_periodicity; rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n", liblte_rrc_sib_type_num[t], liblte_rrc_si_periodicity_num[p]); @@ -1460,29 +1451,8 @@ void rrc::handle_sib1() } // Set TDD Config - if(serving_cell->sib1ptr()->tdd) { - phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg); - } - - // Send PLMN and TAC to NAS - std::stringstream ss; - for (uint32_t i = 0; i < serving_cell->sib1ptr()->N_plmn_ids; i++) { - nas->plmn_found(serving_cell->sib1ptr()->plmn_id[i].id, serving_cell->sib1ptr()->tracking_area_code); - } - - // Jump to next state - switch(state) { - case RRC_STATE_CELL_SELECTING: - si_acquire_state = SI_ACQUIRE_SIB2; - break; - case RRC_STATE_PLMN_SELECTION: - si_acquire_state = SI_ACQUIRE_IDLE; - rrc_log->info("SI Acquisition done. Searching next cell...\n"); - usleep(5000); - phy->cell_search_next(); - break; - default: - si_acquire_state = SI_ACQUIRE_IDLE; + if(sib1->tdd) { + phy->set_config_tdd(&sib1->tdd_cnfg); } } @@ -1569,13 +1539,10 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec, pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi); if (s_tmsi.mmec == s_tmsi_paged->mmec && s_tmsi.m_tmsi == s_tmsi_paged->m_tmsi) { - rrc_log->info("S-TMSI match in paging message\n"); - rrc_log->console("S-TMSI match in paging message\n"); - mac->pcch_stop_rx(); if (RRC_STATE_IDLE == state) { - rrc_log->info("RRC in IDLE state - sending connection request.\n"); - connection_requested = true; - state = RRC_STATE_CELL_SELECTED; + 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); } } } @@ -1656,7 +1623,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); switch (state) { - case RRC_STATE_CONNECTING: + case RRC_STATE_IDLE: send_con_setup_complete(sdu); break; case RRC_STATE_CONNECTED: @@ -1697,18 +1664,19 @@ 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", dl_ccch_msg.msg.rrc_con_rej.wait_time); - // Stop T300 timer mac_timers->timer_get(t300)->stop(); - state = RRC_STATE_LEAVE_CONNECTED; + mac->reset(); + set_mac_default(); + nas->rrc_connection_failure(); break; case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP: rrc_log->info("Connection Setup 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"); - nas->notify_connection_setup(); break; case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST: rrc_log->info("Connection Reestablishment received\n"); @@ -1720,7 +1688,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) { case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ: rrc_log->info("Connection Reestablishment Reject received\n"); rrc_log->console("Reestablishment Reject\n"); - state = RRC_STATE_LEAVE_CONNECTED; + go_idle = true; break; default: break; @@ -1768,6 +1736,8 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); + security_is_activated = true; + // Configure PDCP for security pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); pdcp->enable_integrity(lcid); @@ -2215,7 +2185,7 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg } } -void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) { +bool rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) { if (cnfg->phy_cnfg_ded_present) { apply_phy_config_dedicated(&cnfg->phy_cnfg_ded, false); // Apply SR configuration to MAC @@ -2232,7 +2202,15 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) //TODO } if (cnfg->rlf_timers_and_constants_present) { - //TODO + mac_timers->timer_get(t301)->set(this, liblte_rrc_t301_num[cnfg->rlf_timers_and_constants.t301]); + mac_timers->timer_get(t310)->set(this, liblte_rrc_t310_num[cnfg->rlf_timers_and_constants.t310]); + mac_timers->timer_get(t311)->set(this, liblte_rrc_t311_num[cnfg->rlf_timers_and_constants.t311]); + N310 = liblte_rrc_n310_num[cnfg->rlf_timers_and_constants.n310]; + N311 = liblte_rrc_n311_num[cnfg->rlf_timers_and_constants.n311]; + + rrc_log->info("Updated Constants and Timers: N310=%d, N311=%d, t300=%d, t301=%d, t310=%d, t311=%d\n", + N310, N311, mac_timers->timer_get(t301)->get_timeout(), + mac_timers->timer_get(t310)->get_timeout(), mac_timers->timer_get(t311)->get_timeout()); } for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list_size; i++) { // TODO: handle SRB modification @@ -2245,28 +2223,29 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) // TODO: handle DRB modification add_drb(&cnfg->drb_to_add_mod_list[i]); } + return true; } void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) { - - // Stop T300 timer - mac_timers->timer_get(t300)->stop(); - // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->rr_cnfg); } /* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */ void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) { - mac_timers->timer_get(t301)->stop(); // TODO: Reestablish DRB1. Not done because never was suspended // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->rr_cnfg); - // TODO: Some security stuff here... is it necessary? + mac_timers->timer_get(t300)->stop(); + + // Enter RRC_CONNECTED + state = RRC_STATE_CONNECTED; + + // Send ConnectionSetupComplete message send_con_restablish_complete(); } @@ -2462,10 +2441,7 @@ void rrc::rrc_meas::reset() filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; objects.clear(); - std::map::iterator iter = active.begin(); - while (iter != active.end()) { - remove_meas_id(iter++); - } + active.clear(); reports_cfg.clear(); phy->meas_reset(); bzero(&pcell_measurement, sizeof(meas_value_t)); @@ -2836,7 +2812,7 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) { if (active.count(measId)) { mac_timers->timer_get(active[measId].periodic_timer)->stop(); mac_timers->timer_release_id(active[measId].periodic_timer); - log_h->info("MEAS: Removed measId=%d, timer_id=%d\n", measId, active[measId].periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", measId); active.erase(measId); } else { log_h->warning("MEAS: Removing unexistent measId=%d\n", measId); @@ -2846,14 +2822,14 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) { void rrc::rrc_meas::remove_meas_id(std::map::iterator it) { mac_timers->timer_get(it->second.periodic_timer)->stop(); mac_timers->timer_release_id(it->second.periodic_timer); - log_h->info("MEAS: Removed measId=%d, timer_id=%d\n", it->first, it->second.periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", it->first); active.erase(it); } /* Parses MeasConfig object from RRCConnectionReconfiguration message and applies configuration * as per section 5.5.2 */ -void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) +bool rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) { // Measurement object removal 5.5.2.4 @@ -2986,15 +2962,12 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) } else { is_new = true; active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); - if (!active[measId->meas_id].periodic_timer) { - log_h->error("Could not get unique timer id\n"); - } } active[measId->meas_id].object_id = measId->meas_obj_id; active[measId->meas_id].report_id = measId->rep_cnfg_id; - log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%d, nof_values=%d\n", + log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, nof_values=%d\n", is_new?"Added":"Updated", measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id, - active[measId->meas_id].periodic_timer, active[measId->meas_id].cell_values.size()); + active[measId->meas_id].cell_values.size()); } } @@ -3009,6 +2982,8 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) } update_phy(); + + return true; } /* Instruct PHY to start measurement */ diff --git a/srsue/test/phy/ue_itf_test_prach.cc b/srsue/test/phy/ue_itf_test_prach.cc index 810278c7c..9b8cd54c3 100644 --- a/srsue/test/phy/ue_itf_test_prach.cc +++ b/srsue/test/phy/ue_itf_test_prach.cc @@ -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); } diff --git a/srsue/test/phy/ue_itf_test_sib1.cc b/srsue/test/phy/ue_itf_test_sib1.cc index 23f8566be..c73758cc6 100644 --- a/srsue/test/phy/ue_itf_test_sib1.cc +++ b/srsue/test/phy/ue_itf_test_sib1.cc @@ -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) { diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 2fb3efe95..1c6f5f0e3 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -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) { From c574b8d8a427382dae22df0e18a54d12a4f96529 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 19 Mar 2018 14:21:17 +0100 Subject: [PATCH 02/52] Missed change during merge --- lib/examples/pdsch_ue.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 084dc682b..fc99fdc9a 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -450,12 +450,7 @@ 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) { From 2c3386a4863182fda2f72dc0b501236ae9529348 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 20 Mar 2018 15:09:32 +0100 Subject: [PATCH 03/52] Updated missing changes --- srsue/hdr/phy/phch_recv.h | 5 ++--- srsue/src/phy/phch_recv.cc | 39 ++++++++++++++++++++++++------------ srsue/src/phy/phch_worker.cc | 6 ++++-- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index cf4a8f860..edfe7da2a 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -181,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; @@ -202,6 +202,7 @@ 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); @@ -212,8 +213,6 @@ 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; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index b13356fdf..428003d84 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -1247,7 +1247,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) return ERROR; } - float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); + float rsrp = srslte_chest_dl_get_rsrp_neighbour(&ue_dl.chest); float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); float snr = srslte_chest_dl_get_snr(&ue_dl.chest); float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb)); @@ -1294,9 +1294,11 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 uint32_t max_fft_sz = srslte_symbol_sz(100); uint32_t max_sf_size = SRSLTE_SF_LEN(max_fft_sz); - sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size); - input_cfo_corrected = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*15*max_sf_size); - + 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); + return; + } measure_p.init(sf_buffer, log_h, 1, max_sf_window); //do this different we don't need all this search window. @@ -1304,6 +1306,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 fprintf(stderr, "Error initiating sync_find\n"); return; } + srslte_sync_set_sss_algorithm(&sync_find, SSS_FULL); srslte_sync_cp_en(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_threshold(&sync_find, 1.7); @@ -1317,12 +1320,16 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 srslte_sync_set_sss_eq_enable(&sync_find, true); sync_find.pss.chest_on_filter = true; - - sync_find.sss_channel_equalize = true; + sync_find.sss_channel_equalize = false; reset(); } +void phch_recv::scell_recv::deinit() { + srslte_sync_free(&sync_find); + free(sf_buffer[0]); +} + void phch_recv::scell_recv::reset() { current_fft_sz = 0; @@ -1498,6 +1505,12 @@ int phch_recv::meas_stop(uint32_t earfcn, int pci) { return -1; } +phch_recv::intra_measure::~intra_measure() { + srslte_ringbuffer_free(&ring_buffer); + scell.deinit(); + free(search_buffer); +} + void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, srslte::log *log_h) { this->rrc = rrc; this->log_h = log_h; @@ -1505,11 +1518,11 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, receive_enabled = false; // Start scell - scell.init(log_h, common->args->sic_pss_enabled, INTRA_FREQ_MEAS_LEN_MS); + scell.init(log_h, common->args->sic_pss_enabled, common->args->intra_freq_meas_len_ms); - search_buffer = (cf_t*) srslte_vec_malloc(INTRA_FREQ_MEAS_LEN_MS*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); + search_buffer = (cf_t*) srslte_vec_malloc(common->args->intra_freq_meas_len_ms*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); - if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*INTRA_FREQ_MEAS_LEN_MS*2*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { + if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*common->args->intra_freq_meas_len_ms*2*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { return; } @@ -1573,7 +1586,7 @@ void phch_recv::intra_measure::rem_cell(int pci) { void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples) { if (receive_enabled) { - if ((tti%INTRA_FREQ_MEAS_PERIOD_MS) == 0) { + if ((tti%common->args->intra_freq_meas_period_ms) == 0) { receiving = true; receive_cnt = 0; measure_tti = tti; @@ -1585,7 +1598,7 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples receiving = false; } else { receive_cnt++; - if (receive_cnt == INTRA_FREQ_MEAS_LEN_MS) { + if (receive_cnt == common->args->intra_freq_meas_len_ms) { tti_sync.increase(); receiving = false; } @@ -1604,8 +1617,8 @@ void phch_recv::intra_measure::run_thread() if (running) { // Read data from buffer and find cells in it - srslte_ringbuffer_read(&ring_buffer, search_buffer, INTRA_FREQ_MEAS_LEN_MS*current_sflen*sizeof(cf_t)); - int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, INTRA_FREQ_MEAS_LEN_MS, info); + srslte_ringbuffer_read(&ring_buffer, search_buffer, common->args->intra_freq_meas_len_ms*current_sflen*sizeof(cf_t)); + int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, common->args->intra_freq_meas_len_ms, info); receiving = false; for (int i=0;iconfig->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr); - Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + if (sinr) { + srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr); + Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + } } } From b3be54b274e2c437177de78c24eac0dad7427ece Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 21 Mar 2018 10:46:24 +0100 Subject: [PATCH 04/52] Attach and paging ok. Reselection on IDLE not working --- lib/include/srslte/common/timers.h | 2 +- lib/include/srslte/interfaces/ue_interfaces.h | 32 +- lib/src/phy/rf/rf_uhd_imp.c | 1 + srsue/hdr/mac/mac.h | 3 +- srsue/hdr/phy/phch_common.h | 2 +- srsue/hdr/phy/phch_recv.h | 56 ++- srsue/hdr/phy/phy.h | 2 +- srsue/hdr/upper/nas.h | 19 +- srsue/hdr/upper/rrc.h | 30 +- srsue/src/mac/mac.cc | 7 +- srsue/src/main.cc | 4 - srsue/src/phy/phch_common.cc | 1 - srsue/src/phy/phch_recv.cc | 212 ++++----- srsue/src/phy/phch_worker.cc | 53 +-- srsue/src/phy/phy.cc | 5 +- srsue/src/upper/gw.cc | 17 +- srsue/src/upper/nas.cc | 213 ++++----- srsue/src/upper/rrc.cc | 441 +++++++++++------- srsue/test/mac/mac_test.cc | 4 +- srsue/test/upper/nas_test.cc | 4 +- 20 files changed, 590 insertions(+), 518 deletions(-) diff --git a/lib/include/srslte/common/timers.h b/lib/include/srslte/common/timers.h index 5e8b1cfd5..9809cc260 100644 --- a/lib/include/srslte/common/timers.h +++ b/lib/include/srslte/common/timers.h @@ -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; diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index c05ab4231..0ddebee47 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -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,15 +428,14 @@ 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; diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index b4b0cfcd6..1331495e9 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -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); diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index 1f41c5bc0..4bf888e49 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -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(); diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index f21738b6b..698b3de94 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -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 diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index edfe7da2a..19b8ad17d 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -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); - next_state = IDLE; + 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; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index a00cfd5a5..e05fbfd4c 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -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(); diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index afa9b3343..463040fa1 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -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); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index f91d35354..bc27aa324 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -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_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); diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 4f49d6d01..4372085d7 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -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(); } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 2912f7cd1..63d0e12ab 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -261,10 +261,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&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(&args->expert.phy.time_correct_period)->default_value(5), - "Period for sampling time offset correction.") - ("expert.sss_algorithm", bpo::value(&args->expert.phy.sss_algorithm)->default_value("full"), "Selects the SSS estimation algorithm.") diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 3c3cf1641..29e1e3541 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -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); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 428003d84..58883aefe 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -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 (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: - log_h->info("Cell Search: Could not synchronize with cell\n"); - ret = phy_interface_rrc::CELL_NOT_FOUND; - break; + 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; + } + ret.found = phy_interface_rrc::cell_search_ret_t::CELL_FOUND; + } else { + log_h->info("Cell Search: Could not synchronize with cell\n"); + 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(); - ret = true; - break; - case sfn_sync::ERROR: - Error("Cell Select: Error receiving samples when synchronizing SFN\n"); - radio_error(); - break; - default: - Info("Cell Select: Could not synchronize SFN\n"); - break; + phy_state.run_sfn_sync(); + if (phy_state.is_camping()) { + Info("Cell Select: SFN synchronized. CAMPING...\n"); + ret = true; + } else { + Info("Cell Select: Could not synchronize SFN\n"); } 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) { - 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(); + switch(sfn_p.run_subframe(&cell, &tti)) { + case sfn_sync::SFN_FOUND: + phy_state.state_exit(); + break; + 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,37 +503,29 @@ void phch_recv::run_thread() * SFN is found again go back to camping */ if (radio_is_overflow) { - // Overflow has occurred now while camping - 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"); - rrc->out_of_sync(); - phy_state.force_sfn_sync(); - break; - default: - break; + // If we are coming back from an overflow + if (radio_overflow_return) { + if (phy_state.is_camping()) { + log_h->info("Successfully resynchronized after overflow. Returning to CAMPING\n"); + radio_overflow_return = false; + radio_is_overflow = false; + } 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(); } + } 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 } - // If overflow occurs in any other state, it does not harm } // Increase TTI counter @@ -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 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); } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index f10bc2b67..911429690 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -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,33 +441,31 @@ 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) { - - // Setup estimator filter - float w_coeff = phy->args->estimator_fil_w; - if (w_coeff > 0.0) { - srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); - } else if (w_coeff == 0.0) { - srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0); - } - - if (!phy->args->snr_estim_alg.compare("refs")) { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); - } else if (!phy->args->snr_estim_alg.compare("empty")) { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_EMPTY); - } else { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); - } - - if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { - Error("Getting PDCCH FFT estimate\n"); - return false; - } - chest_done = true; + // 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; + if (w_coeff > 0.0) { + srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); + } else if (w_coeff == 0.0) { + srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0); + } + + if (!phy->args->snr_estim_alg.compare("refs")) { + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); + } else if (!phy->args->snr_estim_alg.compare("empty")) { + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_EMPTY); } else { - chest_done = false; + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); + } + + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { + Error("Getting PDCCH FFT estimate\n"); + return false; } + + chest_done = true; + 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); } } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index ad8c8dce3..06f802f9b 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -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() { diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index fbf4bca9f..4ab6d9460 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -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(); + gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_attempts, ATTACH_MAX_ATTEMPTS); + 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; diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 6904abc1e..f8ee8b4ce 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -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; - } + 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; - } + nas_log->info("NAS attached successfully.\n"); + } 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"); - } + nas_log->info("Attached successfully\n"); } else { - nas_log->error("Could not establish RRC connection\n"); + nas_log->error("Could not attach\n"); } + } else { + 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,54 +198,49 @@ 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) { - 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"); + 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("Timed out while trying to attach\n"); + 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() {} diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index d3ae1e341..c72f8063f 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -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,38 +171,71 @@ void rrc::run_tti(uint32_t tti) { return; } - rrc_log->debug("State %s\n", rrc_state_text[state]); - switch(state) { - case RRC_STATE_IDLE: - // 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"); - if (!cell_selection()) { - // If can not camp on any cell, search again for new cells - cell_search(); + /* 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) { + 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->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 + 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; - case RRC_STATE_CONNECTED: - if (ho_start) { - ho_start = false; - if (!ho_prepare()) { - con_reconfig_failed(); + break; + case RRC_STATE_CONNECTED: + if (ho_start) { + ho_start = false; + if (!ho_prepare()) { + con_reconfig_failed(); + } } - } - measurements.run_tti(tti); - if (go_idle) { - leave_connected(); - } - break; - default: - break; - } - cell_clean_cnt++; - if (cell_clean_cnt==1000) { - clean_neighbours(); - cell_clean_cnt = 0; - } + measurements.run_tti(tti); + if (go_idle) { + go_idle = false; + leave_connected(); + } + break; + default:break; + } + + // Clean old neighbours + cell_clean_cnt++; + 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"); - cell_selection(); - cnt++; - } + rrc_log->info("Initiation of Connection establishment procedure\n"); + + // Perform cell selection & reselection for the selected PLMN + cell_selection(); // .. 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(); - ret = true; + // 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"); + case phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND: + rrc_log->info("No cells found.\n"); break; - case phy_interface_rrc::NO_MORE_FREQS: - rrc_log->info("Finished searching for cells in current EARFCN set\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::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;iget_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,24 +1160,29 @@ 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 (mac_timers->timer_get(t311)->is_running()) { - // Actions following cell reselection while T311 is running 5.3.7.3 - rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); - liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - - mac_timers->timer_get(t301)->reset(); - mac_timers->timer_get(t301)->run(); - mac_timers->timer_get(t311)->stop(); - send_ul_ccch_msg(); + 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 + rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + + mac_timers->timer_get(t301)->reset(); + mac_timers->timer_get(t301)->run(); + 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 { - go_idle = true; + rrc_log->warning("Could not re-synchronize with cell.\n"); } } else { - rrc_log->warning("Could not re-synchronize with cell.\n"); + 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) { - 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; + 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()); + send_ul_info_transfer(sdu); } 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 diff --git a/srsue/test/mac/mac_test.cc b/srsue/test/mac/mac_test.cc index 3d21720d4..f8d3a1f80 100644 --- a/srsue/test/mac/mac_test.cc +++ b/srsue/test/mac/mac_test.cc @@ -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(); } } } diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 1c6f5f0e3..107a577b6 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -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; } From cc28aebced0b9a52f0ff75d8f6b72c14457b62ac Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 21 Mar 2018 19:22:37 +0100 Subject: [PATCH 05/52] Fixed SIB procedure --- srsue/src/upper/rrc.cc | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index c72f8063f..3d63c6b8e 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -598,6 +598,7 @@ bool rrc::si_acquire(uint32_t sib_index) uint32_t tti; uint32_t si_win_start=0, si_win_len=0; uint16_t period; + uint32_t sched_index; uint32_t x, sf, offset; uint32_t last_win_start = 0; @@ -619,31 +620,50 @@ bool rrc::si_acquire(uint32_t sib_index) si_win_len = 1; instruct_phy = true; } + period = 20; + sched_index = 0; } else { // Instruct MAC to look for SIB2..13 if (serving_cell->has_sib1()) { - uint32_t sysinfo_index = sib_index-1; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = serving_cell->sib1ptr(); - if(sysinfo_index < sib1->N_sched_info) { - si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; - x = sysinfo_index*si_win_len; - sf = x%10; - offset = x/10; - - tti = mac->get_current_tti(); - period = liblte_rrc_si_periodicity_num[sib1->sched_info[sysinfo_index].si_periodicity]; - si_win_start = sib_start_tti(tti, period, offset, sf); - si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; - - if (last_win_start == 0 || - (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000)) - { - last_win_start = si_win_start; - instruct_phy = true; - } + + // SIB2 scheduling + if (sib_index == 1) { + period = liblte_rrc_si_periodicity_num[sib1->sched_info[0].si_periodicity]; + sched_index = 0; } else { - rrc_log->warning("Trying to receive SIB%d but only %d available\n", sysinfo_index, sib1->N_sched_info); - return false; + // SIB3+ scheduling Section 5.2.3 + if (sib_index >= 2) { + bool found = false; + for (uint32_t i=0;iN_sched_info && !found;i++) { + for (uint32_t j=0;jsched_info[i].N_sib_mapping_info && !found;j++) { + if ((uint32_t) sib1->sched_info[i].sib_mapping_info[j].sib_type == sib_index - 2) { + period = liblte_rrc_si_periodicity_num[sib1->sched_info[i].si_periodicity]; + sched_index = i; + } + } + } + if (!found) { + rrc_log->error("Could not find SIB%d scheduling in SIB1\n", sib_index+1); + return false; + } + } + } + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; + x = sched_index*si_win_len; + sf = x%10; + offset = x/10; + + tti = mac->get_current_tti(); + si_win_start = sib_start_tti(tti, period, offset, sf); + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; + + if (last_win_start == 0 || + (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000)) + { + last_win_start = si_win_start; + instruct_phy = true; } } else { rrc_log->error("Trying to receive SIB%d but SIB1 not received\n", sib_index+1); @@ -653,8 +673,8 @@ bool rrc::si_acquire(uint32_t sib_index) // Instruct MAC to decode SIB if (instruct_phy && !serving_cell->has_sib(sib_index)) { mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d\n", - sib_index+1, si_win_start, si_win_len); + rrc_log->info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d, period=%d, sched_index=%d\n", + sib_index+1, si_win_start, si_win_len, period, sched_index); } usleep(1000); timeout++; @@ -1512,7 +1532,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { liblte_rrc_unpack_bcch_dlsch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dlsch_msg); for(uint32_t i=0; iinfo("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); + rrc_log->info("Processing SIB%d (%d/%d)\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type], i, dlsch_msg.N_sibs); if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type) { serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1); From 0d099a132b21625267474179b1c67ae13e04dd96 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 22 Mar 2018 11:47:30 +0100 Subject: [PATCH 06/52] Reconnection from paging and IDLE working. Reselecting cell when turning off working --- srsue/src/upper/gw.cc | 27 ++++++++++++--------------- srsue/src/upper/nas.cc | 1 + 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 4ab6d9460..f75d44e0f 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -248,9 +248,8 @@ void gw::run_thread() return; } - const static uint32_t ATTACH_TIMEOUT_S = 4; - const static uint32_t ATTACH_MAX_ATTEMPTS = 3; - uint32_t attach_attempts = 0; + const static uint32_t ATTACH_WAIT_TOUT = 40; // 4 sec + uint32_t attach_wait = 0; gw_log->info("GW IP packet receiver thread run_enable\n"); @@ -277,21 +276,19 @@ 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) { - gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_attempts, ATTACH_MAX_ATTEMPTS); - if (!nas->attach_request()) { - attach_attempts++; - sleep(ATTACH_TIMEOUT_S); - } else { - attach_attempts = 0; + while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_wait < ATTACH_WAIT_TOUT) { + if (!attach_wait) { + gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_wait, ATTACH_WAIT_TOUT); + if (!nas->attach_request()) { + gw_log->console("Could not re-establish the connection\n"); + break; + } } + usleep(100000); + attach_wait++; } - if (attach_attempts == ATTACH_MAX_ATTEMPTS) { - gw_log->warning("LCID=%d was not active after %d attempts\n", cfg.lcid, ATTACH_MAX_ATTEMPTS); - } - - attach_attempts = 0; + attach_wait = 0; if (!run_enable) { break; diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index f8ee8b4ce..7f42f9e4c 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -152,6 +152,7 @@ bool nas::attach_request() { nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n"); if (rrc_connect()) { nas_log->info("NAS attached successfully.\n"); + return true; } else { nas_log->error("Could not attach\n"); } From 9a7357cc945ecb7165a2178f91d34b883fef0937 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 9 Apr 2018 17:19:21 +0200 Subject: [PATCH 07/52] bump version to 18.03.1 --- CHANGELOG | 4 ++++ cmake/modules/SRSLTEVersion.cmake | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 9bed0247c..7a3a03e8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ Change Log for Releases ============================== +## 18.03.1 + * Fixed compilation for NEON + * Fixed logging and RLC AM issue + ## 18.03 * Many bug-fixes and improved stability and performance in all parts diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index 30d2707b0..11b2e79e9 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -20,5 +20,5 @@ SET(SRSLTE_VERSION_MAJOR 18) SET(SRSLTE_VERSION_MINOR 3) -SET(SRSLTE_VERSION_PATCH 0) +SET(SRSLTE_VERSION_PATCH 1) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") From d0d5893a1c9dfcfbefaaa935b65eabce55436e1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 6 Apr 2018 11:20:50 +0200 Subject: [PATCH 08/52] New DL channel noise estimator based on RS --- .../srslte/phy/ch_estimation/chest_dl.h | 8 + lib/src/phy/ch_estimation/chest_dl.c | 149 ++++++++++++++---- 2 files changed, 124 insertions(+), 33 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index a521d653e..5f7731305 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -74,6 +74,7 @@ typedef struct { float snr_vector[12000]; float pilot_power[12000]; #endif + bool smooth_filter_auto; uint32_t smooth_filter_len; float smooth_filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN]; @@ -123,6 +124,13 @@ SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w); +SRSLTE_API void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, + uint32_t order, + float std_dev); + +SRSLTE_API void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t* q, + bool enable); + SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, srslte_chest_dl_noise_alg_t noise_estimation_alg); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index e719b22c0..06bc43d66 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -155,6 +155,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) q->rsrp_neighbour = false; + q->smooth_filter_auto = false; q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); @@ -263,41 +264,66 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) /* Uses the difference between the averaged and non-averaged pilot estimates */ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslte_sf_t ch_mode) { - int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + const float weight = 1.0f; + float sum_power = 0.0f; + uint32_t count = 0; + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t nsymbols = + (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() : srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = npilots / nsymbols; + uint32_t fidx = srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); - if (q->average_subframe) { - if (ch_mode == SRSLTE_SF_MBSFN) { - nref /= 4; - } else { - nref /= 2; - } + cf_t *input2d[nsymbols + 2]; + cf_t *tmp_noise = q->tmp_noise; + + for (int i = 0; i < nsymbols; i++) { + input2d[i + 1] = &q->pilot_estimates[i * nref]; } - /* Substract noisy pilot estimates */ - srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); - -#ifdef FREQ_SEL_SNR - /* Compute frequency-selective SNR */ - srslte_vec_abs_square_cf(q->tmp_noise, q->snr_vector, nref); - srslte_vec_abs_square_cf(q->pilot_estimates, q->pilot_power, nref); - srslte_vec_div_fff(q->pilot_power, q->snr_vector, q->snr_vector, nref); - - srslte_vec_fprint_f(stdout, q->snr_vector, nref); -#endif - - /* Compute average power. Normalized for filter len 3 using matlab */ - float norm = 1; - if (q->average_subframe) { - norm = 32; + input2d[0] = &q->tmp_noise[0]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref); + srslte_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref); + } else { + srslte_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref); + } + + input2d[nsymbols + 1] = &q->tmp_noise[nref]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 2.0f, input2d[nsymbols + 1], nref); + srslte_vec_sub_ccc(input2d[nsymbols + 1], input2d[nsymbols - 3], input2d[nsymbols + 1], nref); } else { - if (q->smooth_filter_len == 3) { - float a = q->smooth_filter[0]; - float norm3 = 6.143*a*a+0.04859*a-0.002774; - norm /= norm3; + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 1.0f, input2d[nsymbols + 1], nref); + } + + for (int i = 1; i < nsymbols + 1; i++) { + uint32_t offset = ((fidx < 3) ^ (i & 1)) ? 0 : 1; + srslte_vec_sc_prod_cfc(input2d[i], weight, tmp_noise, nref); + + srslte_vec_sum_ccc(&input2d[i - 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i - 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i - 1][0] - input2d[i - 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i - 1][nref - 2] - input2d[i - 1][nref - 1]; + } + + srslte_vec_sum_ccc(&input2d[i + 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i + 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i + 1][0] - input2d[i + 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i + 1][nref - 2] - input2d[i + 1][nref - 1]; } + + srslte_vec_sc_prod_cfc(tmp_noise, 1.0f / (weight + 4.0f), tmp_noise, nref); + + srslte_vec_sub_ccc(input2d[i], tmp_noise, tmp_noise, nref); + sum_power = srslte_vec_avg_power_cf(tmp_noise, nref); + count++; } - float power = norm*srslte_vec_avg_power_cf(q->tmp_noise, nref); - return power; + + return sum_power / (float) count * sqrtf(weight + 4.0f); } static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) @@ -443,6 +469,53 @@ void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w) q->smooth_filter[1] = 1-2*w; } +void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, uint32_t order, float std_dev) +{ + const uint32_t filterlen = order + 1; + const int center = (filterlen - 1) / 2; + float *filter = q->smooth_filter; + float norm_p = 0.0f; + + if (filterlen) { + + for (int i = 0; i < filterlen; i++) { + filter[i] = expf(-powf(i - center, 2) / (2.0f * powf(std_dev, 2))); + norm_p += powf(filter[i], 2); + } + + const float norm = srslte_vec_acc_ff(filter, filterlen); + + srslte_vec_sc_prod_fff(filter, 1.0f / norm, filter, filterlen); + q->smooth_filter_len = filterlen; + } +} + +void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t *q, bool enable) { + q->smooth_filter_auto = enable; +} + +uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *tmp, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { + uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; + + if (srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0) < 3) { + srslte_vec_interleave(input, &input[nref], tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], tmp, nref); + } + } else { + srslte_vec_interleave(&input[nref], input, tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[(l + 1) * nref], &input[l * nref], tmp, nref); + } + } + + nref *= 2; + srslte_vec_sc_prod_cfc(tmp, 2.0f / nsymbols, output, nref); + + return nref; +} + static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; @@ -519,11 +592,23 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) } void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols():srslte_refsignal_cs_nof_symbols(port_id); + if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { q->cfo = chest_estimate_cfo(q); } + /* Estimate noise */ + if (q->noise_alg == SRSLTE_NOISE_ALG_REFS) { + q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); + } + if (ce != NULL) { + if (q->smooth_filter_auto) { + srslte_chest_dl_set_smooth_filter_gauss(q, 4, q->noise_estimate[rxant_id][port_id] * 200.0f); + } + /* Smooth estimates (if applicable) and interpolate */ if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode); @@ -533,13 +618,11 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } /* Estimate noise power */ - if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) { - q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); - } else if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { + if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce); } - } else { + } else if (q->noise_alg != SRSLTE_NOISE_ALG_REFS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input); } From 15173c5c3054a6a75eeab9ec3970ae149e430a00 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 6 Apr 2018 13:24:25 +0200 Subject: [PATCH 09/52] Added gaussian filter configuration options in srsue.conf --- lib/include/srslte/interfaces/ue_interfaces.h | 6 ++++-- lib/src/phy/ch_estimation/chest_dl.c | 3 --- srsue/src/main.cc | 16 ++++++++++++---- srsue/src/phy/phch_worker.cc | 12 +++++------- srsue/src/phy/phy.cc | 8 +++----- srsue/ue.conf.example | 8 ++++++-- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index b1c0672d3..f9e8c09c2 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -487,9 +487,11 @@ typedef struct { uint32_t cfo_loop_pss_conv; uint32_t cfo_ref_mask; bool average_subframe_enabled; - int time_correct_period; + bool estimator_fil_auto; + float estimator_fil_stddev; + uint32_t estimator_fil_order; + int time_correct_period; std::string sss_algorithm; - float estimator_fil_w; bool rssi_sensor_enabled; bool sic_pss_enabled; float rx_gain_offset; diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 06bc43d66..238cd1a18 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -592,9 +592,6 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) } void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ - uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); - uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols():srslte_refsignal_cs_nof_symbols(port_id); - if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { q->cfo = chest_estimate_cfo(q); } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index a30892cc7..4acb7c8d9 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -261,6 +261,18 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&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.estimator_fil_auto", + bpo::value(&args->expert.phy.estimator_fil_auto)->default_value(false), + "The channel estimator smooths the channel estimate with an adaptative filter.") + + ("expert.estimator_fil_stddev", + bpo::value(&args->expert.phy.estimator_fil_stddev)->default_value(1.0f), + "Sets the channel estimator smooth gaussian filter standard deviation.") + + ("expert.estimator_fil_order", + bpo::value(&args->expert.phy.estimator_fil_order)->default_value(4), + "Sets the channel estimator smooth gaussian filter order (even values perform better).") + ("expert.time_correct_period", bpo::value(&args->expert.phy.time_correct_period)->default_value(5), "Period for sampling time offset correction.") @@ -269,10 +281,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.sss_algorithm)->default_value("full"), "Selects the SSS estimation algorithm.") - ("expert.estimator_fil_w", - bpo::value(&args->expert.phy.estimator_fil_w)->default_value(0.1), - "Chooses the coefficients for the 3-tap channel estimator centered filter.") - ("expert.pdsch_csi_enabled", bpo::value(&args->expert.phy.pdsch_csi_enabled)->default_value(false), "Stores the Channel State Information and uses it for weightening the softbits. It is only compatible with TM1.") diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 7ac2ed040..282299bf0 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -441,13 +441,11 @@ bool phch_worker::extract_fft_and_pdcch_llr() { if (phy->get_pending_ack(tti) || decode_pdcch) { // Setup estimator filter - float w_coeff = phy->args->estimator_fil_w; - if (w_coeff > 0.0) { - srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); - } else if (w_coeff == 0.0) { - srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0); - } - + srslte_chest_dl_set_smooth_filter_gauss(&ue_dl.chest, + phy->args->estimator_fil_order, + phy->args->estimator_fil_stddev); + srslte_chest_dl_set_smooth_filter_auto(&ue_dl.chest, phy->args->estimator_fil_auto); + if (!phy->args->snr_estim_alg.compare("refs")) { srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); } else if (!phy->args->snr_estim_alg.compare("empty")) { diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 90dbc2833..be0e2b411 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -98,7 +98,9 @@ void phy::set_default_args(phy_args_t *args) args->cfo_correct_tol_hz = 50; args->time_correct_period = 5; args->sss_algorithm = "full"; - args->estimator_fil_w = 0.1; + args->estimator_fil_auto = false; + args->estimator_fil_stddev = 1.0f; + args->estimator_fil_order = 4; } bool phy::check_args(phy_args_t *args) @@ -107,10 +109,6 @@ bool phy::check_args(phy_args_t *args) log_h->console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n"); return false; } - if (args->estimator_fil_w > 1.0) { - log_h->console("Error in PHY args: estimator_fil_w must be 0<=w<=1\n"); - return false; - } if (args->snr_ema_coeff > 1.0) { log_h->console("Error in PHY args: snr_ema_coeff must be 0<=w<=1\n"); return false; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index a3de1a678..531381431 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -150,7 +150,9 @@ enable = false # sampling frequency offset. Default is enabled. # sss_algorithm: Selects the SSS estimation algorithm. Can choose between # {full, partial, diff}. -# estimator_fil_w: Chooses the coefficients for the 3-tap channel estimator centered filter. +# estimator_fil_auto: The channel estimator smooths the channel estimate with an adaptative filter. +# estimator_fil_stddev: Sets the channel estimator smooth gaussian filter standard deviation. +# estimator_fil_order: Sets the channel estimator smooth gaussian filter order (even values perform better). # The taps are [w, 1-2w, w] # metrics_period_secs: Sets the period at which metrics are requested from the UE. # @@ -204,7 +206,9 @@ enable = false #time_correct_period = 5 #sfo_correct_disable = false #sss_algorithm = full -#estimator_fil_w = 0.1 +#estimator_fil_auto = false +#estimator_fil_stddev = 1.0 +#estimator_fil_order = 4 #average_subframe_enabled = true #sic_pss_enabled = true #pregenerate_signals = false From 09e6f164a489f3b5050751ce2fa0322ff9b704b9 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 10 Apr 2018 13:17:59 +0200 Subject: [PATCH 10/52] UE synchronizer can miss up to 100 PSS. This reduces PSS lost of synch for slow fading channels such as EVA5. --- lib/src/phy/ue/ue_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b66cf5b53..38355af92 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -41,7 +41,7 @@ #define MAX_TIME_OFFSET 128 -#define TRACK_MAX_LOST 4 +#define TRACK_MAX_LOST 100 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 4 #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 From f5b8343244413f3150593a412d0e9915a95dd356 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 10 Apr 2018 17:42:50 +0200 Subject: [PATCH 11/52] srsenb now prints an error message when the QCI is not valid --- srsenb/src/upper/rrc.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index f47656c6d..3f6516a48 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1447,6 +1447,7 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu) // Get DRB1 configuration if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0], 1)) { parent->rrc_log->error("Getting DRB1 configuration\n"); + printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI); } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size = 1; } @@ -1525,7 +1526,8 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE // Get DRB configuration if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid)) { - parent->rrc_log->error("Getting DRB configuration\n"); + parent->rrc_log->error("Getting DRB configuration\n"); + printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[lcid+4].qos_params.qCI.QCI); } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size++; } From 296d49f3eb20d98592318f0bf3542182497997da Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 10 Apr 2018 19:45:06 +0200 Subject: [PATCH 12/52] Now enb does not crash when the QCI is not invalid. --- srsenb/src/upper/rrc.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 3f6516a48..9ceb3883a 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1447,7 +1447,8 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu) // Get DRB1 configuration if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0], 1)) { parent->rrc_log->error("Getting DRB1 configuration\n"); - printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI); + printf("The QCI %d for DRB1 is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI); + return; } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size = 1; } @@ -1528,6 +1529,7 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid)) { parent->rrc_log->error("Getting DRB configuration\n"); printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[lcid+4].qos_params.qCI.QCI); + return; } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size++; } From c104c9e3c8e441b7c28afb61076d8086b56d4f75 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 11 Apr 2018 10:50:14 +0200 Subject: [PATCH 13/52] solved the small inconsistency with the drbid/lcid/erabid --- srsenb/src/upper/rrc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 9ceb3883a..93b9f8499 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1526,7 +1526,7 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) // Get DRB configuration - if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid)) { + if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid-2)) { parent->rrc_log->error("Getting DRB configuration\n"); printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[lcid+4].qos_params.qCI.QCI); return; From ff1269add340b2e73cb163ba060ff911e05a2b60 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 11 Apr 2018 15:37:27 +0200 Subject: [PATCH 14/52] HO working --- lib/src/phy/rf/rf_uhd_imp.c | 1 - srsue/hdr/phy/phch_recv.h | 1 - srsue/src/phy/phch_recv.cc | 27 ++++++++++++--------------- srsue/src/ue.cc | 2 +- srsue/src/upper/gw.cc | 2 +- srsue/src/upper/rrc.cc | 18 +++++++++++++----- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 618d4577f..1c09b7990 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -772,7 +772,6 @@ 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); diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 4cabf660f..faff85ca7 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -259,7 +259,6 @@ private: bool running; // Objects for internal use - measure measure_p; search search_p; sfn_sync sfn_p; intra_measure intra_freq_meas; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index fc36760e0..9d24160e0 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -26,6 +26,8 @@ #include #include +#include +#include #include "srslte/srslte.h" #include "srslte/common/log.h" #include "srsue/hdr/phy/phch_worker.h" @@ -90,9 +92,6 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma // Initialize SFN synchronizer sfn_p.init(&ue_sync, sf_buffer, log_h); - // Initialize measurement class for the primary cell - measure_p.init(sf_buffer, log_h, nof_rx_antennas); - // Start intra-frequency measurement intra_freq_meas.init(worker_com, rrc, log_h); @@ -137,7 +136,6 @@ void phch_recv::reset() srate_mode = SRATE_NONE; current_earfcn = -1; sfn_p.reset(); - measure_p.reset(); search_p.reset(); phy_state.go_idle(); @@ -289,7 +287,6 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { worker_com->reset(); sfn_p.reset(); search_p.reset(); - measure_p.reset(); srslte_ue_sync_reset(&ue_sync); /* Reconfigure cell if necessary */ @@ -351,8 +348,7 @@ bool phch_recv::cell_is_camping() { * * It has 3 states: Cell search, SFN syncrhonization, intial measurement and camping. * - CELL_SEARCH: Initial Cell id and MIB acquisition. Uses 1.92 MHz sampling rate - * - CELL_SFN_SYNC: Full sampling rate, uses MIB to obtain SFN. When SFN is obtained, moves to CELL_MEASURE or CELL_CAMP - * - CELL_MEASURE: RSRP/SNR measurement to determine suitability for camping. + * - CELL_SYNC: Full sampling rate, uses MIB to obtain SFN. When SFN is obtained, moves to CELL_CAMP * - CELL_CAMP: Cell camping state. Calls the PHCH workers to process subframes and mantains cell synchronization. * - IDLE: Receives and discards received samples. Does not mantain synchronization. * @@ -550,7 +546,6 @@ void phch_recv::run_thread() * */ void phch_recv::radio_overflow() { - log_h->warning("Overflow\n"); radio_is_overflow = true; } @@ -677,7 +672,6 @@ bool phch_recv::set_cell() { Error("SYNC: Setting cell: initiating ue_sync\n"); return false; } - measure_p.set_cell(cell); sfn_p.set_cell(cell); worker_com->set_cell(cell); intra_freq_meas.set_primay_cell(current_earfcn, cell); @@ -1075,6 +1069,7 @@ void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h Error("SYNC: Initiating ue_dl_measure\n"); return; } + srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); reset(); } @@ -1148,6 +1143,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in offset = offset-sf_len/2; while (offset < 0 && sf_idx < max_sf) { + Info("INTRA: offset=%d, sf_idx=%d\n", offset, sf_idx); offset += sf_len; sf_idx ++; } @@ -1205,6 +1201,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in } } else { Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); + ret = ERROR; } return ret; } @@ -1372,7 +1369,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (cell_id >= 0) { // We found the same cell as before, look another N_id_2 if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { - Info("n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n", n_id_2, cell_id, found_cell.id, cell.id); + Debug("INTRA: n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n", n_id_2, cell_id, found_cell.id, cell.id); sync_res = SRSLTE_SYNC_NOFOUND; } else { // We found a new cell ID @@ -1390,7 +1387,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { - case measure::MEASURE_OK: + default: // Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) { cells[nof_cells].pci = found_cell.id; @@ -1409,13 +1406,13 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (sic_pss_enabled) { srslte_pss_sic(&sync_find.pss, &input_buffer[sf5_cnt * 5 * sf_len + sf_len / 2 - fft_sz]); }*/ + } else { + Info("INTRA: Found neighbour cell but RSRP=%.1f dBm is below threshold (%.1f dBm)\n", + measure_p.rsrp(), ABSOLUTE_RSRP_THRESHOLD_DBM); } break; - default: - Info("INTRA: Not enough samples to measure PCI=%d\n", cell_id); - break; case measure::ERROR: - Error("Measuring neighbour cell\n"); + Error("INTRA: Measuring neighbour cell\n"); return SRSLTE_ERROR; } } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 6c87b3c17..8c10f9a51 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -282,7 +282,7 @@ bool ue::deattach() { bool ue::is_attached() { - return nas.is_attached(); + return rrc.is_connected(); } void ue::start_plot() { diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 0201cfe14..c4b482b92 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -280,7 +280,7 @@ void gw::run_thread() if (!attach_wait) { gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_wait, ATTACH_WAIT_TOUT); if (!nas->attach_request()) { - gw_log->console("Could not re-establish the connection\n"); + gw_log->info("Could not re-establish the connection\n"); break; } } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index cb30c5eef..089e80f7c 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -470,16 +470,21 @@ bool rrc::configure_serving_cell() { * 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) { + uint32_t pci = 0; + uint32_t earfcn = 0; if (earfcn_i < 0) { - earfcn_i = (int) serving_cell->get_earfcn(); + earfcn = (uint32_t) serving_cell->get_earfcn(); + } else { + earfcn = (uint32_t) earfcn_i; } if (pci_i < 0) { - pci_i = (int) serving_cell->get_pci(); + pci = (uint32_t) serving_cell->get_pci(); + } else { + pci = (uint32_t) pci_i; } - - phy_meas_t new_meas = {rsrp, rsrq, tti, (uint32_t) earfcn_i, (uint32_t) pci_i}; + phy_meas_t new_meas = {rsrp, rsrq, tti, earfcn, pci}; phy_meas_q.push(new_meas); - rrc_log->info("MEAS: New measurement pci=%d, rsrp=%.1f dBm.\n", pci_i, rsrp); + rrc_log->info("MEAS: New measurement pci=%d, rsrp=%.1f dBm.\n", pci, rsrp); } /* Processes all pending PHY measurements in queue. Must be called from a mutexed function @@ -1311,6 +1316,9 @@ bool rrc::ho_prepare() { neighbour_cells[target_cell_idx]->get_pci()); return false; } + + set_serving_cell(target_cell_idx); + if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, From 97546d92a57aa012f56b325269fd85d4b9c16b28 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 11 Apr 2018 16:26:03 +0200 Subject: [PATCH 15/52] Continue if SIB>2 is not received --- srsue/src/phy/phch_worker.cc | 4 ++-- srsue/src/upper/rrc.cc | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index e19912a1d..627bddaa1 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -394,7 +394,7 @@ void phch_worker::work_imp() if (chest_ok) { if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -10.0) { - log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", + log_h->info("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", phy->avg_snr_db, phy->avg_rsrp_dbm); chest_loop->in_sync(); } else { @@ -1460,7 +1460,7 @@ void phch_worker::update_measurements() dl_metrics.sinr = phy->avg_snr_db; dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch); phy->set_dl_metrics(dl_metrics); - + } } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 089e80f7c..9f4022825 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -442,7 +442,9 @@ bool rrc::configure_serving_cell() { 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); - return false; + if (i < 2) { + return false; + } } } else { rrc_log->info("Cell has SIB%d\n", i+1); From d3e5aa072e8ace7031e3b07a856be05f0e1f309b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 11 Apr 2018 18:02:13 +0200 Subject: [PATCH 16/52] Mutex overflow logic with rrc API in phch_recv --- srsue/src/phy/phch_recv.cc | 45 ++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 9d24160e0..7cd7a7abe 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -498,30 +498,33 @@ void phch_recv::run_thread() /* Radio overflow detected. If CAMPING, go through SFN sync again and when * SFN is found again go back to camping */ - if (radio_is_overflow) { - // If we are coming back from an overflow - if (radio_overflow_return) { - if (phy_state.is_camping()) { - log_h->info("Successfully resynchronized after overflow. Returning to CAMPING\n"); - radio_overflow_return = false; - radio_is_overflow = false; - } 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(); - } - } 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; + if (!pthread_mutex_trylock(&rrc_mutex)) { + if (radio_is_overflow) { + // If we are coming back from an overflow + if (radio_overflow_return) { + if (phy_state.is_camping()) { + log_h->info("Successfully resynchronized after overflow. Returning to CAMPING\n"); + radio_overflow_return = false; + radio_is_overflow = false; + } 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(); + } } else { - radio_is_overflow = false; + // 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 } - // If overflow occurs in any other state, it does not harm } + pthread_mutex_unlock(&rrc_mutex); } // Increase TTI counter From e31b92c873d40f9ffd1bdcec13b6eb47d62330c1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 12 Apr 2018 17:24:16 +0200 Subject: [PATCH 17/52] Fixed negative UE Power Headroom --- lib/src/radio/radio.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 7008790a3..a15c6dce9 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -175,7 +175,7 @@ float radio::set_tx_power(float power) float radio::get_max_tx_power() { - return 10; + return 40; } float radio::get_rssi() From 99253cb703d3dbf3794918072f54e4c500bb3c95 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 12 Apr 2018 18:17:15 +0200 Subject: [PATCH 18/52] Cherry picked fixes from PR #160 --- lib/src/common/log_filter.cc | 18 +++++++++--------- srsue/hdr/upper/rrc.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index a86a36f1e..9602e202a 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -136,7 +136,7 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, } void log_filter::console(const char * message, ...) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -147,7 +147,7 @@ void log_filter::console(const char * message, ...) { void log_filter::error(const char * message, ...) { if (level >= LOG_LEVEL_ERROR) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -158,7 +158,7 @@ void log_filter::error(const char * message, ...) { } void log_filter::warning(const char * message, ...) { if (level >= LOG_LEVEL_WARNING) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -169,7 +169,7 @@ void log_filter::warning(const char * message, ...) { } void log_filter::info(const char * message, ...) { if (level >= LOG_LEVEL_INFO) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -180,7 +180,7 @@ void log_filter::info(const char * message, ...) { } void log_filter::debug(const char * message, ...) { if (level >= LOG_LEVEL_DEBUG) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -192,7 +192,7 @@ void log_filter::debug(const char * message, ...) { void log_filter::error_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_ERROR) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -203,7 +203,7 @@ void log_filter::error_hex(const uint8_t *hex, int size, const char * message, . } void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_WARNING) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -214,7 +214,7 @@ void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, } void log_filter::info_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_INFO) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -225,7 +225,7 @@ void log_filter::info_hex(const uint8_t *hex, int size, const char * message, .. } void log_filter::debug_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_DEBUG) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index ba8fdd046..db61c01e5 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -107,7 +107,7 @@ class cell_t } void set_rsrp(float rsrp) { - if (~isnan(rsrp)) { + if (!isnan(rsrp)) { this->rsrp = rsrp; } in_sync = true; From 5d9433b34006ffecb8078ebc4e458317a4952891 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 13 Apr 2018 11:34:04 +0200 Subject: [PATCH 19/52] Removed log info --- srsue/src/phy/phch_worker.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 663cb52db..212c5839a 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -394,7 +394,7 @@ void phch_worker::work_imp() if (chest_ok) { if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -10.0) { - log_h->info("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", + log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", phy->avg_snr_db, phy->avg_rsrp_dbm); chest_loop->in_sync(); } else { From 190015435b3fbbd671ae7c244553592f9bcabbc9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 17 Apr 2018 13:30:37 +0100 Subject: [PATCH 20/52] Fixed some un-initialized variables in E-RAB Setup Response. --- srsenb/src/upper/rrc.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 93b9f8499..2afedad08 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1090,9 +1090,13 @@ void rrc::ue::notify_s1ap_ue_ctxt_setup_complete() void rrc::ue::notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e) { LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT res; + res.ext=false; res.E_RABSetupListBearerSURes.len = 0; res.E_RABFailedToSetupListBearerSURes.len = 0; + res.CriticalityDiagnostics_present = false; + res.E_RABFailedToSetupListBearerSURes_present = false; + for(uint32_t i=0; ilen; i++) { res.E_RABSetupListBearerSURes_present = true; LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT *erab = &e->buffer[i]; From 384e0f86499fca03a6a57ebc60711c62de465fce Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 17 Apr 2018 19:16:04 +0200 Subject: [PATCH 21/52] Fixed UL interleaver (missing SIMD deinterleaver) --- lib/include/srslte/phy/phch/sch.h | 2 +- lib/include/srslte/phy/utils/bit.h | 11 +++++ lib/include/srslte/phy/utils/vector.h | 1 + lib/src/phy/phch/sch.c | 14 +++---- lib/src/phy/utils/bit.c | 59 +++++++++++++++++++++++++++ lib/src/phy/utils/vector.c | 6 +++ 6 files changed, 85 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/phy/phch/sch.h b/lib/include/srslte/phy/phch/sch.h index 4ef0328e7..003e9b7df 100644 --- a/lib/include/srslte/phy/phch/sch.h +++ b/lib/include/srslte/phy/phch/sch.h @@ -64,7 +64,7 @@ typedef struct SRSLTE_API { uint8_t *parity_bits; void *e; uint8_t *temp_g_bits; - uint16_t *ul_interleaver; + uint32_t *ul_interleaver; srslte_uci_bit_t ack_ri_bits[12*288]; uint32_t nof_ri_ack_bits; diff --git a/lib/include/srslte/phy/utils/bit.h b/lib/include/srslte/phy/utils/bit.h index 29fca8e9e..8a4ff789b 100644 --- a/lib/include/srslte/phy/utils/bit.h +++ b/lib/include/srslte/phy/utils/bit.h @@ -70,6 +70,17 @@ SRSLTE_API void srslte_bit_copy(uint8_t *dst, uint32_t src_offset, uint32_t nof_bits); +SRSLTE_API void srslte_bit_interleave_i(uint8_t *input, + uint8_t *output, + uint32_t *interleaver, + uint32_t nof_bits); + +SRSLTE_API void srslte_bit_interleave_i_w_offset(uint8_t *input, + uint8_t *output, + uint32_t *interleaver, + uint32_t nof_bits, + uint32_t w_offset); + SRSLTE_API void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *interleaver, diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 1fcbe4235..d6742fb3c 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -99,6 +99,7 @@ SRSLTE_API void srslte_vec_convert_fi(const float *x, const float scale, int16_t SRSLTE_API void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len); SRSLTE_API void srslte_vec_lut_sss(const short *x, const unsigned short *lut, short *y, const uint32_t len); +SRSLTE_API void srslte_vec_lut_sis(const short *x, const unsigned int *lut, short *y, const uint32_t len); /* vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index b679e00f9..f419ea826 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -130,7 +130,7 @@ int srslte_sch_init(srslte_sch_t *q) { goto clean; } bzero(q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12); - q->ul_interleaver = srslte_vec_malloc(sizeof(uint16_t)*SRSLTE_MAX_PRB*12*12*12); + q->ul_interleaver = srslte_vec_malloc(sizeof(uint32_t)*SRSLTE_MAX_PRB*12*12*12); if (!q->ul_interleaver) { goto clean; } @@ -577,7 +577,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu * Profiling show that the computation of this matrix is neglegible. */ static void ulsch_interleave_gen(uint32_t H_prime_total, uint32_t N_pusch_symbs, uint32_t Qm, - uint8_t *ri_present, uint16_t *interleaver_lut) + uint8_t *ri_present, uint32_t *interleaver_lut) { uint32_t rows = H_prime_total/N_pusch_symbs; uint32_t cols = N_pusch_symbs; @@ -599,7 +599,7 @@ static void ulsch_interleave_gen(uint32_t H_prime_total, uint32_t N_pusch_symbs, /* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits, - uint8_t *ri_present, uint16_t *inteleaver_lut) + uint8_t *ri_present, uint32_t *inteleaver_lut) { // Prepare ri_bits for fast search using temp_buffer @@ -611,7 +611,7 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, // Genearate interleaver table and interleave bits ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); - srslte_bit_interleave(g_bits, q_bits, inteleaver_lut, H_prime_total*Qm); + srslte_bit_interleave_i(g_bits, q_bits, inteleaver_lut, H_prime_total*Qm); // Reset temp_buffer because will be reused next time if (nof_ri_bits > 0) { @@ -624,7 +624,7 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, /* UL-SCH channel deinterleaver according to 5.2.2.8 of 36.212 */ void ulsch_deinterleave(int16_t *q_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, int16_t *g_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits, - uint8_t *ri_present, uint16_t *inteleaver_lut) + uint8_t *ri_present, uint32_t *inteleaver_lut) { // Prepare ri_bits for fast search using temp_buffer if (nof_ri_bits > 0) { @@ -634,8 +634,8 @@ void ulsch_deinterleave(int16_t *q_bits, uint32_t Qm, uint32_t H_prime_total, } // Generate interleaver table and interleave samples - ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); - srslte_vec_lut_sss(q_bits, inteleaver_lut, g_bits, H_prime_total*Qm); + ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); + srslte_vec_lut_sis(q_bits, inteleaver_lut, g_bits, H_prime_total*Qm); // Reset temp_buffer because will be reused next time if (nof_ri_bits > 0) { diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index f4e97fad6..6ef061252 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -205,6 +205,65 @@ void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, uint8_t *input, uin } +void srslte_bit_interleave_i(uint8_t *input, uint8_t *output, uint32_t *interleaver, uint32_t nof_bits) { + srslte_bit_interleave_i_w_offset(input, output, interleaver, nof_bits, 0); +} + +void srslte_bit_interleave_i_w_offset(uint8_t *input, uint8_t *output, uint32_t *interleaver, uint32_t nof_bits, uint32_t w_offset) { + uint32_t st=0, w_offset_p=0; + static const uint8_t mask[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + + if (w_offset < 8 && w_offset > 0) { + st=1; + for (uint32_t j=0;j<8-w_offset;j++) { + uint32_t i_p = interleaver[j]; + if (input[i_p/8] & mask[i_p%8]) { + output[0] |= mask[j+w_offset]; + } else { + output[0] &= ~(mask[j+w_offset]); + } + } + w_offset_p=8-w_offset; + } + for (uint32_t i=st;i Date: Wed, 18 Apr 2018 13:23:48 +0200 Subject: [PATCH 22/52] Implemented SSE/MMX int32 bit Interleaver --- lib/src/phy/utils/bit.c | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index 6ef061252..674c1da81 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -225,6 +225,102 @@ void srslte_bit_interleave_i_w_offset(uint8_t *input, uint8_t *output, uint32_t } w_offset_p=8-w_offset; } + +#ifdef LV_HAVE_SSE + __m64 m64mask = _mm_setr_pi8((uint8_t) 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1); + + union { + uint8_t v[8]; + __m64 m64; + } a, b, c; + + union { + __m128i m128; + uint16_t u32[4]; + uint16_t u16[8]; + uint8_t u8[16]; + struct { + __m64 reg_a; + __m64 reg_b; + } m64; + struct { + uint16_t i0, i1, i2, i3, i4, i5, i6, i7; + } v16; + struct { + uint32_t i0, i1, i2, i3; + } v32; + } ipx1, ipx2, epx1, epx2; + for (uint32_t i = st; i < nof_bits / 8; i++) { + ipx1.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8 + 0) - w_offset_p)); + epx1.m128 = _mm_shuffle_epi8(ipx1.m128, _mm_set_epi8(0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C)); + ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8 + 4) - w_offset_p)); + epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C)); + + epx1.m128 = _mm_blendv_epi8(epx2.m128, epx1.m128, _mm_setr_epi8(+1, +1, +1, +1, + -1, -1, -1, -1, + +1, +1, +1, +1, + -1, -1, -1, -1)); + + b.m64 = _mm_and_si64(epx1.m64.reg_a, _mm_set1_pi8(0x7)); + b.m64 = _mm_shuffle_pi8(m64mask, b.m64); + + ipx1.m128 = _mm_srli_epi32(ipx1.m128, 3); + ipx2.m128 = _mm_srli_epi32(ipx2.m128, 3); + + a.m64 = _mm_set_pi8(input[ipx1.v32.i0], + input[ipx1.v32.i1], + input[ipx1.v32.i2], + input[ipx1.v32.i3], + input[ipx2.v32.i0], + input[ipx2.v32.i1], + input[ipx2.v32.i2], + input[ipx2.v32.i3]); + + c.m64 = _mm_cmpeq_pi8(_mm_and_si64(a.m64, b.m64), b.m64); + output[i] = (uint8_t) _mm_movemask_pi8(c.m64); + } + +#if 0 /* Disabled */ + /* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */ + uint8_t *output2 = malloc(nof_bits/8); + for (uint32_t i=st;i Date: Mon, 16 Apr 2018 21:30:18 +0200 Subject: [PATCH 23/52] Added DL CSI decoding to TM2 and TM3 --- lib/include/srslte/phy/mimo/precoding.h | 7 +- lib/include/srslte/phy/utils/mat.h | 119 ++++- lib/include/srslte/phy/utils/simd.h | 148 +++++- lib/src/phy/mimo/layermap.c | 2 +- lib/src/phy/mimo/precoding.c | 571 +++++++++++++++++------- lib/src/phy/phch/pcfich.c | 2 +- lib/src/phy/phch/pdcch.c | 2 +- lib/src/phy/phch/pdsch.c | 4 +- lib/src/phy/phch/phich.c | 2 +- lib/src/phy/utils/mat.c | 31 +- lib/src/phy/utils/test/mat_test.c | 102 ++++- lib/src/phy/utils/vector.c | 4 +- 12 files changed, 788 insertions(+), 206 deletions(-) diff --git a/lib/include/srslte/phy/mimo/precoding.h b/lib/include/srslte/phy/mimo/precoding.h index d363231e2..5caf4f0ca 100644 --- a/lib/include/srslte/phy/mimo/precoding.h +++ b/lib/include/srslte/phy/mimo/precoding.h @@ -87,7 +87,7 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y, SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, - float *csi, + float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_symbols, float scaling, @@ -102,7 +102,8 @@ SRSLTE_API int srslte_predecoding_diversity(cf_t *y, SRSLTE_API int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_ports, int nof_symbols, @@ -113,7 +114,7 @@ SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - float *csi, + float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_ports, int nof_layers, diff --git a/lib/include/srslte/phy/utils/mat.h b/lib/include/srslte/phy/utils/mat.h index a0f11abe3..8db0205f9 100644 --- a/lib/include/srslte/phy/utils/mat.h +++ b/lib/include/srslte/phy/utils/mat.h @@ -53,12 +53,17 @@ SRSLTE_API void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, float noise_estimate, float norm); +SRSLTE_API void srslte_mat_2x2_mmse_csi_gen(cf_t y0, cf_t y1, + cf_t h00, cf_t h01, cf_t h10, cf_t h11, + cf_t *x0, cf_t *x1, float *csi0, float *csi1, + float noise_estimate, + float norm); + SRSLTE_API float srslte_mat_2x2_cn(cf_t h00, cf_t h01, cf_t h10, cf_t h11); - #ifdef LV_HAVE_SSE /* SSE implementation for complex reciprocal */ @@ -103,4 +108,114 @@ SRSLTE_API void srslte_mat_2x2_mmse_avx(__m256 y0, __m256 y1, #endif /* LV_HAVE_AVX */ -#endif // SRSLTE_MAT_H +#if SRSLTE_SIMD_CF_SIZE != 0 + +/* Generic SIMD implementation for 2x2 determinant */ +static inline simd_cf_t srslte_mat_2x2_det_simd(simd_cf_t a00, simd_cf_t a01, simd_cf_t a10, simd_cf_t a11) { + return srslte_simd_cf_sub(srslte_simd_cf_prod(a00, a11), srslte_simd_cf_prod(a01, a10)); +} + +/* Generic SIMD implementation for Zero Forcing (ZF) solver */ +static inline void srslte_mat_2x2_zf_csi_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + simd_f_t *csi0, + simd_f_t *csi1, + float norm) { + simd_cf_t det = srslte_mat_2x2_det_simd(h00, h01, h10, h11); + simd_cf_t detrec = srslte_simd_cf_mul(srslte_simd_cf_rcp(det), srslte_simd_f_set1(norm)); + + *x0 = srslte_simd_cf_prod(srslte_simd_cf_sub(srslte_simd_cf_prod(h11, y0), srslte_simd_cf_prod(h01, y1)), detrec); + *x1 = srslte_simd_cf_prod(srslte_simd_cf_sub(srslte_simd_cf_prod(h00, y1), srslte_simd_cf_prod(h10, y0)), detrec); + + *csi0 = srslte_simd_f_set1(1.0f); + *csi1 = srslte_simd_f_set1(1.0f); +} + +static inline void srslte_mat_2x2_zf_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + float norm) { + simd_f_t csi1, csi2; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, x0, x1, &csi1, &csi2, norm); +} + +/* Generic SIMD implementation for Minimum Mean Squared Error (MMSE) solver */ +static inline void srslte_mat_2x2_mmse_csi_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + simd_f_t *csi0, + simd_f_t *csi1, + float noise_estimate, + float norm) { + simd_cf_t _noise_estimate; + simd_f_t _norm = srslte_simd_f_set1(norm); + + _noise_estimate.re = srslte_simd_f_set1(noise_estimate); + _noise_estimate.im = srslte_simd_f_zero(); + + /* 1. A = H' x H + No*/ + simd_cf_t a00 = + srslte_simd_cf_add(srslte_simd_cf_add(srslte_simd_cf_conjprod(h00, h00), srslte_simd_cf_conjprod(h10, h10)), + _noise_estimate); + simd_cf_t a01 = srslte_simd_cf_add(srslte_simd_cf_conjprod(h01, h00), srslte_simd_cf_conjprod(h11, h10)); + simd_cf_t a10 = srslte_simd_cf_add(srslte_simd_cf_conjprod(h00, h01), srslte_simd_cf_conjprod(h10, h11)); + simd_cf_t a11 = + srslte_simd_cf_add(srslte_simd_cf_add(srslte_simd_cf_conjprod(h01, h01), srslte_simd_cf_conjprod(h11, h11)), + _noise_estimate); + simd_cf_t a_det_rcp = srslte_simd_cf_rcp(srslte_mat_2x2_det_simd(a00, a01, a10, a11)); + + /* 2. B = inv(H' x H + No) = inv(A) */ + simd_cf_t _norm2 = srslte_simd_cf_mul(a_det_rcp, _norm); + simd_cf_t b00 = srslte_simd_cf_prod(a11, _norm2); + simd_cf_t b01 = srslte_simd_cf_prod(srslte_simd_cf_neg(a01), _norm2); + simd_cf_t b10 = srslte_simd_cf_prod(srslte_simd_cf_neg(a10), _norm2); + simd_cf_t b11 = srslte_simd_cf_prod(a00, _norm2); + + + /* 3. W = inv(H' x H + No) x H' = B x H' */ + simd_cf_t w00 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b00, h00), srslte_simd_cf_conjprod(b01, h01)); + simd_cf_t w01 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b00, h10), srslte_simd_cf_conjprod(b01, h11)); + simd_cf_t w10 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b10, h00), srslte_simd_cf_conjprod(b11, h01)); + simd_cf_t w11 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b10, h10), srslte_simd_cf_conjprod(b11, h11)); + + /* 4. X = W x Y */ + *x0 = srslte_simd_cf_add(srslte_simd_cf_prod(y0, w00), srslte_simd_cf_prod(y1, w01)); + *x1 = srslte_simd_cf_add(srslte_simd_cf_prod(y0, w10), srslte_simd_cf_prod(y1, w11)); + + /* 5. Extract CSI */ + *csi0 = srslte_simd_f_rcp(srslte_simd_cf_re(b00)); + *csi1 = srslte_simd_f_rcp(srslte_simd_cf_re(b11)); +} + +static inline void srslte_mat_2x2_mmse_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + float noise_estimate, + float norm) { + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, x0, x1, &csi0, &csi1, noise_estimate, norm); +} + +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ +#endif /* SRSLTE_MAT_H */ diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index f6d7a0a44..e9cb4da30 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -197,7 +197,7 @@ static inline simd_f_t srslte_simd_f_loadu(const float *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_ps(ptr); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 return _mm256_loadu_ps(ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -233,7 +233,7 @@ static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) { #ifdef LV_HAVE_AVX512 _mm512_storeu_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 _mm256_storeu_ps(ptr, simdreg); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -360,7 +360,7 @@ static inline simd_f_t srslte_simd_f_add(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX2 return _mm256_add_ps(a, b); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_add_ps(a, b); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON @@ -376,9 +376,9 @@ static inline simd_f_t srslte_simd_f_zero (void) { return _mm512_setzero_ps(); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return _mm256_setzero_ps(); + return _mm256_setzero_ps(); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_setzero_ps(); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON @@ -401,7 +401,7 @@ static inline simd_f_t srslte_simd_f_swap(simd_f_t a) { #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON return vcombine_f32(vrev64_f32(vget_low_f32(a)), vrev64_f32(vget_high_f32(a))); -#endif /* HAVE_NEON */ +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -443,7 +443,7 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #ifdef LV_HAVE_AVX512 return _mm512_sqrt_ps(a); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 return _mm256_sqrt_ps(a); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -458,7 +458,43 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { float32x4_t zeros = vmovq_n_f32(0); /* Zero vector */ uint32x4_t mask = vceqq_f32(a, zeros); /* Zero vector mask */ return vbslq_f32(mask, zeros, result); /* Force zero results and return */ -#endif /* HAVE_NEON */ +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_neg(simd_f_t a) { +#ifdef LV_HAVE_AVX512 + return _mm512_xor_ps(_mm512_set1_ps(-0.0f), a); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_xor_ps(_mm256_set1_ps(-0.0f), a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_xor_ps(_mm_set1_ps(-0.0f), a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vnegq_f32(a); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_neg_mask(simd_f_t a, simd_f_t mask) { +#ifdef LV_HAVE_AVX512 + return _mm512_xor_ps(mask, a); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_xor_ps(mask, a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_xor_ps(mask, a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return (float32x4_t) veorq_s32((int32x4_t) a, (int32x4_t) mask); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -470,12 +506,11 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #if SRSLTE_SIMD_CF_SIZE #ifdef HAVE_NEON - typedef float32x4x2_t simd_cf_t; +typedef float32x4x2_t simd_cf_t; #else typedef struct { simd_f_t re; simd_f_t im; - } simd_cf_t; #endif @@ -667,8 +702,8 @@ static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg) _mm512_store_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_store_ps((float *) re, simdreg.re); - _mm256_store_ps((float *) im, simdreg.im); + _mm256_store_ps(re, simdreg.re); + _mm256_store_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_SSE _mm_store_ps((float *) re, simdreg.re); @@ -689,8 +724,8 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg _mm512_storeu_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_storeu_ps((float *) re, simdreg.re); - _mm256_storeu_ps((float *) im, simdreg.im); + _mm256_storeu_ps(re, simdreg.re); + _mm256_storeu_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_SSE _mm_storeu_ps((float *) re, simdreg.re); @@ -833,8 +868,32 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { return ret; } +static inline simd_cf_t srslte_simd_cf_sub (simd_cf_t a, simd_cf_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_sub_ps(a.re, b.re); + ret.im = _mm512_sub_ps(a.im, b.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_sub_ps(a.re, b.re); + ret.im = _mm256_sub_ps(a.im, b.im); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + ret.re = _mm_sub_ps(a.re, b.re); + ret.im = _mm_sub_ps(a.im, b.im); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vsubq_f32(a.val[0],b.val[0]); + ret.val[1] = vsubq_f32(a.val[1],b.val[1]); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { - simd_cf_t ret; + simd_cf_t ret; #ifdef LV_HAVE_AVX512 ret.re = _mm512_mul_ps(a.re, b); ret.im = _mm512_mul_ps(a.im, b); @@ -855,7 +914,7 @@ static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ - return ret; + return ret; } static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { @@ -902,6 +961,59 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { return ret; } +static inline simd_cf_t srslte_simd_cf_neg (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg(a.val[0]); + ret.val[1] = srslte_simd_f_neg(a.val[1]); +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg(a.re); + ret.im = srslte_simd_f_neg(a.im); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_neg_mask (simd_cf_t a, simd_f_t mask) { + simd_cf_t ret; +#ifndef LV_HAVE_AVX512 +#ifdef LV_HAVE_AVX2 + mask = _mm256_permutevar8x32_ps(mask, _mm256_setr_epi32(0,4,1,5,2,6,3,7)); +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg_mask(a.val[0], mask); + ret.val[1] = srslte_simd_f_neg_mask(a.val[1], mask); +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg_mask(a.re, mask); + ret.im = srslte_simd_f_neg_mask(a.im, mask); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_conj (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = a.val[0]; + ret.val[1] = srslte_simd_f_neg(a.val[1]); +#else /* LV_HAVE_NEON */ + ret.re = a.re; + ret.im = srslte_simd_f_neg(a.im); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_mulj (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg(a.val[1]); + ret.val[1] = a.val[0]; +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg(a.im); + ret.im = a.re; +#endif /* LV_HAVE_NEON */ + return ret; +} + static inline simd_cf_t srslte_simd_cf_zero (void) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 @@ -1057,7 +1169,7 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s int* sel = (int*) &selector; int* c_ptr = (int*) &ret; for(int i = 0;i<4;i++) - { + { if(sel[i] == -1){ c_ptr[i] = b_ptr[i]; }else{ @@ -1115,7 +1227,7 @@ static inline simd_s_t srslte_simd_s_loadu(const int16_t *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_si512(ptr); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE diff --git a/lib/src/phy/mimo/layermap.c b/lib/src/phy/mimo/layermap.c index a5bfc8b92..6de30fca7 100644 --- a/lib/src/phy/mimo/layermap.c +++ b/lib/src/phy/mimo/layermap.c @@ -54,7 +54,7 @@ int srslte_layermap_multiplex(cf_t *d[SRSLTE_MAX_CODEWORDS], cf_t *x[SRSLTE_MAX_ int nof_symbols[SRSLTE_MAX_CODEWORDS]) { if (nof_cw == nof_layers) { for (int i = 0; i < nof_cw; i++) { - srs_vec_cf_cpy(x[i], d[i], (uint32_t) nof_symbols[0]); + srs_vec_cf_cpy(d[i], x[i], (uint32_t) nof_symbols[0]); } return nof_symbols[0]; } else if (nof_cw == 1) { diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index f8faeda75..2f987c898 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -283,13 +283,13 @@ int srslte_predecoding_single_csi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ for (; i < nof_symbols; i++) { cf_t r = 0; float hh = 0; - float _scaling = 1.0f / scaling; + float norm = 1.0f / scaling; for (int p = 0; p < nof_rxant; p++) { r += y[p][i] * conj(h[p][i]); hh += (__real__ h[p][i] * __real__ h[p][i]) + (__imag__ h[p][i] * __imag__ h[p][i]); } csi[i] = hh + noise_estimate; - x[i] = r * _scaling / csi[i]; + x[i] = r * norm / csi[i]; } return nof_symbols; } @@ -327,10 +327,10 @@ int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, float *csi, int nof_s } /* ZF/MMSE SISO equalizer x=y(h'h+no)^(-1)h' (ZF if n0=0.0)*/ -int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi, +int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { - if (csi) { - return srslte_predecoding_single_csi(y, h, x, csi, nof_rxant, nof_symbols, scaling, noise_estimate); + if (csi && csi[0]) { + return srslte_predecoding_single_csi(y, h, x, csi[0], nof_rxant, nof_symbols, scaling, noise_estimate); } #ifdef LV_HAVE_AVX @@ -566,18 +566,123 @@ int srslte_predecoding_diversity(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[S #endif } +int srslte_predecoding_diversity_csi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, int nof_ports, int nof_symbols, float scaling) { + int i; + if (nof_ports == 2) { + cf_t h00, h01, h10, h11, r0, r1; + + for (i = 0; i < nof_symbols / 2; i++) { + float hh = 0; + cf_t x0 = 0; + cf_t x1 = 0; + for (int p=0;p 32 && nof_ports == 2) { - return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); + if (csi && csi[0]) { + return srslte_predecoding_diversity_csi(y, h, x, csi, nof_rxant, nof_ports, nof_symbols, scaling); } else { +#ifdef LV_HAVE_SSE + if (nof_symbols > 32 && nof_ports == 2) { + return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); + } else { + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); + } +#else return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); +#endif } -#else - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); -#endif } int srslte_precoding_mimo_2x2_gen(cf_t W[2][2], cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], @@ -614,102 +719,164 @@ int srslte_precoding_mimo_2x2_gen(cf_t W[2][2], cf_t *y[SRSLTE_MAX_PORTS], cf_t return SRSLTE_SUCCESS; } -// AVX implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_AVX - -int srslte_predecoding_ccd_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, - float scaling) { +static int srslte_predecoding_ccd_2x2_zf_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_symbols, + float scaling) { uint32_t i = 0; + float norm = 2.0f / scaling; + +#if SRSLTE_SIMD_CF_SIZE != 0 + +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, + +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f + -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f}; +#endif - __m256 mask0 = _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f); - __m256 mask1 = _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f); + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); - for (i = 0; i < nof_symbols - 3; i += 4) { + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { /* Load channel */ - __m256 h00i = _mm256_load_ps((float *) &h[0][0][i]); - __m256 h01i = _mm256_load_ps((float *) &h[0][1][i]); - __m256 h10i = _mm256_load_ps((float *) &h[1][0][i]); - __m256 h11i = _mm256_load_ps((float *) &h[1][1][i]); + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); /* Apply precoding */ - __m256 h00 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, mask0)); - __m256 h10 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, mask0)); - __m256 h01 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, mask1)); - __m256 h11 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, mask1)); + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m256 x0, x1; + simd_cf_t x0, x1; + simd_f_t csi0, csi1; - srslte_mat_2x2_zf_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, 2.0f / scaling); + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ - return nof_symbols; -} -#endif /* LV_HAVE_AVX */ + cf_t h00, h01, h10, h11, det; + for (; i < nof_symbols; i++) { -// SSE implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_SSE + // Even precoder + h00 = +h[0][0][i] + h[1][0][i]; + h10 = +h[0][1][i] + h[1][1][i]; + h01 = +h[0][0][i] - h[1][0][i]; + h11 = +h[0][1][i] - h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); + + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; + + csi[0][i] = 1.0f; + csi[1][i] = 1.0f; + + i++; + + // Odd precoder + h00 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] - h[1][1][i]; + h01 = h[0][0][i] + h[1][0][i]; + h11 = h[0][1][i] + h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); + + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; -int srslte_predecoding_ccd_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, - float scaling) { + csi[0][i] = 1.0f; + csi[1][i] = 1.0f; + } + return SRSLTE_SUCCESS; +} + +static int srslte_predecoding_ccd_2x2_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int nof_symbols, + float scaling) { uint32_t i = 0; + float norm = 2.0f / scaling; + +#if SRSLTE_SIMD_CF_SIZE != 0 + +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, + +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f + -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f}; +#endif + + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); - for (i = 0; i < nof_symbols - 1; i += 2) { + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { /* Load channel */ - __m128 h00i = _mm_load_ps((float *) &h[0][0][i]); - __m128 h01i = _mm_load_ps((float *) &h[0][1][i]); - __m128 h10i = _mm_load_ps((float *) &h[1][0][i]); - __m128 h11i = _mm_load_ps((float *) &h[1][1][i]); + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); /* Apply precoding */ - __m128 h00 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h10 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h01 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - __m128 h11 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m128 x0, x1; + simd_cf_t x0, x1; - srslte_mat_2x2_zf_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, 2.0f / scaling); + srslte_mat_2x2_zf_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ - return nof_symbols; -} -#endif - -// Generic implementation of ZF 2x2 CCD equalizer -int srslte_predecoding_ccd_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - int nof_symbols, - float scaling) { - cf_t h00, h01, h10, h11; - - for (int i = 0; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11, det; + for (; i < nof_symbols; i++) { // Even precoder h00 = +h[0][0][i] + h[1][0][i]; h10 = +h[0][1][i] + h[1][1][i]; h01 = +h[0][0][i] - h[1][0][i]; h11 = +h[0][1][i] - h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); - srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], 2.0f / scaling); + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; i++; @@ -718,30 +885,35 @@ int srslte_predecoding_ccd_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], h10 = h[0][1][i] - h[1][1][i]; h01 = h[0][0][i] + h[1][0][i]; h11 = h[0][1][i] + h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); - srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], 2.0f / scaling); + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; } return SRSLTE_SUCCESS; } -int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int nof_symbols, float scaling) -{ +static int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int nof_symbols, + float scaling) { if (nof_ports == 2 && nof_rxant == 2) { if (nof_layers == 2) { -#ifdef LV_HAVE_AVX - return srslte_predecoding_ccd_2x2_zf_avx(y, h, x, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_ccd_2x2_zf_sse(y, h, x, nof_symbols, scaling); -#else - return srslte_predecoding_ccd_2x2_zf_gen(y, h, x, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_ccd_2x2_zf_csi(y, h, x, csi, nof_symbols, scaling); + } else { + return srslte_predecoding_ccd_2x2_zf(y, h, x, nof_symbols, scaling); + } } else { DEBUG("Error predecoding CCD: Invalid number of layers %d\n", nof_layers); - return -1; - } + return -1; + } } else if (nof_ports == 4) { DEBUG("Error predecoding CCD: Only 2 ports supported\n"); } else { @@ -750,86 +922,155 @@ int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORT return SRSLTE_ERROR; } -// AVX implementation of MMSE 2x2 CCD equalizer -#ifdef LV_HAVE_AVX +static int srslte_predecoding_ccd_2x2_mmse_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_symbols, float scaling, float noise_estimate) { + int i = 0; + float norm = 2.0f / scaling; + +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; +#endif -int srslte_predecoding_ccd_2x2_mmse_avx(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, float scaling, float noise_estimate) { - uint32_t i = 0; + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); - for (i = 0; i < nof_symbols - 3; i += 4) { + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { /* Load channel */ - __m256 h00i = _mm256_load_ps((float *) &h[0][0][i]); - __m256 h01i = _mm256_load_ps((float *) &h[0][1][i]); - __m256 h10i = _mm256_load_ps((float *) &h[1][0][i]); - __m256 h11i = _mm256_load_ps((float *) &h[1][1][i]); + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); /* Apply precoding */ - __m256 h00 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f))); - __m256 h10 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f))); - __m256 h01 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f))); - __m256 h11 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f))); + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m256 x0, x1; + simd_cf_t x0, x1; + simd_f_t csi0, csi1; - srslte_mat_2x2_mmse_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, 2.0f / scaling); + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ - return nof_symbols; + cf_t h00, h01, h10, h11; + for (; i < nof_symbols; i++) { + + // Even precoder + h00 = +h[0][0][i] + h[1][0][i]; + h10 = +h[0][1][i] + h[1][1][i]; + h01 = +h[0][0][i] - h[1][0][i]; + h11 = +h[0][1][i] - h[1][1][i]; + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); + i++; + + // Odd precoder + h00 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] - h[1][1][i]; + h01 = h[0][0][i] + h[1][0][i]; + h11 = h[0][1][i] + h[1][1][i]; + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); + } + return SRSLTE_SUCCESS; } -#endif /* LV_HAVE_AVX */ -// SSE implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_SSE +static int srslte_predecoding_ccd_2x2_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int nof_symbols, float scaling, float noise_estimate) { + int i = 0; + float norm = 2.0f / scaling; + +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; +#endif -int srslte_predecoding_ccd_2x2_mmse_sse(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, float scaling, float noise_estimate) { - uint32_t i = 0; + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); - for (i = 0; i < nof_symbols - 1; i += 2) { + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { /* Load channel */ - __m128 h00i = _mm_load_ps((float *) &h[0][0][i]); - __m128 h01i = _mm_load_ps((float *) &h[0][1][i]); - __m128 h10i = _mm_load_ps((float *) &h[1][0][i]); - __m128 h11i = _mm_load_ps((float *) &h[1][1][i]); + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); /* Apply precoding */ - __m128 h00 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h10 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h01 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - __m128 h11 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m128 x0, x1; + simd_cf_t x0, x1; + srslte_mat_2x2_mmse_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); - srslte_mat_2x2_mmse_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, 2.0f / scaling); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ - return nof_symbols; -} -#endif /* LV_HAVE_SSE */ - -// Generic implementation of ZF 2x2 CCD equalizer -int srslte_predecoding_ccd_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_symbols, float scaling, float noise_estimate) { cf_t h00, h01, h10, h11; - - for (int i = 0; i < nof_symbols; i++) { + for (i = 0; i < nof_symbols; i++) { // Even precoder h00 = +h[0][0][i] + h[1][0][i]; @@ -850,21 +1091,23 @@ int srslte_predecoding_ccd_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLT return SRSLTE_SUCCESS; } - -int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int nof_symbols, float scaling, float noise_estimate) -{ +int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int nof_symbols, + float scaling, + float noise_estimate) { if (nof_ports == 2 && nof_rxant == 2) { if (nof_layers == 2) { -#ifdef LV_HAVE_AVX - return srslte_predecoding_ccd_2x2_mmse_avx(y, h, x, nof_symbols, scaling, noise_estimate); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_ccd_2x2_mmse_sse(y, h, x, nof_symbols, scaling, noise_estimate); -#else - return srslte_predecoding_ccd_2x2_mmse_gen(y, h, x, nof_symbols, scaling, noise_estimate); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) + return srslte_predecoding_ccd_2x2_mmse_csi(y, h, x, csi, nof_symbols, scaling, noise_estimate); + else { + return srslte_predecoding_ccd_2x2_mmse(y, h, x, nof_symbols, scaling, noise_estimate); + } } else { DEBUG("Error predecoding CCD: Invalid number of layers %d\n", nof_layers); return -1; @@ -1468,7 +1711,7 @@ void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder) { /* 36.211 v10.3.0 Section 6.3.4 */ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], float *csi, int nof_rxant, int nof_ports, int nof_layers, + cf_t *x[SRSLTE_MAX_LAYERS], float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols, srslte_mimo_type_t type, float scaling, float noise_estimate) { @@ -1488,10 +1731,10 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] if (nof_layers >= 2 && nof_layers <= 4) { switch (mimo_decoder) { case SRSLTE_MIMO_DECODER_ZF: - return srslte_predecoding_ccd_zf(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling); + return srslte_predecoding_ccd_zf(y, h, x, csi, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling); break; case SRSLTE_MIMO_DECODER_MMSE: - return srslte_predecoding_ccd_mmse(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling, noise_estimate); + return srslte_predecoding_ccd_mmse(y, h, x, csi, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling, noise_estimate); break; } } else { @@ -1510,7 +1753,7 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: if (nof_ports == nof_layers) { - return srslte_predecoding_diversity_multi(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); + return srslte_predecoding_diversity_multi(y, h, x, csi, nof_rxant, nof_ports, nof_symbols, scaling); } else { fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); diff --git a/lib/src/phy/phch/pcfich.c b/lib/src/phy/phch/pcfich.c index 6b00e768a..c6f1fe127 100644 --- a/lib/src/phy/phch/pcfich.c +++ b/lib/src/phy/phch/pcfich.c @@ -221,7 +221,7 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P /* no need for layer demapping */ srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, NULL, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); + srslte_predecoding_diversity_multi(q_symbols, q_ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); } diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 83f681f8f..1c40333e8 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -492,7 +492,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA /* no need for layer demapping */ srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2); } else { - srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); + srslte_predecoding_diversity_multi(q->symbols, q->ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports); } diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index c59956a71..6e7a3b33c 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -402,7 +402,7 @@ int srslte_pdsch_enable_csi(srslte_pdsch_t *q, bool enable) { if (enable) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (!q->csi[i]) { - q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re); + q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re * 2); if (!q->csi[i]) { return SRSLTE_ERROR; } @@ -757,7 +757,7 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } // Pre-decoder - if (srslte_predecoding_type(q->symbols, q->ce, x, q->csi[0], q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, + if (srslte_predecoding_type(q->symbols, q->ce, x, q->csi, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) { DEBUG("Error predecoding\n"); return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/phich.c b/lib/src/phy/phch/phich.c index 15aa4db88..21bfb040b 100644 --- a/lib/src/phy/phch/phich.c +++ b/lib/src/phy/phch/phich.c @@ -241,7 +241,7 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS], /* no need for layer demapping */ srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, NULL, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); + srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports); } DEBUG("Recv!!: \n"); diff --git a/lib/src/phy/utils/mat.c b/lib/src/phy/utils/mat.c index bbfc38135..55b1dc177 100644 --- a/lib/src/phy/utils/mat.c +++ b/lib/src/phy/utils/mat.c @@ -60,8 +60,8 @@ inline void srslte_mat_2x2_zf_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h10 } /* Generic implementation for Minimum Mean Squared Error (MMSE) solver */ -inline void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h10, cf_t h11, - cf_t *x0, cf_t *x1, float noise_estimate, float norm) { +inline void srslte_mat_2x2_mmse_csi_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h10, cf_t h11, + cf_t *x0, cf_t *x1, float *csi0, float *csi1, float noise_estimate, float norm) { /* Create conjugated matrix */ cf_t _h00 = conjf(h00); cf_t _h01 = conjf(h01); @@ -73,14 +73,14 @@ inline void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h cf_t a01 = _h00 * h01 + _h10 * h11; cf_t a10 = _h01 * h00 + _h11 * h10; cf_t a11 = _h01 * h01 + _h11 * h11 + noise_estimate; + cf_t a_det_rcp = srslte_mat_cf_recip_gen(srslte_mat_2x2_det_gen(a00, a01, a10, a11)); /* 2. B = inv(H' x H + No) = inv(A) */ - cf_t b00 = a11; - cf_t b01 = -a01; - cf_t b10 = -a10; - cf_t b11 = a00; - cf_t _norm = norm * srslte_mat_cf_recip_gen(srslte_mat_2x2_det_gen(a00, a01, a10, a11)); - + cf_t _norm = norm * a_det_rcp; + cf_t b00 = a11 * _norm; + cf_t b01 = -a01 * _norm; + cf_t b10 = -a10 * _norm; + cf_t b11 = a00 * _norm; /* 3. W = inv(H' x H + No) x H' = B x H' */ cf_t w00 = b00 * _h00 + b01 * _h01; @@ -89,8 +89,19 @@ inline void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h cf_t w11 = b10 * _h10 + b11 * _h11; /* 4. X = W x Y */ - *x0 = (y0 * w00 + y1 * w01) * _norm; - *x1 = (y0 * w10 + y1 * w11) * _norm; + *x0 = (y0 * w00 + y1 * w01); + *x1 = (y0 * w10 + y1 * w11); + + /* 5. Set CSI */ + *csi0 = 1.0f / crealf(b00); + *csi1 = 1.0f / crealf(b11); +} + +/* Generic implementation for Minimum Mean Squared Error (MMSE) solver */ +void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, cf_t h00, cf_t h01, cf_t h10, cf_t h11, + cf_t *x0, cf_t *x1, float noise_estimate, float norm) { + float csi0, csi1; + srslte_mat_2x2_mmse_csi_gen(y0, y1, h00, h01, h10, h11, x0, x1, &csi0, &csi1, noise_estimate, norm); } inline float srslte_mat_2x2_cn(cf_t h00, cf_t h01, cf_t h10, cf_t h11) { diff --git a/lib/src/phy/utils/test/mat_test.c b/lib/src/phy/utils/test/mat_test.c index 0bfb482a9..6ee1c451a 100644 --- a/lib/src/phy/utils/test/mat_test.c +++ b/lib/src/phy/utils/test/mat_test.c @@ -32,8 +32,8 @@ #include #include "srslte/phy/utils/mat.h" -#include "srslte/phy/utils/simd.h" #include "srslte/phy/utils/vector.h" +#include "srslte/phy/utils/vector_simd.h" bool zf_solver = false; @@ -378,6 +378,98 @@ bool test_mmse_solver_avx(void) { #endif /* LV_HAVE_AVX */ +#if SRSLTE_SIMD_CF_SIZE != 0 + +bool test_zf_solver_simd(void) { + cf_t cf_error0, cf_error1; + float error = 0.0f; + + cf_t x0_gold_1 = RANDOM_CF(); + cf_t x1_gold_1 = RANDOM_CF(); + cf_t h00_1 = RANDOM_CF(); + cf_t h01_1 = RANDOM_CF(); + cf_t h10_1 = RANDOM_CF(); + cf_t h11_1 = (1 - h01_1 * h10_1) / h00_1; + cf_t y0_1 = x0_gold_1 * h00_1 + x1_gold_1 * h01_1; + cf_t y1_1 = x0_gold_1 * h10_1 + x1_gold_1 * h11_1; + + simd_cf_t _y0 = srslte_simd_cf_set1(y0_1); + simd_cf_t _y1 = srslte_simd_cf_set1(y1_1); + + simd_cf_t _h00 = srslte_simd_cf_set1(h00_1); + simd_cf_t _h01 = srslte_simd_cf_set1(h01_1); + simd_cf_t _h10 = srslte_simd_cf_set1(h10_1); + simd_cf_t _h11 = srslte_simd_cf_set1(h11_1); + + simd_cf_t _x0, _x1; + + srslte_mat_2x2_zf_simd(_y0, _y1, _h00, _h01, _h10, _h11, &_x0, &_x1, 1.0f); + + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x0[SRSLTE_SIMD_CF_SIZE]; + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x1[SRSLTE_SIMD_CF_SIZE]; + + srslte_simd_cfi_store(x0, _x0); + srslte_simd_cfi_store(x1, _x1); + + cf_error0 = x0[1] - x0_gold_1; + cf_error1 = x1[1] - x1_gold_1; + error += crealf(cf_error0) * crealf(cf_error0) + cimagf(cf_error0) * cimagf(cf_error0) + + crealf(cf_error1) * crealf(cf_error1) + cimagf(cf_error1) * cimagf(cf_error1); + + return (error < 1e-3); +} + +bool test_mmse_solver_simd(void) { + cf_t cf_error0, cf_error1; + float error = 0.0f; + + cf_t x0_gold[SRSLTE_SIMD_CF_SIZE]; + cf_t x1_gold[SRSLTE_SIMD_CF_SIZE]; + cf_t h00[SRSLTE_SIMD_CF_SIZE]; + cf_t h01[SRSLTE_SIMD_CF_SIZE]; + cf_t h10[SRSLTE_SIMD_CF_SIZE]; + cf_t h11[SRSLTE_SIMD_CF_SIZE]; + cf_t y0[SRSLTE_SIMD_CF_SIZE]; + cf_t y1[SRSLTE_SIMD_CF_SIZE]; + for (int i = 0; i < SRSLTE_SIMD_CF_SIZE; i++) { + x0_gold[i] = RANDOM_CF(); + x1_gold[i] = RANDOM_CF(); + h00[i] = RANDOM_CF(); + h01[i] = RANDOM_CF(); + h10[i] = RANDOM_CF(); + h11[i] = (1 - h01[i] * h10[i]) / h00[i]; + y0[i] = x0_gold[i] * h00[i]+ x1_gold[i] * h01[i]; + y1[i] = x0_gold[i] * h10[i] + x1_gold[i] * h11[i]; + } + + simd_cf_t _y0 = srslte_simd_cfi_loadu(y0); + simd_cf_t _y1 = srslte_simd_cfi_loadu(y1); + + simd_cf_t _h00 = srslte_simd_cfi_loadu(h00); + simd_cf_t _h01 = srslte_simd_cfi_loadu(h01); + simd_cf_t _h10 = srslte_simd_cfi_loadu(h10); + simd_cf_t _h11 = srslte_simd_cfi_loadu(h11); + + simd_cf_t _x0, _x1; + + srslte_mat_2x2_mmse_simd(_y0, _y1, _h00, _h01, _h10, _h11, &_x0, &_x1, 0.0f, 1.0f); + + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x0[SRSLTE_SIMD_CF_SIZE]; + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x1[SRSLTE_SIMD_CF_SIZE]; + + srslte_simd_cfi_store(x0, _x0); + srslte_simd_cfi_store(x1, _x1); + + cf_error0 = x0[1] - x0_gold[1]; + cf_error1 = x1[1] - x1_gold[1]; + error += crealf(cf_error0) * crealf(cf_error0) + cimagf(cf_error0) * cimagf(cf_error0) + + crealf(cf_error1) * crealf(cf_error1) + cimagf(cf_error1) * cimagf(cf_error1); + + return (error < 1e-3); +} + +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ + bool test_vec_dot_prod_ccc(void) { __attribute__((aligned(256))) cf_t a[14]; __attribute__((aligned(256))) cf_t b[14]; @@ -413,6 +505,10 @@ int main(int argc, char **argv) { #ifdef LV_HAVE_AVX RUN_TEST(test_zf_solver_avx); #endif /* LV_HAVE_AVX */ + +#if SRSLTE_SIMD_CF_SIZE != 0 + RUN_TEST(test_zf_solver_simd); +#endif /* SRSLTE_SIMD_CF_SIZE != 0*/ } if (mmse_solver) { @@ -426,6 +522,10 @@ int main(int argc, char **argv) { #ifdef LV_HAVE_AVX RUN_TEST(test_mmse_solver_avx); #endif /* LV_HAVE_AVX */ + +#if SRSLTE_SIMD_CF_SIZE != 0 + RUN_TEST(test_mmse_solver_simd); +#endif /* SRSLTE_SIMD_CF_SIZE != 0*/ } RUN_TEST(test_vec_dot_prod_ccc); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 56010d2c4..d3d836b21 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -427,8 +427,8 @@ void srslte_vec_quant_sus(const int16_t *in, uint16_t *out, const float gain, co } } -void srs_vec_cf_cpy(const cf_t *dst, cf_t *src, int len) { - srslte_vec_cp_simd(dst, src, len); +void srs_vec_cf_cpy(const cf_t *src, cf_t *dst, int len) { + srslte_vec_cp_simd(src, dst, len); } void srslte_vec_interleave(const cf_t *x, const cf_t *y, cf_t *z, const int len) { From bad12918431234535c5ae485c2e9f307ec412d1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 17 Apr 2018 09:35:54 +0200 Subject: [PATCH 24/52] Corrected ZF SIMD predecoder --- lib/src/phy/mimo/precoding.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index 2f987c898..db0938696 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -729,18 +729,17 @@ static int srslte_predecoding_ccd_2x2_zf_csi(cf_t *y[SRSLTE_MAX_PORTS], float norm = 2.0f / scaling; #if SRSLTE_SIMD_CF_SIZE != 0 - #if SRSLTE_SIMD_CF_SIZE == 16 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, - +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f - -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; #elif SRSLTE_SIMD_CF_SIZE == 8 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; #elif SRSLTE_SIMD_CF_SIZE == 4 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; #endif simd_f_t mask1 = srslte_simd_f_loadu(_mask1); @@ -821,18 +820,17 @@ static int srslte_predecoding_ccd_2x2_zf(cf_t *y[SRSLTE_MAX_PORTS], float norm = 2.0f / scaling; #if SRSLTE_SIMD_CF_SIZE != 0 - #if SRSLTE_SIMD_CF_SIZE == 16 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, - +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f - -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; #elif SRSLTE_SIMD_CF_SIZE == 8 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; #elif SRSLTE_SIMD_CF_SIZE == 4 - float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, +0.0f, -0.0f, -0.0f}; - float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, -0.0f, +0.0f, +0.0f}; + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; #endif simd_f_t mask1 = srslte_simd_f_loadu(_mask1); @@ -1070,7 +1068,7 @@ static int srslte_predecoding_ccd_2x2_mmse(cf_t *y[SRSLTE_MAX_PORTS], #endif /* SRSLTE_SIMD_CF_SIZE != 0 */ cf_t h00, h01, h10, h11; - for (i = 0; i < nof_symbols; i++) { + for (; i < nof_symbols; i++) { // Even precoder h00 = +h[0][0][i] + h[1][0][i]; From 7146819fcd6eedff800a1993dcbfea54ff06da4d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Apr 2018 11:17:33 +0200 Subject: [PATCH 25/52] Added CSI Predecoding for TM4 with SIMD Support --- lib/src/phy/mimo/precoding.c | 710 +++++++++++++++++++---------------- 1 file changed, 385 insertions(+), 325 deletions(-) diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index db0938696..dbf34ab90 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -1118,14 +1118,17 @@ int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], return SRSLTE_ERROR; } -#ifdef LV_HAVE_AVX - -// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; +static int srslte_predecoding_multiplex_2x2_zf_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi, + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = 1.0f; + int i = 0; - switch(codebook_idx) { + switch (codebook_idx) { case 0: norm = (float) M_SQRT2 / scaling; break; @@ -1138,62 +1141,103 @@ int srslte_predecoding_multiplex_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[S return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols - 3; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); - __m256 h00, h01, h10, h11; + simd_cf_t h00, h01, h10, h11; switch (codebook_idx) { case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; break; case 1: - h00 = _mm256_add_ps(_h00, _h10); - h01 = _mm256_sub_ps(_h00, _h10); - h10 = _mm256_add_ps(_h01, _h11); - h11 = _mm256_sub_ps(_h01, _h11); + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); break; case 2: - h00 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h01 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h10 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - h11 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); break; default: - DEBUG("Wrong codebook_idx=%d\n", codebook_idx); + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); - - __m256 x0, x1; + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - srslte_mat_2x2_zf_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + srslte_simd_f_store(&csi[i], csi0); + srslte_simd_f_store(&csi[i], csi1); } +#endif /* SRSLTE_SIMD_CF_SIZE */ - return SRSLTE_SUCCESS; -} + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; -#endif /* LV_HAVE_AVX */ + switch (codebook_idx) { + case 0: + h00 = h[0][0][i]; + h01 = h[1][0][i]; + h10 = h[0][1][i]; + h11 = h[1][1][i]; + break; + case 1: + h00 = h[0][0][i] + h[1][0][i]; + h01 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] + h[1][1][i]; + h11 = h[0][1][i] - h[1][1][i]; + break; + case 2: + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } -#ifdef LV_HAVE_SSE + cf_t det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); -// SSE implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; - switch(codebook_idx) { + csi[i] = 1.0f; + csi[i] = 1.0f; + } + return SRSLTE_SUCCESS; +} + +// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer +static int srslte_predecoding_multiplex_2x2_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = 1.0f; + int i = 0; + + switch (codebook_idx) { case 0: norm = (float) M_SQRT2 / scaling; break; @@ -1206,77 +1250,55 @@ int srslte_predecoding_multiplex_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[S return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); - __m128 h00, h01, h10, h11; + simd_cf_t h00, h01, h10, h11; switch (codebook_idx) { case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; break; case 1: - h00 = _mm_add_ps(_h00, _h10); - h01 = _mm_sub_ps(_h00, _h10); - h10 = _mm_add_ps(_h01, _h11); - h11 = _mm_sub_ps(_h01, _h11); + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); break; case 2: - h00 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h01 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h10 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); - h11 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); - - __m128 x0, x1; - - srslte_mat_2x2_zf_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_SSE */ + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); -// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; } +#endif /* SRSLTE_SIMD_CF_SIZE */ - for (int i = 0; i < nof_symbols; i++) { - cf_t h00, h01, h10, h11, det; + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; - switch(codebook_idx) { + switch (codebook_idx) { case 0: h00 = h[0][0][i]; h01 = h[1][0][i]; @@ -1290,34 +1312,34 @@ int srslte_predecoding_multiplex_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[S h11 = h[0][1][i] - h[1][1][i]; break; case 2: - h00 = h[0][0][i] + _Complex_I*h[1][0][i]; - h01 = h[0][0][i] - _Complex_I*h[1][0][i]; - h10 = h[0][1][i] + _Complex_I*h[1][1][i]; - h11 = h[0][1][i] - _Complex_I*h[1][1][i]; + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - det = (h00 * h11 - h01 * h10); - det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); - - x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; - x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; + srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], norm); } return SRSLTE_SUCCESS; } -#ifdef LV_HAVE_AVX - -// AVX implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { - float norm = 1.0; +// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer +static int srslte_predecoding_multiplex_2x2_mmse_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { + float norm = 1.0f; + int i = 0; - switch(codebook_idx) { + switch (codebook_idx) { case 0: norm = (float) M_SQRT2 / scaling; break; @@ -1326,132 +1348,109 @@ int srslte_predecoding_multiplex_2x2_mmse_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h norm = 2.0f / scaling; break; default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + ERROR("Wrong codebook_idx=%d", codebook_idx); return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); - __m256 h00, h01, h10, h11; + simd_cf_t h00, h01, h10, h11; switch (codebook_idx) { case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; break; case 1: - h00 = _mm256_add_ps(_h00, _h10); - h01 = _mm256_sub_ps(_h00, _h10); - h10 = _mm256_add_ps(_h01, _h11); - h11 = _mm256_sub_ps(_h01, _h11); + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); break; case 2: - h00 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h01 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h10 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - h11 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); - - __m256 x0, x1; - - srslte_mat_2x2_mmse_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); - - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_AVX */ - + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); -#ifdef LV_HAVE_SSE + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); -// SSE implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { - float norm; + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); } +#endif /* SRSLTE_SIMD_CF_SIZE */ - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; - __m128 h00, h01, h10, h11; switch (codebook_idx) { case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; + h00 = h[0][0][i]; + h01 = h[1][0][i]; + h10 = h[0][1][i]; + h11 = h[1][1][i]; break; case 1: - h00 = _mm_add_ps(_h00, _h10); - h01 = _mm_sub_ps(_h00, _h10); - h10 = _mm_add_ps(_h01, _h11); - h11 = _mm_sub_ps(_h01, _h11); + h00 = h[0][0][i] + h[1][0][i]; + h01 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] + h[1][1][i]; + h11 = h[0][1][i] - h[1][1][i]; break; case 2: - h00 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h01 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h10 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); - h11 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); - - __m128 x0, x1; - - srslte_mat_2x2_mmse_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); - + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); } - return SRSLTE_SUCCESS; } -#endif /* LV_HAVE_SSE */ -// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { +static int srslte_predecoding_multiplex_2x2_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { float norm = 1.0; + int i = 0; switch(codebook_idx) { case 0: @@ -1466,7 +1465,51 @@ int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols; i++) { +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + simd_cf_t h00, h01, h10, h11; + switch(codebook_idx) { + case 0: + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; + break; + case 1: + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); + break; + case 2: + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i++) { cf_t h00, h01, h10, h11; switch(codebook_idx) { @@ -1498,134 +1541,147 @@ int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h return SRSLTE_SUCCESS; } -#ifdef LV_HAVE_AVX - -// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -int srslte_predecoding_multiplex_2x1_mrc_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - for (int i = 0; i < nof_symbols - 3; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); +// Implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer +static int srslte_predecoding_multiplex_2x1_mrc(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = (float) M_SQRT2 / scaling; + int i = 0; - __m256 h0, h1; - switch (codebook_idx) { - case 0: - h0 = _mm256_add_ps(_h00, _h10); - h1 = _mm256_add_ps(_h01, _h11); - break; - case 1: - h0 = _mm256_sub_ps(_h00, _h10); - h1 = _mm256_sub_ps(_h01, _h11); - break; - case 2: - h0 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h1 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - case 3: - h0 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h1 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } +#if SRSLTE_SIMD_CF_SIZE != 0 + simd_f_t _norm = srslte_simd_f_set1(norm); - __m256 h0_2 = _mm256_mul_ps(h0, h0); - __m256 h1_2 = _mm256_mul_ps(h1, h1); - __m256 hh0 = _mm256_add_ps(_mm256_movehdup_ps(h0_2), _mm256_moveldup_ps(h0_2)); - __m256 hh1 = _mm256_add_ps(_mm256_movehdup_ps(h1_2), _mm256_moveldup_ps(h1_2)); - __m256 hh = _mm256_add_ps(hh0, hh1); - __m256 hhrec = _mm256_rcp_ps(hh); + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t x0 = srslte_simd_cf_set1(0.0f); + simd_f_t hh = srslte_simd_f_set1(0.0f); - hhrec = _mm256_mul_ps(hhrec, _mm256_set1_ps((float) M_SQRT2 / scaling)); - __m256 y0 = _mm256_load_ps((float*)&y[0][i]); - __m256 y1 = _mm256_load_ps((float*)&y[1][i]); + for (int k = 0; k < 2; k++) { + simd_cf_t h0xi = srslte_simd_cfi_load(&h[0][k][i]); + simd_cf_t h1xi = srslte_simd_cfi_load(&h[1][k][i]); + simd_cf_t yx = srslte_simd_cfi_load(&y[k][i]); - __m256 x0 = _mm256_add_ps(_MM256_PROD_PS(_MM256_CONJ_PS(h0), y0), _MM256_PROD_PS(_MM256_CONJ_PS(h1), y1)); - x0 = _mm256_mul_ps(hhrec, x0); + simd_cf_t hx; + switch (codebook_idx) { + case 0: + hx = srslte_simd_cf_add(h0xi, h1xi); + break; + case 1: + hx = srslte_simd_cf_sub(h0xi, h1xi); + break; + case 2: + hx = srslte_simd_cf_add(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + case 3: + hx = srslte_simd_cf_sub(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } - _mm256_store_ps((float*)&x[0][i], x0); + hh = srslte_simd_f_add(srslte_simd_cf_re(srslte_simd_cf_conjprod(hx, hx)), hh); + x0 = srslte_simd_cf_add(srslte_simd_cf_conjprod(yx, hx), x0); + } + hh = srslte_simd_f_mul(_norm, srslte_simd_f_rcp(hh)); + srslte_simd_cfi_store(&x[0][i], srslte_simd_cf_mul(x0, hh)); } +#endif /* SRSLTE_SIMD_CF_SIZE */ - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_AVX */ - - -// SSE implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -#ifdef LV_HAVE_SSE - -int srslte_predecoding_multiplex_2x1_mrc_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); + for (; i < nof_symbols; i += 1) { + cf_t h0, h1; + float hh; - __m128 h0, h1; switch (codebook_idx) { case 0: - h0 = _mm_add_ps(_h00, _h10); - h1 = _mm_add_ps(_h01, _h11); + h0 = h[0][0][i] + h[1][0][i]; + h1 = h[0][1][i] + h[1][1][i]; break; case 1: - h0 = _mm_sub_ps(_h00, _h10); - h1 = _mm_sub_ps(_h01, _h11); + h0 = h[0][0][i] - h[1][0][i]; + h1 = h[0][1][i] - h[1][1][i]; break; case 2: - h0 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h1 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); + h0 = h[0][0][i] + _Complex_I * h[1][0][i]; + h1 = h[0][1][i] + _Complex_I * h[1][1][i]; break; case 3: - h0 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h1 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); + h0 = h[0][0][i] - _Complex_I * h[1][0][i]; + h1 = h[0][1][i] - _Complex_I * h[1][1][i]; break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m128 h0_2 = _mm_mul_ps(h0, h0); - __m128 h1_2 = _mm_mul_ps(h1, h1); - __m128 hh0 = _mm_add_ps(_mm_movehdup_ps(h0_2), _mm_moveldup_ps(h0_2)); - __m128 hh1 = _mm_add_ps(_mm_movehdup_ps(h1_2), _mm_moveldup_ps(h1_2)); - __m128 hh = _mm_add_ps(hh0, hh1); - __m128 hhrec = _mm_rcp_ps(hh); + hh = norm / (crealf(h0) * crealf(h0) + cimagf(h0) * cimagf(h0) + crealf(h1) * crealf(h1) + cimagf(h1) * cimagf(h1)); - hhrec = _mm_mul_ps(hhrec, _mm_set1_ps((float) M_SQRT2 / scaling)); + x[0][i] = (conjf(h0) * y[0][i] + conjf(h1) * y[1][i]) * hh; + } + return SRSLTE_SUCCESS; +} - __m128 y0 = _mm_load_ps((float*)&y[0][i]); - __m128 y1 = _mm_load_ps((float*)&y[1][i]); +// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer +static int srslte_predecoding_multiplex_2x1_mrc_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi, + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = (float) M_SQRT2 / scaling; + int i = 0; - __m128 x0 = _mm_add_ps(_MM_PROD_PS(_MM_CONJ_PS(h0), y0), _MM_PROD_PS(_MM_CONJ_PS(h1), y1)); - x0 = _mm_mul_ps(hhrec, x0); +#if SRSLTE_SIMD_CF_SIZE != 0 + simd_f_t _norm = srslte_simd_f_set1(norm); - _mm_store_ps((float*)&x[0][i], x0); + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t x0 = srslte_simd_cf_set1(0.0f); + simd_f_t hh = srslte_simd_f_set1(0.0f); - } + for (int k = 0; k < 2; k++) { + simd_cf_t h0xi = srslte_simd_cfi_load(&h[0][k][i]); + simd_cf_t h1xi = srslte_simd_cfi_load(&h[1][k][i]); + simd_cf_t yx = srslte_simd_cfi_load(&y[k][i]); - return SRSLTE_SUCCESS; -} + simd_cf_t hx; + switch (codebook_idx) { + case 0: + hx = srslte_simd_cf_add(h0xi, h1xi); + break; + case 1: + hx = srslte_simd_cf_sub(h0xi, h1xi); + break; + case 2: + hx = srslte_simd_cf_add(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + case 3: + hx = srslte_simd_cf_sub(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } -#endif /* LV_HAVE_SSE */ + hh = srslte_simd_f_add(srslte_simd_cf_re(srslte_simd_cf_conjprod(hx, hx)), hh); + x0 = srslte_simd_cf_add(srslte_simd_cf_conjprod(yx, hx), x0); + } -// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -int srslte_predecoding_multiplex_2x1_mrc_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = (float) M_SQRT2 / scaling; + hh = srslte_simd_f_mul(_norm, srslte_simd_f_rcp(hh)); + srslte_simd_cfi_store(&x[0][i], srslte_simd_cf_mul(x0, hh)); + srslte_simd_f_store(&csi[i], srslte_simd_f_mul(srslte_simd_f_rcp(hh), srslte_simd_f_set1((float) M_SQRT1_2))); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ - for (int i = 0; i < nof_symbols; i += 1) { + for (; i < nof_symbols; i += 1) { cf_t h0, h1; - float hh; + float hh, _csi; - switch(codebook_idx) { + switch (codebook_idx) { case 0: h0 = h[0][0][i] + h[1][0][i]; h1 = h[0][1][i] + h[1][1][i]; @@ -1647,53 +1703,57 @@ int srslte_predecoding_multiplex_2x1_mrc_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[ return SRSLTE_ERROR; } - hh = norm / (crealf(h0) * crealf(h0) + cimagf(h0) * cimagf(h0) + crealf(h1) * crealf(h1) + cimagf(h1) * cimagf(h1)); + _csi = crealf(h0) * crealf(h0) + cimagf(h0) * cimagf(h0) + crealf(h1) * crealf(h1) + cimagf(h1) * cimagf(h1); + hh = norm / _csi; x[0][i] = (conjf(h0) * y[0][i] + conjf(h1) * y[1][i]) * hh; + csi[i] = _csi / norm * (float) M_SQRT1_2; } return SRSLTE_SUCCESS; } -int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) -{ +static int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { if (nof_ports == 2 && nof_rxant <= 2) { if (nof_layers == 2) { switch (mimo_decoder) { case SRSLTE_MIMO_DECODER_ZF: -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x2_zf_avx(y, h, x, codebook_idx, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x2_zf_sse(y, h, x, codebook_idx, nof_symbols, scaling); -#else - return srslte_predecoding_multiplex_2x2_zf_gen(y, h, x, codebook_idx, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x2_zf_csi(y, h, x, csi[0], codebook_idx, nof_symbols, scaling); + } else { + return srslte_predecoding_multiplex_2x2_zf(y, h, x, codebook_idx, nof_symbols, scaling); + } break; case SRSLTE_MIMO_DECODER_MMSE: -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x2_mmse_avx(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x2_mmse_sse(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#else - return srslte_predecoding_multiplex_2x2_mmse_gen(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x2_mmse_csi(y, + h, + x, + csi, + codebook_idx, + nof_symbols, + scaling, + noise_estimate); + } else { + return srslte_predecoding_multiplex_2x2_mmse(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); + } break; } } else { -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x1_mrc_avx(y, h, x, codebook_idx, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x1_mrc_sse(y, h, x, codebook_idx, nof_symbols, scaling); -#else - return srslte_predecoding_multiplex_2x1_mrc_gen(y, h, x, codebook_idx, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x1_mrc_csi(y, h, x, csi[0], codebook_idx, nof_symbols, scaling); + } else { + return srslte_predecoding_multiplex_2x1_mrc(y, h, x, codebook_idx, nof_symbols, scaling); + } } } else if (nof_ports == 4) { DEBUG("Error predecoding multiplex: not implemented for %d Tx ports", nof_ports); @@ -1759,7 +1819,7 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] } break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: - return srslte_predecoding_multiplex(y, h, x, nof_rxant, nof_ports, nof_layers, codebook_idx, nof_symbols, + return srslte_predecoding_multiplex(y, h, x, csi, nof_rxant, nof_ports, nof_layers, codebook_idx, nof_symbols, scaling, noise_estimate); default: return SRSLTE_ERROR; From e71dde7311f99a69cd054a962fae0ff337673b3f Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Mon, 23 Apr 2018 15:38:31 +0100 Subject: [PATCH 26/52] Fix for RRC ReportConfigEUTRA pack function --- lib/src/asn1/liblte_rrc.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index 74beb46cf..60bf992b6 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -2715,8 +2715,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_eutra_ie(LIBLTE_RRC_REPORT_CONFI liblte_value_2_bits(rep_cnfg_eutra->trigger_type, ie_ptr, 1); if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type) { + // Event ID choice extension indicator + liblte_value_2_bits(0, ie_ptr, 1); // Choice with extension - unlikely to be >63 choices + // Event ID - // FIXME: Handle extension properly liblte_value_2_bits(rep_cnfg_eutra->event.event_id, ie_ptr, 3); if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id) { From 786d29962bd624040172e4facc912e2f0a222035 Mon Sep 17 00:00:00 2001 From: frankist Date: Mon, 23 Apr 2018 17:28:29 +0100 Subject: [PATCH 27/52] refactoring and improvement of time-domain RR scheduling (#181) * fixed the scheduler not filling the mask for multiple UEs * fixed a bug related with the reset of the allocations * The RR now saves the last UE to be assigned --- srsenb/hdr/mac/scheduler_metric.h | 13 ++- srsenb/hdr/mac/scheduler_ue.h | 3 +- srsenb/src/mac/scheduler_metric.cc | 132 ++++++++++++++--------------- srsenb/src/mac/scheduler_ue.cc | 2 +- 4 files changed, 73 insertions(+), 77 deletions(-) diff --git a/srsenb/hdr/mac/scheduler_metric.h b/srsenb/hdr/mac/scheduler_metric.h index 11e77b455..4685f932a 100644 --- a/srsenb/hdr/mac/scheduler_metric.h +++ b/srsenb/hdr/mac/scheduler_metric.h @@ -42,18 +42,17 @@ private: bool new_allocation(uint32_t nof_rbg, uint32_t* rbgmask); void update_allocation(uint32_t new_mask); - bool allocation_is_valid(uint32_t mask); - - + bool allocation_is_valid(uint32_t mask); + dl_harq_proc* apply_user_allocation(sched_ue *user); + uint32_t get_required_rbg(sched_ue *user, uint32_t tti); uint32_t count_rbg(uint32_t mask); uint32_t calc_rbg_mask(bool mask[25]); bool used_rb[MAX_RBG]; - uint32_t nof_users_with_data; - - uint32_t current_tti; + + uint32_t current_tti; uint32_t total_rb; uint32_t used_rb_mask; uint32_t nof_ctrl_symbols; @@ -72,8 +71,8 @@ private: bool new_allocation(uint32_t L, ul_harq_proc::ul_alloc_t *alloc); bool allocation_is_valid(ul_harq_proc::ul_alloc_t alloc); + ul_harq_proc* apply_user_allocation(sched_ue *user); - uint32_t nof_users_with_data; bool used_rb[MAX_PRB]; uint32_t current_tti; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 90db552a6..aaa4b49b7 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -40,7 +40,8 @@ class sched_ue { public: // used by sched_metric - uint32_t ue_idx; + dl_harq_proc* dl_next_alloc; + ul_harq_proc* ul_next_alloc; bool has_pucch; diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index a15faebbd..f6ec18555 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -78,7 +78,6 @@ uint32_t dl_metric_rr::get_required_rbg(sched_ue *user, uint32_t tti) void dl_metric_rr::new_tti(std::map &ue_db, uint32_t start_rb, uint32_t nof_rb, uint32_t nof_ctrl_symbols_, uint32_t tti) { - total_rb = start_rb+nof_rb; for (uint32_t i=0;i &ue_db, uint32_t start_rb } available_rb = nof_rb; used_rb_mask = calc_rbg_mask(used_rb); - current_tti = tti; - nof_ctrl_symbols = nof_ctrl_symbols_; - - nof_users_with_data = 0; - for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_dl_new_data(current_tti) || user->get_pending_dl_harq(current_tti)) { - user->ue_idx = nof_users_with_data; - nof_users_with_data++; + current_tti = tti; + nof_ctrl_symbols = nof_ctrl_symbols_; + + if(ue_db.size()==0) + return; + + // give priority in a time-domain RR basis + uint32_t priority_idx = current_tti % ue_db.size(); + std::map::iterator iter = ue_db.begin(); + std::advance(iter,priority_idx); + for(uint32_t ue_count = 0 ; ue_count < ue_db.size() ; ++iter, ++ue_count) { + if(iter==ue_db.end()) { + iter = ue_db.begin(); // wrap around } + sched_ue *user = (sched_ue*) &iter->second; + user->dl_next_alloc = apply_user_allocation(user); } } @@ -136,25 +141,11 @@ bool dl_metric_rr::allocation_is_valid(uint32_t mask) return (mask & used_rb_mask); } -dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) -{ - uint32_t pending_data = user->get_pending_dl_new_data(current_tti); +dl_harq_proc* dl_metric_rr::apply_user_allocation(sched_ue *user) { + uint32_t pending_data = user->get_pending_dl_new_data(current_tti); dl_harq_proc *h = user->get_pending_dl_harq(current_tti); - // Time-domain RR scheduling -#if ASYNC_DL_SCHED - if (pending_data || h) { -#else - if (pending_data || (h && !h->is_empty())) { -#endif - if (nof_users_with_data) { - if ((current_tti%nof_users_with_data) != user->ue_idx) { - return NULL; - } - } - } - - // Schedule retx if we have space + // Schedule retx if we have space #if ASYNC_DL_SCHED if (h) { #else @@ -164,38 +155,45 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) // If can schedule the same mask, do it if (!allocation_is_valid(retx_mask)) { update_allocation(retx_mask); - return h; + return h; } - // If not, try to find another mask in the current tti + + // If not, try to find another mask in the current tti uint32_t nof_rbg = count_rbg(retx_mask); if (nof_rbg < available_rb) { if (new_allocation(nof_rbg, &retx_mask)) { update_allocation(retx_mask); h->set_rbgmask(retx_mask); - return h; + return h; } } - } + } // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID #if ASYNC_DL_SCHED - h = user->get_empty_dl_harq(); + h = user->get_empty_dl_harq(); if (h) { #else - if (h && h->is_empty()) { + if (h && h->is_empty()) { #endif // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols); - uint32_t newtx_mask = 0; + uint32_t newtx_mask = 0; new_allocation(pending_rb, &newtx_mask); if (newtx_mask) { update_allocation(newtx_mask); h->set_rbgmask(newtx_mask); - return h; + return h; } - } + } } - return NULL; + + return NULL; +} + +dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) +{ + return user->dl_next_alloc; } @@ -219,15 +217,20 @@ void ul_metric_rr::new_tti(std::map &ue_db, uint32_t nof_rb_, available_rb = nof_rb_; bzero(used_rb, nof_rb*sizeof(bool)); - nof_users_with_data = 0; - for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty(0)) { - user->ue_idx = nof_users_with_data; - nof_users_with_data++; + if(ue_db.size()==0) + return; + + // give priority in a time-domain RR basis + uint32_t priority_idx = (current_tti+ue_db.size()/2) % ue_db.size(); // make DL and UL interleaved + std::map::iterator iter = ue_db.begin(); + std::advance(iter,priority_idx); + for(uint32_t ue_count = 0 ; ue_count < ue_db.size() ; ++iter, ++ue_count) { + if(iter==ue_db.end()) { + iter = ue_db.begin(); // wrap around } + sched_ue *user = (sched_ue*) &iter->second; + user->ul_next_alloc = apply_user_allocation(user); } - } bool ul_metric_rr::allocation_is_valid(ul_harq_proc::ul_alloc_t alloc) @@ -288,56 +291,49 @@ void ul_metric_rr::update_allocation(ul_harq_proc::ul_alloc_t alloc) available_rb -= alloc.L; } -ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) -{ +ul_harq_proc* ul_metric_rr::apply_user_allocation(sched_ue *user) { // Time-domain RR scheduling - uint32_t pending_data = user->get_pending_ul_new_data(current_tti); + uint32_t pending_data = user->get_pending_ul_new_data(current_tti); ul_harq_proc *h = user->get_ul_harq(current_tti); - - if (pending_data || !h->is_empty(0)) { - if (nof_users_with_data) { - if ((current_tti%nof_users_with_data) != user->ue_idx) { - return NULL; - } - } - } - // Schedule retx if we have space - + // Schedule retx if we have space if (!h->is_empty(0)) { - ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); - + // If can schedule the same mask, do it if (allocation_is_valid(alloc)) { update_allocation(alloc); return h; } - + // If not, try to find another mask in the current tti if (new_allocation(alloc.L, &alloc)) { update_allocation(alloc); h->set_alloc(alloc); return h; } - } - // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID + } + + // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID if (h->is_empty(0)) { - // Allocate resources based on pending data + // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_ul(pending_data); - ul_harq_proc::ul_alloc_t alloc; + ul_harq_proc::ul_alloc_t alloc; new_allocation(pending_rb, &alloc); if (alloc.L) { update_allocation(alloc); h->set_alloc(alloc); - return h; + return h; } - } + } } - return NULL; + return NULL; } - +ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) +{ + return user->ul_next_alloc; +} } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 6cb4462e8..f9245ac9b 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -49,7 +49,7 @@ namespace srsenb { * *******************************************************/ -sched_ue::sched_ue() : ue_idx(0), has_pucch(false), power_headroom(0), rnti(0), max_mcs_dl(0), max_mcs_ul(0), +sched_ue::sched_ue() : dl_next_alloc(NULL), ul_next_alloc(NULL), has_pucch(false), power_headroom(0), rnti(0), max_mcs_dl(0), max_mcs_ul(0), fixed_mcs_ul(0), fixed_mcs_dl(0), phy_config_dedicated_enabled(false) { log_h = NULL; From 9c7b3339befbe0152549a4c4718c2c4fd4befa0f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 10:18:13 +0200 Subject: [PATCH 28/52] Get CRS-based RSRP estimate for in/out-sync measurement. New SNR estimation gives 0 SNR when cell signal is lost preventing from detecting out-of-sync --- srsue/hdr/phy/phch_common.h | 6 ++- srsue/src/phy/phch_common.cc | 3 ++ srsue/src/phy/phch_worker.cc | 82 ++++++++++++++++++++++-------------- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 32289a6b0..4d2536f53 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -68,15 +68,17 @@ public: float cur_radio_power; float cur_pusch_power; float avg_rsrp; + float avg_rsrp_cqi; float avg_rsrp_dbm; + float avg_rsrp_sync_dbm; float avg_rsrq_db; float avg_rssi_dbm; float last_radio_rssi; float rx_gain_offset; - float avg_snr_db; + float avg_snr_db_cqi; + float avg_snr_db_sync; float avg_noise; - bool pcell_first_measurement; uint32_t pcell_report_period; // Save last TBS for mcs>28 cases diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 5b081ac3c..1129e7c6e 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -342,7 +342,10 @@ void phch_common::reset() { cur_radio_power = 0; sr_last_tx_tti = -1; cur_pusch_power = 0; + avg_snr_db_cqi = 0; + avg_snr_db_sync = 0; avg_rsrp = 0; + avg_rsrp_cqi = 0; avg_rsrp_dbm = 0; avg_rsrq_db = 0; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 212c5839a..698f830fa 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -133,6 +133,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph return false; } + srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); srslte_chest_dl_average_subframe(&ue_dl.chest, phy->args->average_subframe_enabled); srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask); srslte_ue_ul_set_normalization(&ue_ul, true); @@ -164,8 +165,6 @@ 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; @@ -393,13 +392,13 @@ void phch_worker::work_imp() update_measurements(); if (chest_ok) { - if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -10.0) { - log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", - phy->avg_snr_db, phy->avg_rsrp_dbm); + if (phy->avg_rsrp_sync_dbm > -130.0 && phy->avg_snr_db_sync > -10.0) { + log_h->info("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", + phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->in_sync(); } else { - log_h->warning("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", - phy->avg_snr_db, phy->avg_rsrp_dbm); + log_h->info("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", + phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->out_of_sync(); } } @@ -914,16 +913,16 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND; - cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db_cqi); cqi_report.subband.subband_label = 0; log_h->console("Warning: Subband CQI periodic reports not implemented\n"); - Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db); + Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db_cqi); } else { cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND; if (cqi_fixed >= 0) { cqi_report.wideband.wideband_cqi = cqi_fixed; } else { - cqi_report.wideband.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.wideband.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db_cqi); } if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) { cqi_report.wideband.wideband_cqi = cqi_max; @@ -933,7 +932,7 @@ void phch_worker::set_uci_periodic_cqi() cqi_report.wideband.pmi = phy->last_pmi; cqi_report.wideband.rank_is_not_one = (phy->last_ri != 0); } - Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); + Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db_cqi); } uci_data.uci_cqi_len = (uint32_t) srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; @@ -963,7 +962,7 @@ void phch_worker::set_uci_aperiodic_cqi() if (rnti_is_set) { srslte_cqi_value_t cqi_report = {0}; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db_cqi); // TODO: implement subband CQI properly cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands @@ -989,7 +988,7 @@ void phch_worker::set_uci_aperiodic_cqi() } Info("PUSCH: Aperiodic RM30 CQI=%s, %sSNR=%.1f dB, for %d subbands\n", - cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db, cqi_report.subband_hl.N); + cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db_cqi, cqi_report.subband_hl.N); } break; case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: @@ -1402,18 +1401,18 @@ void phch_worker::update_measurements() } } - // Average RSRQ + // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); if (isnormal(rsrq_db)) { - if (!phy->avg_rsrq_db) { - phy->avg_rsrq_db = SRSLTE_VEC_EMA(rsrq_db, phy->avg_rsrq_db, snr_ema_coeff); - } else { + if (!(tti%phy->pcell_report_period) || !phy->avg_rsrq_db) { phy->avg_rsrq_db = rsrq_db; + } else { + phy->avg_rsrq_db = SRSLTE_VEC_CMA(rsrq_db, phy->avg_rsrq_db, tti%phy->pcell_report_period); } } - // Average RSRP - float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest); + // Average RSRP taken from CRS + float rsrp_lin = srslte_chest_dl_get_rsrp_neighbour(&ue_dl.chest); if (isnormal(rsrp_lin)) { if (!phy->avg_rsrp) { phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff); @@ -1425,19 +1424,20 @@ void phch_worker::update_measurements() /* Correct absolute power measurements by RX gain offset */ float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset; - // Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC + // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC if (isnormal(rsrp_dbm)) { - if (!phy->avg_rsrp_dbm) { + if (!(tti%phy->pcell_report_period) || !phy->avg_rsrp_dbm) { phy->avg_rsrp_dbm = rsrp_dbm; } 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_first_measurement) { - phy->pcell_first_measurement = false; - phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); + phy->avg_rsrp_dbm = SRSLTE_VEC_CMA(rsrp_dbm, phy->avg_rsrp_dbm, tti%phy->pcell_report_period); } } + // Send PCell measurement + if ((tti%phy->pcell_report_period) == phy->pcell_report_period-1) { + phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); + } + // Compute PL float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm; @@ -1451,17 +1451,37 @@ void phch_worker::update_measurements() phy->avg_noise = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise, snr_ema_coeff); } } - - // Compute SNR - phy->avg_snr_db = 10*log10(phy->avg_rsrp/phy->avg_noise); - + + // To compute CQI use RSRP measurements from resource elements in RS since is more robust to time offset + float rsrp_lin_cqi = srslte_chest_dl_get_rsrp(&ue_dl.chest); + if (isnormal(rsrp_lin_cqi)) { + if (!phy->avg_rsrp_cqi) { + phy->avg_rsrp_cqi = SRSLTE_VEC_EMA(rsrp_lin_cqi, phy->avg_rsrp_cqi, snr_ema_coeff); + } else { + phy->avg_rsrp_cqi = rsrp_lin_cqi; + } + } + float rsrp_sync_dbm = 10*log10(rsrp_lin_cqi) + 30 - phy->rx_gain_offset; + if (isnormal(rsrp_sync_dbm)) { + if (!phy->avg_rsrp_sync_dbm) { + phy->avg_rsrp_sync_dbm = rsrp_sync_dbm; + } else { + phy->avg_rsrp_sync_dbm = SRSLTE_VEC_EMA(rsrp_sync_dbm, phy->avg_rsrp_sync_dbm, snr_ema_coeff); + } + } + + // We compute 2 SNR metrics, 1 for deciding in-sync/out-of-sync and another for CQI measurements + phy->avg_snr_db_cqi = 10*log10(phy->avg_rsrp_cqi/phy->avg_noise); // this for CQI + phy->avg_snr_db_sync = 10*log10(phy->avg_rsrp/phy->avg_noise); // this for sync + + // Store metrics dl_metrics.n = phy->avg_noise; dl_metrics.rsrp = phy->avg_rsrp_dbm; dl_metrics.rsrq = phy->avg_rsrq_db; dl_metrics.rssi = phy->avg_rssi_dbm; dl_metrics.pathloss = phy->pathloss; - dl_metrics.sinr = phy->avg_snr_db; + dl_metrics.sinr = phy->avg_snr_db_cqi; dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch); phy->set_dl_metrics(dl_metrics); From e446c14214af38eb523f8131d4bf633182704a31 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 10:24:06 +0200 Subject: [PATCH 29/52] Restored in/out-sync debug --- srsue/src/phy/phch_worker.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 698f830fa..300e264fc 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -393,11 +393,11 @@ void phch_worker::work_imp() if (chest_ok) { if (phy->avg_rsrp_sync_dbm > -130.0 && phy->avg_snr_db_sync > -10.0) { - log_h->info("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", + log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->in_sync(); } else { - log_h->info("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", + log_h->warning("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->out_of_sync(); } From ab7a0842ba42356bbee5440d3a2b58c003d517f9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 10:43:17 +0200 Subject: [PATCH 30/52] Send PRACH from worker thread with zero time advance --- srsue/hdr/phy/phch_worker.h | 3 ++ srsue/hdr/phy/prach.h | 14 +++--- srsue/src/phy/phch_recv.cc | 53 ++++++++++++-------- srsue/src/phy/phch_worker.cc | 97 +++++++++++++++++++++--------------- srsue/src/phy/phy.cc | 1 + srsue/src/phy/prach.cc | 74 ++++++++++----------------- 6 files changed, 123 insertions(+), 119 deletions(-) diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 53848905b..14687da73 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -53,6 +53,7 @@ public: cf_t* get_buffer(uint32_t antenna_idx); void set_tti(uint32_t tti, uint32_t tx_tti); void set_tx_time(srslte_timestamp_t tx_time, uint32_t next_offset); + void set_prach(cf_t *prach_ptr, float prach_power); void set_cfo(float cfo); void set_ul_params(bool pregen_disabled = false); @@ -169,6 +170,8 @@ private: bool sr_configured; float cfo; bool rar_cqi_request; + cf_t *prach_ptr; + float prach_power; uint32_t rssi_read_cnt; diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 651203eb7..06d8f61cf 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -58,13 +58,11 @@ namespace srsue { bool is_ready_to_send(uint32_t current_tti); bool is_pending(); int tx_tti(); - - void send(srslte::radio* radio_handler, float cfo, float pathloss, srslte_timestamp_t rx_time); - float get_p0_preamble(); - - static const uint32_t tx_advance_sf = 4; // Number of subframes to advance transmission - - private: + cf_t* generate(float cfo, uint32_t *nof_sf, float *target_power = NULL); + + private: + + const static int MAX_LEN_SF = 3; LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config; phy_args_t *args; @@ -81,7 +79,7 @@ namespace srsue { srslte_cell_t cell; cf_t *signal_buffer; srslte_cfo_t cfo_h; - float target_power_dbm; + float target_power_dbm; }; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 7cd7a7abe..12c113e24 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -367,6 +367,11 @@ void phch_recv::run_thread() dummy_buffer[i] = (cf_t*) malloc(sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); } + uint32_t prach_nof_sf = 0; + uint32_t prach_sf_cnt = 0; + cf_t *prach_ptr = NULL; + float prach_power = 0; + while (running) { Debug("SYNC: state=%s\n", phy_state.to_string()); @@ -423,40 +428,46 @@ 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(get_tx_cfo()); worker_com->set_sync_metrics(metrics); + // Check if we need to TX a PRACH + if (prach_buffer->is_ready_to_send(tti)) { + prach_ptr = prach_buffer->generate(get_tx_cfo(), &prach_nof_sf, &prach_power); + if (!prach_ptr) { + Error("Generating PRACH\n"); + } + } + /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ - srslte_timestamp_t rx_time, tx_time, tx_time_prach; + srslte_timestamp_t rx_time, tx_time; srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); - worker->set_tx_time(tx_time, next_offset); - next_offset = 0; + if (prach_ptr) { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3); + } else { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); + } - Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id()); + worker->set_prach(prach_ptr?&prach_ptr[prach_sf_cnt*SRSLTE_SF_LEN_PRB(cell.nof_prb)]:NULL, prach_power); + worker->set_cfo(get_tx_cfo()); worker->set_tti(tti, tx_mutex_cnt); + worker->set_tx_time(tx_time, next_offset); + next_offset = 0; tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; - // Reset Uplink TX buffer to avoid mixing packets in TX queue - /* - if (prach_buffer->is_pending()) { - Info("SYNC: PRACH pending: Reset UL\n"); - radio_h->tx_end(); - }*/ - - // Check if we need to TX a PRACH - 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, 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); + // Advance/reset prach subframe pointer + if (prach_ptr) { + prach_sf_cnt++; + if (prach_sf_cnt == prach_nof_sf) { + prach_sf_cnt = 0; + prach_ptr = NULL; + } } + // Start worker workers_pool->start_worker(worker); + // Save signal for Intra-frequency measurement if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 300e264fc..8bdbe12e2 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -186,6 +186,11 @@ void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_) log_phy_lib_h->step(tti); } +void phch_worker::set_prach(cf_t *prach_ptr, float prach_power) { + this->prach_ptr = prach_ptr; + this->prach_power = prach_power; +} + void phch_worker::set_cfo(float cfo_) { cfo = cfo_; @@ -319,60 +324,70 @@ void phch_worker::work_imp() /***** Uplink Processing + Transmission *******/ - - /* Generate SR if required*/ - set_uci_sr(); - /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ - ul_grant_available = decode_pdcch_ul(&ul_mac_grant); + bool signal_ready = false; + cf_t *signal_ptr = NULL; - /* Generate CQI reports if required, note that in case both aperiodic - and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ - if (ul_grant_available && ul_mac_grant.has_cqi_request) { - set_uci_aperiodic_cqi(); + /* Transmit PRACH if pending, or PUSCH/PUCCH otherwise */ + if (prach_ptr) { + signal_ready = true; + signal_ptr = prach_ptr; } else { - set_uci_periodic_cqi(); - } + /* Generate SR if required*/ + set_uci_sr(); - /* TTI offset for UL */ - ul_action.tti_offset = HARQ_DELAY_MS; + /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ + ul_grant_available = decode_pdcch_ul(&ul_mac_grant); - /* Send UL grant or HARQ information (from PHICH) to MAC */ - if (ul_grant_available && ul_ack_available) { - phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); - } else if (ul_grant_available && !ul_ack_available) { - phy->mac->new_grant_ul(ul_mac_grant, &ul_action); - } else if (!ul_grant_available && ul_ack_available) { - phy->mac->harq_recv(tti, ul_ack, &ul_action); - } + /* Generate CQI reports if required, note that in case both aperiodic + and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ + if (ul_grant_available && ul_mac_grant.has_cqi_request) { + set_uci_aperiodic_cqi(); + } else { + set_uci_periodic_cqi(); + } + + /* TTI offset for UL */ + ul_action.tti_offset = HARQ_DELAY_MS; - /* Set UL CFO before transmission */ - srslte_ue_ul_set_cfo(&ue_ul, cfo); - - /* Transmit PUSCH, PUCCH or SRS */ - bool signal_ready = false; - if (ul_action.tx_enabled) { - encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, - &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); - signal_ready = true; - if (ul_action.expect_ack) { - phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + /* Send UL grant or HARQ information (from PHICH) to MAC */ + if (ul_grant_available && ul_ack_available) { + phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); + } else if (ul_grant_available && !ul_ack_available) { + phy->mac->new_grant_ul(ul_mac_grant, &ul_action); + } else if (!ul_grant_available && ul_ack_available) { + phy->mac->harq_recv(tti, ul_ack, &ul_action); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { - encode_pucch(); - signal_ready = true; - } else if (srs_is_ready_to_send()) { - encode_srs(); - signal_ready = true; - } + /* Set UL CFO before transmission */ + srslte_ue_ul_set_cfo(&ue_ul, cfo); + + /* Transmit PUSCH, PUCCH or SRS */ + if (ul_action.tx_enabled) { + encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, + &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); + signal_ready = true; + if (ul_action.expect_ack) { + phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + } + + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { + encode_pucch(); + signal_ready = true; + } else if (srs_is_ready_to_send()) { + encode_srs(); + signal_ready = true; + } + signal_ptr = signal_buffer[0]; + } + tr_log_end(); if (next_offset > 0) { - phy->worker_end(tx_tti, signal_ready, signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, signal_ptr, SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } else { - phy->worker_end(tx_tti, signal_ready, &signal_buffer[0][-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, &signal_ptr[-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } if (!dl_action.generate_ack_callback) { diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 875fc483c..eb1b87aa7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -341,6 +341,7 @@ void phy::reset() { Info("Resetting PHY\n"); n_ta = 0; + sf_recv.set_time_adv_sec(0); pdcch_dl_search_reset(); for(uint32_t i=0;i= 0 && nof_sf) { -void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte_timestamp_t tx_time) -{ - - // Get current TX gain - float old_gain = radio_handler->get_tx_gain(); - - // Correct CFO before transmission FIXME: UL SISO Only - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); - - // If power control is enabled, choose amplitude and power - if (args->ul_pwr_ctrl_en) { - // Get PRACH transmission power - float tx_power = SRSLTE_MIN(SRSLTE_PC_MAX, pathloss + target_power_dbm); - - // Get output power for amplitude 1 - radio_handler->set_tx_power(tx_power); - - // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); - float scale = sqrtf(pow(10,tx_power/10)/digital_power); - - srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); - log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB, scale %.2f\n", - pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); - - } else { - float prach_gain = args->prach_gain; - if (prach_gain > 0) { - radio_handler->set_tx_gain(prach_gain); + // Correct CFO before transmission FIXME: UL SISO Only + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + + // pad guard symbols with zeros + uint32_t nsf = (len-1)/SRSLTE_SF_LEN_PRB(cell.nof_prb)+1; + bzero(&signal_buffer[len], (nsf*SRSLTE_SF_LEN_PRB(cell.nof_prb)-len)*sizeof(cf_t)); + + *nof_sf = nsf; + + if (target_power) { + *target_power = target_power_dbm; } - Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); - } - void *tmp_buffer[SRSLTE_MAX_PORTS] = {signal_buffer, NULL, NULL, NULL}; - radio_handler->tx(tmp_buffer, len, tx_time); - radio_handler->tx_end(); - - Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", - preamble_idx, cfo*15, tx_time.frac_secs); - preamble_idx = -1; + Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, nof_sf=%d, target_power=%.1f dBm\n", + preamble_idx, cfo*15, nsf, target_power_dbm); + preamble_idx = -1; - radio_handler->set_tx_gain(old_gain); - Debug("Restoring TX gain to %.0f dB\n", old_gain); + return signal_buffer; + } else { + return NULL; + } } } // namespace srsue From 6348745b192c0d1367d9e342fd53a932d4b214b0 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 12:58:28 +0200 Subject: [PATCH 31/52] Restored RAR search debug level --- srsue/src/phy/phch_worker.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 8bdbe12e2..d34aa90e8 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -524,13 +524,13 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) srslte_ra_dl_dci_t dci_unpacked; if (type == SRSLTE_RNTI_RAR) { - Info("Looking for RNTI=0x%x\n", dl_rnti); + Debug("Looking for RNTI=0x%x\n", dl_rnti); } if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10, dl_rnti, type, &dci_msg) != 1) { if (type == SRSLTE_RNTI_RAR) { - Info("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n", + Debug("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), tti, cfi, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cell.id); } From 5ab0149218d57c59734a9b06140d816342b6fec7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 13:18:48 +0200 Subject: [PATCH 32/52] Apply new TA through sample offset --- srsue/src/phy/phch_recv.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 12c113e24..687e66fea 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -615,6 +615,8 @@ void phch_recv::set_agc_enable(bool enable) void phch_recv::set_time_adv_sec(float time_adv_sec) { this->time_adv_sec = time_adv_sec; + next_offset = -time_adv_sec*srslte_sampling_freq_hz(cell.nof_prb); + Info("Applying time_adv_sec=%.1f us, next_offset=%d\n", time_adv_sec*1e6, next_offset); } float phch_recv::get_tx_cfo() From 74d60287697a5e77c8e32411b089efb6832078ca Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 13:50:59 +0200 Subject: [PATCH 33/52] Delay application of time_adv by 1 subframe --- srsue/hdr/phy/phch_recv.h | 2 +- srsue/src/phy/phch_recv.cc | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index faff85ca7..78559d3cd 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -425,7 +425,7 @@ private: // This is the primary cell srslte_cell_t cell; bool started; - float time_adv_sec; + float time_adv_sec, next_time_adv_sec; uint32_t tti; bool do_agc; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 687e66fea..9d6e39f4f 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -453,6 +453,9 @@ void phch_recv::run_thread() worker->set_tti(tti, tx_mutex_cnt); worker->set_tx_time(tx_time, next_offset); next_offset = 0; + if (next_time_adv_sec != time_adv_sec) { + time_adv_sec = next_time_adv_sec; + } tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; // Advance/reset prach subframe pointer @@ -614,8 +617,11 @@ void phch_recv::set_agc_enable(bool enable) void phch_recv::set_time_adv_sec(float time_adv_sec) { - this->time_adv_sec = time_adv_sec; - next_offset = -time_adv_sec*srslte_sampling_freq_hz(cell.nof_prb); + // If transmitting earlier, transmit less samples to align time advance. If transmit later just delay next TX + if (time_adv_sec > this->time_adv_sec) { + next_offset = -floor(time_adv_sec*srslte_sampling_freq_hz(cell.nof_prb)+1); + } + this->next_time_adv_sec = time_adv_sec; Info("Applying time_adv_sec=%.1f us, next_offset=%d\n", time_adv_sec*1e6, next_offset); } From 5b7b176ac7f3af7a250d2674e547d57500fccea1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 16:51:13 +0200 Subject: [PATCH 34/52] Fixed HO with new PRACH --- srsue/src/phy/phch_recv.cc | 2 +- srsue/src/upper/rrc.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 9d6e39f4f..780f2c72a 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -619,7 +619,7 @@ void phch_recv::set_time_adv_sec(float time_adv_sec) { // If transmitting earlier, transmit less samples to align time advance. If transmit later just delay next TX if (time_adv_sec > this->time_adv_sec) { - next_offset = -floor(time_adv_sec*srslte_sampling_freq_hz(cell.nof_prb)+1); + next_offset = floor((this->time_adv_sec-time_adv_sec)*srslte_sampling_freq_hz(cell.nof_prb)+1); } this->next_time_adv_sec = time_adv_sec; Info("Applying time_adv_sec=%.1f us, next_offset=%d\n", time_adv_sec*1e6, next_offset); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 9f4022825..ae975e1cc 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1308,7 +1308,7 @@ bool rrc::ho_prepare() { pdcp->reestablish(); rlc->reestablish(); mac->reset(); - // PHY is reset inside cell_handover() function + phy->reset(); mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); From 431fce998e70bf00e89552587ca04cbcc6f9583e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 24 Apr 2018 18:45:55 +0200 Subject: [PATCH 35/52] Allow negative time_adv_nsamples parameter --- lib/src/radio/radio.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index d4cc2aa6c..3be26e6b3 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -451,6 +451,10 @@ void radio::set_tx_srate(double srate) // Calculate TX advance in seconds from samples and sampling rate tx_adv_sec = nsamples/cur_tx_srate; + if (tx_adv_sec<0) { + tx_adv_sec *= -1; + tx_adv_negative = true; + } } void radio::register_error_handler(srslte_rf_error_handler_t h) From 35e8b1ca76029616fd7178c5100fae34777b74fc Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 13:07:27 +0200 Subject: [PATCH 36/52] Attach only once from main --- srsue/src/main.cc | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index dd03541f8..afb7a1f8b 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -474,29 +474,23 @@ int main(int argc, char *argv[]) pthread_t input; pthread_create(&input, NULL, &input_loop, &args); - bool plot_started = false; - bool signals_pregenerated = false; - - while (running) { - if (ue->is_attached()) { - if (!signals_pregenerated && args.expert.pregenerate_signals) { - ue->pregenerate_signals(true); - signals_pregenerated = true; - } - if (!plot_started && args.gui.enable) { - ue->start_plot(); - plot_started = true; - } - } else { - while (!ue->attach() && running) { - sleep(1); - } + printf("Attaching UE...\n"); + while (!ue->attach() && running) { + sleep(1); + printf("Could not attach. Trying again...\n"); + } + if (running) { + if (args.expert.pregenerate_signals) { + ue->pregenerate_signals(true); } - if (running) { - ue->print_pool(); - sleep(10); + if (args.gui.enable) { + ue->start_plot(); } } + while (running) { + ue->print_pool(); + sleep(10); + } pthread_cancel(input); metricshub.stop(); ue->stop(); From ab78eb6d58891469438cefad68425e3320b7c375 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 13:44:58 +0200 Subject: [PATCH 37/52] Process BCCH from pdu_process thread. Process PCCH from new thread in RRC --- lib/include/srslte/common/pdu_queue.h | 30 ++++++++++------- lib/src/common/pdu_queue.cc | 17 ++++++---- srsenb/hdr/mac/ue.h | 2 +- srsenb/src/mac/ue.cc | 2 +- srsue/hdr/mac/demux.h | 5 +-- srsue/hdr/upper/rrc.h | 17 ++++++++++ srsue/src/mac/demux.cc | 46 +++++++++++++++++---------- srsue/src/upper/rrc.cc | 32 +++++++++++++++++++ 8 files changed, 111 insertions(+), 40 deletions(-) diff --git a/lib/include/srslte/common/pdu_queue.h b/lib/include/srslte/common/pdu_queue.h index a0c2b1da9..5866ce3b3 100644 --- a/lib/include/srslte/common/pdu_queue.h +++ b/lib/include/srslte/common/pdu_queue.h @@ -41,29 +41,35 @@ namespace srslte { class pdu_queue { public: + typedef enum { + DCH, + BCH, + MCH + } channel_t; class process_callback { - public: - virtual void process_pdu(uint8_t *buff, uint32_t len, uint32_t tstamp) = 0; + public: + virtual void process_pdu(uint8_t *buff, uint32_t len, channel_t channel, uint32_t tstamp) = 0; }; pdu_queue(uint32_t pool_size = DEFAULT_POOL_SIZE) : pool(pool_size), callback(NULL), log_h(NULL) {} void init(process_callback *callback, log* log_h_); - uint8_t* request(uint32_t len); + uint8_t* request(uint32_t len); void deallocate(uint8_t* pdu); - void push(uint8_t *ptr, uint32_t len, uint32_t tstamp = 0); - + void push(uint8_t *ptr, uint32_t len, channel_t channel = DCH, uint32_t tstamp = 0); + bool process_pdus(); - + private: - const static int DEFAULT_POOL_SIZE = 64; // Number of PDU buffers in total - const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps - + const static int DEFAULT_POOL_SIZE = 64; // Number of PDU buffers in total + const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps + typedef struct { - uint8_t ptr[MAX_PDU_LEN]; - uint32_t len; - uint32_t tstamp; + uint8_t ptr[MAX_PDU_LEN]; + uint32_t len; + uint32_t tstamp; + channel_t channel; #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED char debug_name[128]; #endif diff --git a/lib/src/common/pdu_queue.cc b/lib/src/common/pdu_queue.cc index 061433033..9b5e83c7b 100644 --- a/lib/src/common/pdu_queue.cc +++ b/lib/src/common/pdu_queue.cc @@ -74,12 +74,13 @@ void pdu_queue::deallocate(uint8_t* pdu) * This function enqueues the packet and returns quicly because ACK * deadline is important here. */ -void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp) +void pdu_queue::push(uint8_t *ptr, uint32_t len, channel_t channel, uint32_t tstamp) { if (ptr) { pdu_t *pdu = (pdu_t*) ptr; pdu->len = len; pdu->tstamp = tstamp; + pdu->channel = channel; pdu_q.push(pdu); } else { log_h->warning("Error pushing pdu: ptr is empty\n"); @@ -88,15 +89,17 @@ void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp) bool pdu_queue::process_pdus() { - bool have_data = false; - uint32_t cnt = 0; - pdu_t *pdu; + bool have_data = false; + uint32_t cnt = 0; + pdu_t *pdu; while(pdu_q.try_pop(&pdu)) { if (callback) { - callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp); + callback->process_pdu(pdu->ptr, pdu->len, pdu->channel, pdu->tstamp); } - if (!pool.deallocate(pdu)) { - log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n"); + if (pdu->channel == DCH) { + if (!pool.deallocate(pdu)) { + log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n"); + } } cnt++; have_data = true; diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index e7fbd0c10..165c1ea3e 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -95,7 +95,7 @@ public: bool process_pdus(); uint8_t *request_buffer(uint32_t tti, uint32_t len); - void process_pdu(uint8_t *pdu, uint32_t nof_bytes, uint32_t tstamp); + void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp); void push_pdu(uint32_t tti, uint32_t len); void deallocate_pdu(uint32_t tti); diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index 39e8c88e2..975d6e9b1 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -142,7 +142,7 @@ void ue::set_tti(uint32_t tti) { #include -void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, uint32_t tstamp) +void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp) { // Unpack ULSCH MAC PDU mac_msg_ul.init_rx(nof_bytes, true); diff --git a/srsue/hdr/mac/demux.h b/srsue/hdr/mac/demux.h index c738a0fd3..410865c55 100644 --- a/srsue/hdr/mac/demux.h +++ b/srsue/hdr/mac/demux.h @@ -51,12 +51,13 @@ public: void push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); void push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); + void push_pdu_mch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes); void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg); bool get_uecrid_successful(); - - void process_pdu(uint8_t *pdu, uint32_t nof_bytes, uint32_t tstamp); + + void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp); private: const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 602ebd55b..1e099351d 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -36,6 +36,7 @@ #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" #include "srslte/common/threads.h" +#include "srslte/common/block_queue.h" #include #include @@ -253,6 +254,7 @@ class rrc ,public rrc_interface_pdcp ,public rrc_interface_rlc ,public srslte::timer_callback + ,public thread { public: rrc(); @@ -310,6 +312,21 @@ public: private: + + typedef struct { + enum { + PCCH, + STOP + } command; + byte_buffer_t *pdu; + } cmd_msg_t; + + bool running; + srslte::block_queue cmd_q; + void run_thread(); + + void process_pcch(byte_buffer_t *pdu); + srslte::byte_buffer_pool *pool; srslte::log *rrc_log; phy_interface_rrc *phy; diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 3e0d2f44f..640b78bd5 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -107,27 +107,29 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes) Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n"); - pdus.push(buff, nof_bytes); + pdus.push(buff, nof_bytes, srslte::pdu_queue::DCH); } else { Warning("Trying to push PDU with payload size zero\n"); } } -/* Demultiplexing of logical channels and dissassemble of MAC CE - * This function enqueues the packet and returns quicly because ACK - * deadline is important here. - */ +/* Demultiplexing of logical channels and dissassemble of MAC CE + * This function enqueues the packet and returns quickly because ACK + * deadline is important here. + */ void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { - return pdus.push(buff, nof_bytes, tstamp); + return pdus.push(buff, nof_bytes, srslte::pdu_queue::DCH, tstamp); } /* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through * the MAC in transparent mode. -* Warning: In this case function sends the message to RLC now, since SI blocks do not -* require ACK feedback to be transmitted quickly. */ void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { - rlc->write_pdu_bcch_dlsch(buff, nof_bytes); + pdus.push(buff, nof_bytes, srslte::pdu_queue::BCH, tstamp); +} + +void demux::push_pdu_mch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + pdus.push(buff, nof_bytes, srslte::pdu_queue::MCH, tstamp); } bool demux::process_pdus() @@ -135,15 +137,25 @@ bool demux::process_pdus() return pdus.process_pdus(); } -void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes, uint32_t tstamp) +void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp) { - // Unpack DLSCH MAC PDU - mac_msg.init_rx(nof_bytes); - mac_msg.parse_packet(mac_pdu); - - process_sch_pdu(&mac_msg); - //srslte_vec_fprint_byte(stdout, mac_pdu, nof_bytes); - Debug("MAC PDU processed\n"); + Debug("Processing MAC PDU channel %d\n", channel); + switch(channel) { + case srslte::pdu_queue::DCH: + // Unpack DLSCH MAC PDU + mac_msg.init_rx(nof_bytes); + mac_msg.parse_packet(mac_pdu); + + process_sch_pdu(&mac_msg); + //srslte_vec_fprint_byte(stdout, mac_pdu, nof_bytes); + break; + case srslte::pdu_queue::BCH: + rlc->write_pdu_bcch_dlsch(mac_pdu, nof_bytes); + break; + case srslte::pdu_queue::MCH: + // Process downlink MCH + break; + } } void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index ae975e1cc..8e9e60c4f 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -56,6 +56,7 @@ rrc::rrc() serving_cell = new cell_t(); neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); initiated = false; + running = false; } rrc::~rrc() @@ -139,10 +140,17 @@ void rrc::init(phy_interface_rrc *phy_, // set seed for rand (used in attach) srand(time(NULL)); + running = true; + start(); initiated = true; } void rrc::stop() { + running = false; + cmd_msg_t msg; + msg.command = cmd_msg_t::STOP; + cmd_q.push(msg); + wait_thread_finish(); } rrc_state_t rrc::get_state() { @@ -161,6 +169,23 @@ void rrc::set_args(rrc_args_t *args) { memcpy(&this->args, args, sizeof(rrc_args_t)); } +/* + * Low priority thread to run functions that can not be executed from main thread + */ +void rrc::run_thread() { + while(running) { + cmd_msg_t msg = cmd_q.wait_pop(); + switch(msg.command) { + case cmd_msg_t::STOP: + return; + case cmd_msg_t::PCCH: + process_pcch(msg.pdu); + break; + } + } +} + + /* * * RRC State Machine @@ -1639,6 +1664,13 @@ void rrc::handle_sib13() * *******************************************************************************/ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { + cmd_msg_t msg; + msg.pdu = pdu; + msg.command = cmd_msg_t::PCCH; + cmd_q.push(msg); +} + +void rrc::process_pcch(byte_buffer_t *pdu) { if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BITS) { rrc_log->info_hex(pdu->msg, pdu->N_bytes, "PCCH message received %d bytes\n", pdu->N_bytes); rrc_log->info("PCCH message Stack latency: %ld us\n", pdu->get_latency_us()); From 208871b251dcd95203225d287610780374093ddb Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 18:01:37 +0200 Subject: [PATCH 38/52] Changed liblte structs to simple structs and initialized nas/rrc uses. --- lib/include/srslte/asn1/liblte_common.h | 83 +-- lib/include/srslte/asn1/liblte_mme.h | 4 +- lib/include/srslte/asn1/liblte_rrc.h | 8 +- lib/src/asn1/liblte_mme.cc | 52 +- lib/src/asn1/liblte_rrc.cc | 8 +- lib/src/asn1/liblte_s1ap.cc | 842 ++++++++++++------------ srsepc/src/mme/s1ap_nas_transport.cc | 6 +- srsue/src/main.cc | 1 - srsue/src/upper/nas.cc | 29 +- srsue/src/upper/rrc.cc | 13 +- 10 files changed, 505 insertions(+), 541 deletions(-) diff --git a/lib/include/srslte/asn1/liblte_common.h b/lib/include/srslte/asn1/liblte_common.h index 21d962748..053f64d70 100644 --- a/lib/include/srslte/asn1/liblte_common.h +++ b/lib/include/srslte/asn1/liblte_common.h @@ -51,6 +51,8 @@ // FIXME: This was chosen arbitrarily #define LIBLTE_ASN1_OID_MAXSUBIDS 128 + +// Caution these values must match SRSLTE_ ones in common.h #define LIBLTE_MAX_MSG_SIZE_BITS 102048 #define LIBLTE_MAX_MSG_SIZE_BYTES 12756 #define LIBLTE_MSG_HEADER_OFFSET 1024 @@ -82,6 +84,8 @@ static const char liblte_error_text[LIBLTE_ERROR_N_ITEMS][64] = { "Decode failure", }; +#define LIBLTE_STRING_LEN 128 + typedef void* LIBLTE_ASN1_OPEN_TYPE_STRUCT; typedef struct { @@ -96,86 +100,15 @@ typedef struct{ typedef struct{ uint32 N_bits; + uint8 header[LIBLTE_MSG_HEADER_OFFSET]; uint8 msg[LIBLTE_MAX_MSG_SIZE_BITS]; -}LIBLTE_SIMPLE_BIT_MSG_STRUCT; +}LIBLTE_BIT_MSG_STRUCT; typedef struct{ uint32 N_bytes; + uint8 header[LIBLTE_MSG_HEADER_OFFSET]; uint8 msg[LIBLTE_MAX_MSG_SIZE_BYTES]; -}LIBLTE_SIMPLE_BYTE_MSG_STRUCT; - - -struct LIBLTE_BYTE_MSG_STRUCT{ - uint32 N_bytes; - uint8 buffer[LIBLTE_MAX_MSG_SIZE_BYTES]; - uint8 *msg; - - LIBLTE_BYTE_MSG_STRUCT():N_bytes(0) - { - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - } - LIBLTE_BYTE_MSG_STRUCT(const LIBLTE_BYTE_MSG_STRUCT& buf) - { - N_bytes = buf.N_bytes; - memcpy(msg, buf.msg, N_bytes); - } - LIBLTE_BYTE_MSG_STRUCT & operator= (const LIBLTE_BYTE_MSG_STRUCT & buf) - { - // avoid self assignment - if (&buf == this) - return *this; - N_bytes = buf.N_bytes; - memcpy(msg, buf.msg, N_bytes); - return *this; - } - uint32 get_headroom() - { - return msg-buffer; - } - void reset() - { - N_bytes = 0; - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - } -}; - -struct LIBLTE_BIT_MSG_STRUCT{ - uint32 N_bits; - uint8 buffer[LIBLTE_MAX_MSG_SIZE_BITS]; - uint8 *msg; - - LIBLTE_BIT_MSG_STRUCT():N_bits(0) - { - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - while( (uint64_t)(msg) % 8 > 0) { - msg++; - } - } - LIBLTE_BIT_MSG_STRUCT(const LIBLTE_BIT_MSG_STRUCT& buf){ - N_bits = buf.N_bits; - memcpy(msg, buf.msg, N_bits); - } - LIBLTE_BIT_MSG_STRUCT & operator= (const LIBLTE_BIT_MSG_STRUCT & buf){ - // avoid self assignment - if (&buf == this) - return *this; - N_bits = buf.N_bits; - memcpy(msg, buf.msg, N_bits); - return *this; - } - uint32 get_headroom() - { - return msg-buffer; - } - void reset() - { - N_bits = 0; - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - while( (uint64_t)(msg) % 8 > 0) { - msg++; - } - } -}; +}LIBLTE_BYTE_MSG_STRUCT; /******************************************************************************* diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 31b1a49df..4a168bca2 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -1209,7 +1209,7 @@ static const char liblte_mme_add_ci_text[LIBLTE_MME_ADD_CI_N_ITEMS][20] = {"Don' "Add"}; // Structs typedef struct{ - std::string name; + char name[LIBLTE_STRING_LEN]; LIBLTE_MME_ADD_CI_ENUM add_ci; }LIBLTE_MME_NETWORK_NAME_STRUCT; // Functions @@ -1752,7 +1752,7 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ // Enums // Structs typedef struct{ - std::string apn; + char apn[LIBLTE_STRING_LEN]; }LIBLTE_MME_ACCESS_POINT_NAME_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn, diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index 4fdff34e2..22038d130 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -5579,7 +5579,7 @@ static const char liblte_rrc_ul_information_transfer_type_text[LIBLTE_RRC_UL_INF "CDMA2000-HRPD"}; // Structs typedef struct{ - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_BYTE_MSG_STRUCT dedicated_info; LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; }LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT; // Functions @@ -5960,7 +5960,7 @@ typedef struct{ }LIBLTE_RRC_REGISTERED_MME_STRUCT; typedef struct{ LIBLTE_RRC_REGISTERED_MME_STRUCT registered_mme; - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info_nas; + LIBLTE_BYTE_MSG_STRUCT dedicated_info_nas; uint8 rrc_transaction_id; uint8 selected_plmn_id; bool registered_mme_present; @@ -6245,7 +6245,7 @@ typedef struct{ typedef struct{ LIBLTE_RRC_MEAS_CONFIG_STRUCT meas_cnfg; LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT mob_ctrl_info; - LIBLTE_SIMPLE_BYTE_MSG_STRUCT ded_info_nas_list[LIBLTE_RRC_MAX_DRB]; + LIBLTE_BYTE_MSG_STRUCT ded_info_nas_list[LIBLTE_RRC_MAX_DRB]; LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT rr_cnfg_ded; LIBLTE_RRC_SECURITY_CONFIG_HO_STRUCT sec_cnfg_ho; uint32 N_ded_info_nas; @@ -6626,7 +6626,7 @@ static const char liblte_rrc_dl_information_transfer_type_text[LIBLTE_RRC_DL_INF "CDMA2000-HRPD"}; // Structs typedef struct{ - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_BYTE_MSG_STRUCT dedicated_info; LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; uint8 rrc_transaction_id; }LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT; diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 6d9dedcdc..0425e8a35 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -2225,14 +2225,14 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_network_name_ie(LIBLTE_MME_NETWORK_NAME_STRUCT uint32 i; uint32 bit_offset; uint32 byte_offset; - const char *char_str = net_name->name.c_str(); + const char *char_str = net_name->name; if(net_name != NULL && ie_ptr != NULL) { bit_offset = 0; byte_offset = 2; - for(i=0; iname.size(); i++) + for(i=0; iname = ""; - while(byte_offset < N_bytes) + str_cnt = 0; + + while(byte_offset < N_bytes && str_cnt < LIBLTE_STRING_LEN) { switch(bit_offset) { @@ -2389,7 +2391,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 (tmp_char >= 0x61 && tmp_char <= 0x7A)) { - net_name->name += tmp_char; + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = tmp_char; + str_cnt++; + } } } @@ -2412,10 +2417,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 (tmp_char >= 0x61 && tmp_char <= 0x7A)) { - net_name->name += tmp_char; + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = tmp_char; + str_cnt++; + } } } + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = '\0'; + str_cnt++; + } + *ie_ptr += byte_offset + 1; err = LIBLTE_SUCCESS; @@ -3765,12 +3778,12 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_N if(apn != NULL && ie_ptr != NULL) { - apn_str = apn->apn.c_str(); - (*ie_ptr)[0] = apn->apn.length()+1; + apn_str = apn->apn; + (*ie_ptr)[0] = strnlen(apn->apn, LIBLTE_STRING_LEN)+1; len_idx = 0; apn_idx = 0; label_len = 0; - while(apn->apn.length() > apn_idx) + while(strnlen(apn->apn, LIBLTE_STRING_LEN) > apn_idx) { (*ie_ptr)[1+apn_idx+1] = (uint8)apn_str[apn_idx]; apn_idx++; @@ -3785,7 +3798,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_N } } (*ie_ptr)[1+len_idx] = label_len; - *ie_ptr += apn->apn.length() + 2; + *ie_ptr += strnlen(apn->apn, LIBLTE_STRING_LEN) + 2; err = LIBLTE_SUCCESS; } @@ -3799,26 +3812,31 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 uint32 i; uint32 ie_idx; uint32 label_len; + uint32 str_cnt; if(ie_ptr != NULL && apn != NULL) { - apn->apn.clear(); ie_idx = 0; - while(ie_idx < (*ie_ptr)[0]) + str_cnt = 0; + while(ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) { label_len = (*ie_ptr)[1+ie_idx]; - for(i=0; iapn += (char)((*ie_ptr)[1+ie_idx+i+1]); + apn->apn[str_cnt] = (char)((*ie_ptr)[1+ie_idx+i+1]); + str_cnt++; } ie_idx += label_len + 1; - if(ie_idx < (*ie_ptr)[0]) + if(ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) { - apn->apn += '.'; + apn->apn[str_cnt] = '.'; + str_cnt++; } } - apn->apn += "\0"; + if (str_cnt < LIBLTE_STRING_LEN) { + apn->apn[str_cnt] = '\0'; + } *ie_ptr += (*ie_ptr)[0] + 1; err = LIBLTE_SUCCESS; diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index 60bf992b6..8e489cd9f 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -380,7 +380,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000, +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000, uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -412,7 +412,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_SIMPLE_BYTE_ return(err); } LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, - LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000) + LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -452,7 +452,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas, +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_nas, uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -484,7 +484,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_SIMPLE_BYTE_MSG_S return(err); } LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_nas_ie(uint8 **ie_ptr, - LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas) + LIBLTE_BYTE_MSG_STRUCT *ded_info_nas) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; diff --git a/lib/src/asn1/liblte_s1ap.cc b/lib/src/asn1/liblte_s1ap.cc index e6a8fe575..0a589e709 100644 --- a/lib/src/asn1/liblte_s1ap.cc +++ b/lib/src/asn1/liblte_s1ap.cc @@ -12586,7 +12586,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabinformationlistitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -14074,7 +14074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rablist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -15610,7 +15610,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransferlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -18814,7 +18814,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistres( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -18900,7 +18900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19110,7 +19110,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsubjecttodataforwardinglist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabdataforwardingitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19196,7 +19196,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplisthoreq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19282,7 +19282,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmittedlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmitteditem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19368,7 +19368,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddllist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19454,7 +19454,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedullist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19540,7 +19540,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistbearersureq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19626,7 +19626,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistbearersures( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitembearersures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19712,7 +19712,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19798,7 +19798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifylistbearermodres( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19884,7 +19884,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaselistbearerrelcomp( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19970,7 +19970,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistctxtsureq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20056,7 +20056,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistctxtsures( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20142,7 +20142,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_taiitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20228,7 +20228,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24400,7 +24400,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_totargetenb_transparentcontainer_ex // ProtocolIE - MobilityInformation if(msg->MobilityInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mobilityinformation(&msg->MobilityInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24500,7 +24500,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist( uint8_t *tmp_ptr; // ProtocolIE - E_RABInformationListItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabinformationlistitem(&msg->E_RABInformationListItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24602,7 +24602,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation_ext( // ProtocolIE - Time_UE_StayedInCell_EnhancedGranularity if(msg->Time_UE_StayedInCell_EnhancedGranularity_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_time_ue_stayedincell_enhancedgranularity(&msg->Time_UE_StayedInCell_EnhancedGranularity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24621,7 +24621,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation_ext( // ProtocolIE - HO_Cause if(msg->HO_Cause_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->HO_Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24731,7 +24731,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformationreply_ext( // ProtocolIE - Time_Synchronization_Info if(msg->Time_Synchronization_Info_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timesynchronizationinfo(&msg->Time_Synchronization_Info, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24838,7 +24838,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - ULCOUNTValueExtended if(msg->ULCOUNTValueExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_countvalueextended(&msg->ULCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24857,7 +24857,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - DLCOUNTValueExtended if(msg->DLCOUNTValueExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_countvalueextended(&msg->DLCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24876,7 +24876,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - ReceiveStatusOfULPDCPSDUsExtended if(msg->ReceiveStatusOfULPDCPSDUsExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_receivestatusofulpdcpsdusextended(&msg->ReceiveStatusOfULPDCPSDUsExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24990,7 +24990,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabitem(&msg->E_RABItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25090,7 +25090,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_configuration_ext( // ProtocolIE - SignallingBasedMDTPLMNList if(msg->SignallingBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->SignallingBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25193,7 +25193,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_x2tnlconfigurationinfo_ext( // ProtocolIE - eNBX2ExtendedTransportLayerAddresses if(msg->eNBX2ExtendedTransportLayerAddresses_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbx2exttlas(&msg->eNBX2ExtendedTransportLayerAddresses, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25293,7 +25293,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_item( uint8_t *tmp_ptr; // ProtocolIE - Bearers_SubjectToStatusTransfer_Item - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&msg->Bearers_SubjectToStatusTransfer_Item, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25399,7 +25399,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M3Configuration if(msg->M3Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m3configuration(&msg->M3Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25418,7 +25418,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M4Configuration if(msg->M4Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m4configuration(&msg->M4Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25437,7 +25437,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M5Configuration if(msg->M5Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m5configuration(&msg->M5Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25456,7 +25456,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - MDT_Location_Info if(msg->MDT_Location_Info_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdt_location_info(&msg->MDT_Location_Info, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25577,7 +25577,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_sonconfigurationtransfer_ext( // ProtocolIE - x2TNLConfigurationInfo if(msg->x2TNLConfigurationInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_x2tnlconfigurationinfo(&msg->x2TNLConfigurationInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25679,7 +25679,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_traceactivation_ext( // ProtocolIE - MDTConfiguration if(msg->MDTConfiguration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdt_configuration(&msg->MDTConfiguration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25795,7 +25795,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25812,7 +25812,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25829,7 +25829,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25846,7 +25846,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25863,7 +25863,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - TargetID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_targetid(&msg->TargetID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25881,7 +25881,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - Direct_Forwarding_Path_Availability if(msg->Direct_Forwarding_Path_Availability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_direct_forwarding_path_availability(&msg->Direct_Forwarding_Path_Availability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25900,7 +25900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - SRVCCHOIndication if(msg->SRVCCHOIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvcchoindication(&msg->SRVCCHOIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25918,7 +25918,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( } // ProtocolIE - Source_ToTarget_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25936,7 +25936,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - Source_ToTarget_TransparentContainer_Secondary if(msg->Source_ToTarget_TransparentContainer_Secondary_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25955,7 +25955,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - MSClassmark2 if(msg->MSClassmark2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_msclassmark2(&msg->MSClassmark2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25974,7 +25974,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - MSClassmark3 if(msg->MSClassmark3_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_msclassmark3(&msg->MSClassmark3, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25993,7 +25993,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26012,7 +26012,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26031,7 +26031,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - PS_ServiceNotAvailable if(msg->PS_ServiceNotAvailable_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ps_servicenotavailable(&msg->PS_ServiceNotAvailable, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26278,7 +26278,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26295,7 +26295,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26312,7 +26312,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26330,7 +26330,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26448,7 +26448,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq_ext( // ProtocolIE - Data_Forwarding_Not_Possible if(msg->Data_Forwarding_Not_Possible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_data_forwarding_not_possible(&msg->Data_Forwarding_Not_Possible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26686,7 +26686,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26703,7 +26703,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26721,7 +26721,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26835,7 +26835,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26852,7 +26852,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26869,7 +26869,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26886,7 +26886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26904,7 +26904,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26923,7 +26923,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27188,7 +27188,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27205,7 +27205,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27222,7 +27222,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27240,7 +27240,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27355,7 +27355,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27372,7 +27372,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27389,7 +27389,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27498,7 +27498,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27515,7 +27515,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27533,7 +27533,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27648,7 +27648,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureqext( // ProtocolIE - Correlation_ID if(msg->Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27667,7 +27667,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureqext( // ProtocolIE - SIPTO_Correlation_ID if(msg->SIPTO_Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27845,7 +27845,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifyitembearermodreqext( // ProtocolIE - TransportInformation if(msg->TransportInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportinformation(&msg->TransportInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28017,7 +28017,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28034,7 +28034,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28052,7 +28052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28070,7 +28070,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( } // ProtocolIE - E_RABToBeReleasedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28088,7 +28088,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( // ProtocolIE - NAS_PDU if(msg->NAS_PDU_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28280,7 +28280,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28297,7 +28297,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28314,7 +28314,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABReleasedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28332,7 +28332,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28452,7 +28452,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureqext( // ProtocolIE - Correlation_ID if(msg->Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28471,7 +28471,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureqext( // ProtocolIE - SIPTO_Correlation_ID if(msg->SIPTO_Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28648,7 +28648,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28665,7 +28665,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28682,7 +28682,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28700,7 +28700,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28885,7 +28885,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28902,7 +28902,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28919,7 +28919,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28937,7 +28937,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( // ProtocolIE - GWContextReleaseIndication if(msg->GWContextReleaseIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gwcontextreleaseindication(&msg->GWContextReleaseIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29052,7 +29052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecommand( uint8_t *tmp_ptr; // ProtocolIE - UE_S1AP_IDs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_s1ap_ids(&msg->UE_S1AP_IDs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29069,7 +29069,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecommand( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29175,7 +29175,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29192,7 +29192,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29210,7 +29210,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29229,7 +29229,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29362,7 +29362,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29379,7 +29379,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29397,7 +29397,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - SecurityKey if(msg->SecurityKey_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29416,7 +29416,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29435,7 +29435,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29454,7 +29454,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - CSFallbackIndicator if(msg->CSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29473,7 +29473,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - UESecurityCapabilities if(msg->UESecurityCapabilities_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29492,7 +29492,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29511,7 +29511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - RegisteredLAI if(msg->RegisteredLAI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29530,7 +29530,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - AdditionalCSFallbackIndicator if(msg->AdditionalCSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29690,7 +29690,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29707,7 +29707,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29725,7 +29725,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29837,7 +29837,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29854,7 +29854,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29871,7 +29871,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29889,7 +29889,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30006,7 +30006,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30023,7 +30023,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30041,7 +30041,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( // ProtocolIE - UERadioCapability if(msg->UERadioCapability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30153,7 +30153,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30170,7 +30170,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30187,7 +30187,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - VoiceSupportMatchIndicator - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_voicesupportmatchindicator(&msg->VoiceSupportMatchIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30205,7 +30205,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30324,7 +30324,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30341,7 +30341,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30358,7 +30358,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30376,7 +30376,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30395,7 +30395,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30537,7 +30537,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( uint8_t *tmp_ptr; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30554,7 +30554,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30571,7 +30571,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30588,7 +30588,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30605,7 +30605,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - RRC_Establishment_Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_rrc_establishment_cause(&msg->RRC_Establishment_Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30623,7 +30623,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - S_TMSI if(msg->S_TMSI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_s_tmsi(&msg->S_TMSI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30642,7 +30642,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30661,7 +30661,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30680,7 +30680,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30699,7 +30699,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GW_TransportLayerAddress if(msg->GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30718,7 +30718,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - RelayNode_Indicator if(msg->RelayNode_Indicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relaynode_indicator(&msg->RelayNode_Indicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30737,7 +30737,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GUMMEIType if(msg->GUMMEIType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeitype(&msg->GUMMEIType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30756,7 +30756,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30775,7 +30775,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - SIPTO_L_GW_TransportLayerAddress if(msg->SIPTO_L_GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30794,7 +30794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30988,7 +30988,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31005,7 +31005,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31022,7 +31022,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31039,7 +31039,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31056,7 +31056,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31074,7 +31074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - GW_TransportLayerAddress if(msg->GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31093,7 +31093,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - SIPTO_L_GW_TransportLayerAddress if(msg->SIPTO_L_GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31112,7 +31112,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31251,7 +31251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31268,7 +31268,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31285,7 +31285,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31302,7 +31302,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31414,7 +31414,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitem( uint8_t *tmp_ptr; // ProtocolIE - UE_associatedLogicalS1_ConnectionItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31511,7 +31511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitemres( uint8_t *tmp_ptr; // ProtocolIE - UE_associatedLogicalS1_ConnectionItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31617,7 +31617,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - MME_UE_S1AP_ID if(msg->MME_UE_S1AP_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31636,7 +31636,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - eNB_UE_S1AP_ID if(msg->eNB_UE_S1AP_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31655,7 +31655,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - Cause if(msg->Cause_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31674,7 +31674,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31799,7 +31799,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( uint8_t *tmp_ptr; // ProtocolIE - Global_ENB_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31817,7 +31817,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( // ProtocolIE - eNBname if(msg->eNBname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31835,7 +31835,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( } // ProtocolIE - SupportedTAs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31852,7 +31852,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - DefaultPagingDRX - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31870,7 +31870,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31999,7 +31999,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - MMEname if(msg->MMEname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32017,7 +32017,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( } // ProtocolIE - ServedGUMMEIs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32034,7 +32034,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - RelativeMMECapacity - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32052,7 +32052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - MMERelaySupportIndicator if(msg->MMERelaySupportIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmerelaysupportindicator(&msg->MMERelaySupportIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32071,7 +32071,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32199,7 +32199,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32217,7 +32217,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32236,7 +32236,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32357,7 +32357,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - eNBname if(msg->eNBname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32376,7 +32376,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - SupportedTAs if(msg->SupportedTAs_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32395,7 +32395,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32414,7 +32414,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - DefaultPagingDRX if(msg->DefaultPagingDRX_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32538,7 +32538,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdateacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32642,7 +32642,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32660,7 +32660,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32679,7 +32679,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32798,7 +32798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - MMEname if(msg->MMEname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32817,7 +32817,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - ServedGUMMEIs if(msg->ServedGUMMEIs_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32836,7 +32836,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - RelativeMMECapacity if(msg->RelativeMMECapacity_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32953,7 +32953,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdateacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33057,7 +33057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33075,7 +33075,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33094,7 +33094,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33214,7 +33214,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33231,7 +33231,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33248,7 +33248,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000RATType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33265,7 +33265,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000SectorID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000sectorid(&msg->cdma2000SectorID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33283,7 +33283,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000HORequiredIndication if(msg->cdma2000HORequiredIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000horequiredindication(&msg->cdma2000HORequiredIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33302,7 +33302,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000OneXSRVCCInfo if(msg->cdma2000OneXSRVCCInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000onexsrvccinfo(&msg->cdma2000OneXSRVCCInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33321,7 +33321,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000OneXRAND if(msg->cdma2000OneXRAND_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000onexrand(&msg->cdma2000OneXRAND, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33339,7 +33339,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( } // ProtocolIE - cdma2000PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33357,7 +33357,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - EUTRANRoundTripDelayEstimationInfo if(msg->EUTRANRoundTripDelayEstimationInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutranroundtripdelayestimationinfo(&msg->EUTRANRoundTripDelayEstimationInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33503,7 +33503,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33520,7 +33520,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33537,7 +33537,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( *ptr += tmp_msg.N_bits; // ProtocolIE - UERadioCapability - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33644,7 +33644,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33661,7 +33661,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33678,7 +33678,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_StatusTransfer_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33785,7 +33785,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33802,7 +33802,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33819,7 +33819,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_StatusTransfer_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33926,7 +33926,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33943,7 +33943,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33960,7 +33960,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( *ptr += tmp_msg.N_bits; // ProtocolIE - TraceActivation - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34067,7 +34067,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34084,7 +34084,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34101,7 +34101,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34118,7 +34118,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34230,7 +34230,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34247,7 +34247,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34264,7 +34264,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34373,7 +34373,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34390,7 +34390,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34407,7 +34407,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34424,7 +34424,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34441,7 +34441,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - TraceCollectionEntityIPAddress - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->TraceCollectionEntityIPAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34459,7 +34459,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( // ProtocolIE - PrivacyIndicator if(msg->PrivacyIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_privacyindicator(&msg->PrivacyIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34584,7 +34584,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34601,7 +34601,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34618,7 +34618,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( *ptr += tmp_msg.N_bits; // ProtocolIE - RequestType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34725,7 +34725,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34742,7 +34742,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34759,7 +34759,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34866,7 +34866,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34883,7 +34883,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34900,7 +34900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34917,7 +34917,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34934,7 +34934,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - RequestType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35055,7 +35055,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( uint8_t *tmp_ptr; // ProtocolIE - OverloadResponse - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_overloadresponse(&msg->OverloadResponse, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35073,7 +35073,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( // ProtocolIE - GUMMEIList if(msg->GUMMEIList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35092,7 +35092,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( // ProtocolIE - TrafficLoadReductionIndication if(msg->TrafficLoadReductionIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_trafficloadreductionindication(&msg->TrafficLoadReductionIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35207,7 +35207,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstop( // ProtocolIE - GUMMEIList if(msg->GUMMEIList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35321,7 +35321,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35338,7 +35338,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35356,7 +35356,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningAreaList if(msg->WarningAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35374,7 +35374,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( } // ProtocolIE - RepetitionPeriod - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_repetitionperiod(&msg->RepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35392,7 +35392,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - ExtendedRepetitionPeriod if(msg->ExtendedRepetitionPeriod_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_extendedrepetitionperiod(&msg->ExtendedRepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35410,7 +35410,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( } // ProtocolIE - NumberofBroadcastRequest - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_numberofbroadcastrequest(&msg->NumberofBroadcastRequest, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35428,7 +35428,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningType if(msg->WarningType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningtype(&msg->WarningType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35447,7 +35447,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningSecurityInfo if(msg->WarningSecurityInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningsecurityinfo(&msg->WarningSecurityInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35466,7 +35466,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - DataCodingScheme if(msg->DataCodingScheme_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_datacodingscheme(&msg->DataCodingScheme, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35485,7 +35485,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningMessageContents if(msg->WarningMessageContents_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningmessagecontents(&msg->WarningMessageContents, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35504,7 +35504,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - ConcurrentWarningMessageIndicator if(msg->ConcurrentWarningMessageIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_concurrentwarningmessageindicator(&msg->ConcurrentWarningMessageIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35670,7 +35670,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35687,7 +35687,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35705,7 +35705,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( // ProtocolIE - BroadcastCompletedAreaList if(msg->BroadcastCompletedAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_broadcastcompletedarealist(&msg->BroadcastCompletedAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35724,7 +35724,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35841,7 +35841,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmedirectinformationtransfer( uint8_t *tmp_ptr; // ProtocolIE - Inter_SystemInformationTransferTypeMDT - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeMDT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35941,7 +35941,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationtransfer( // ProtocolIE - SONConfigurationTransferECT if(msg->SONConfigurationTransferECT_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferECT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36044,7 +36044,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationtransfer( // ProtocolIE - SONConfigurationTransferMCT if(msg->SONConfigurationTransferMCT_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferMCT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36216,7 +36216,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36233,7 +36233,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36251,7 +36251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( // ProtocolIE - WarningAreaList if(msg->WarningAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36270,7 +36270,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( // ProtocolIE - KillAllWarningMessages if(msg->KillAllWarningMessages_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_killallwarningmessages(&msg->KillAllWarningMessages, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36391,7 +36391,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36408,7 +36408,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36426,7 +36426,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( // ProtocolIE - BroadcastCancelledAreaList if(msg->BroadcastCancelledAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_broadcastcancelledarealist(&msg->BroadcastCancelledAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36445,7 +36445,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36564,7 +36564,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( uint8_t *tmp_ptr; // ProtocolIE - ECGIListForRestart - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ecgilistforrestart(&msg->ECGIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36581,7 +36581,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Global_ENB_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36598,7 +36598,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( *ptr += tmp_msg.N_bits; // ProtocolIE - TAIListForRestart - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tailistforrestart(&msg->TAIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36616,7 +36616,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( // ProtocolIE - EmergencyAreaIDListForRestart if(msg->EmergencyAreaIDListForRestart_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_emergencyareaidlistforrestart(&msg->EmergencyAreaIDListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36731,7 +36731,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36748,7 +36748,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36765,7 +36765,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36782,7 +36782,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36894,7 +36894,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36911,7 +36911,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36928,7 +36928,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36945,7 +36945,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37057,7 +37057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknonueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37074,7 +37074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknonueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37176,7 +37176,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknonueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37193,7 +37193,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknonueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37295,7 +37295,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbdirectinformationtransfer( uint8_t *tmp_ptr; // ProtocolIE - Inter_SystemInformationTransferTypeEDT - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeEDT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37392,7 +37392,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabdataforwardingitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABDataForwardingItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabdataforwardingitem(&msg->E_RABDataForwardingItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37489,7 +37489,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemHOReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&msg->E_RABToBeSetupItemHOReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37586,7 +37586,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmitteditem( uint8_t *tmp_ptr; // ProtocolIE - E_RABAdmittedItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmitteditem(&msg->E_RABAdmittedItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37683,7 +37683,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack( uint8_t *tmp_ptr; // ProtocolIE - E_RABFailedtoSetupItemHOReqAck - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&msg->E_RABFailedtoSetupItemHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37780,7 +37780,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddlitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSwitchedDLItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&msg->E_RABToBeSwitchedDLItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37877,7 +37877,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedulitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSwitchedULItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&msg->E_RABToBeSwitchedULItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37974,7 +37974,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemBearerSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&msg->E_RABToBeSetupItemBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38071,7 +38071,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitembearersures( uint8_t *tmp_ptr; // ProtocolIE - E_RABSetupItemBearerSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitembearersures(&msg->E_RABSetupItemBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38168,7 +38168,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifieditembearermodreq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeModifiedItemBearerModReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&msg->E_RABToBeModifiedItemBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38265,7 +38265,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyitembearermodres( uint8_t *tmp_ptr; // ProtocolIE - E_RABModifyItemBearerModRes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&msg->E_RABModifyItemBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38362,7 +38362,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseitembearerrelcomp( uint8_t *tmp_ptr; // ProtocolIE - E_RABReleaseItemBearerRelComp - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&msg->E_RABReleaseItemBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38459,7 +38459,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemCtxtSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&msg->E_RABToBeSetupItemCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38556,7 +38556,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitemctxtsures( uint8_t *tmp_ptr; // ProtocolIE - E_RABSetupItemCtxtSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&msg->E_RABSetupItemCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38653,7 +38653,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_taiitem( uint8_t *tmp_ptr; // ProtocolIE - TAIItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_taiitem(&msg->TAIItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38755,7 +38755,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetacknowledge( // ProtocolIE - UE_associatedLogicalS1_ConnectionListResAck if(msg->UE_associatedLogicalS1_ConnectionListResAck_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack(&msg->UE_associatedLogicalS1_ConnectionListResAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38774,7 +38774,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38881,7 +38881,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_reset( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38898,7 +38898,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_reset( *ptr += tmp_msg.N_bits; // ProtocolIE - ResetType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_resettype(&msg->ResetType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39004,7 +39004,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39021,7 +39021,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39039,7 +39039,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( // ProtocolIE - E_RABSubjecttoDataForwardingList if(msg->E_RABSubjecttoDataForwardingList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39058,7 +39058,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( // ProtocolIE - cdma2000HOStatus if(msg->cdma2000HOStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000hostatus(&msg->cdma2000HOStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39076,7 +39076,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( } // ProtocolIE - cdma2000RATType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39093,7 +39093,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39229,7 +39229,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39246,7 +39246,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39263,7 +39263,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39281,7 +39281,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - NASSecurityParametersfromE_UTRAN if(msg->NASSecurityParametersfromE_UTRAN_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nassecurityparametersfrome_utran(&msg->NASSecurityParametersfromE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39300,7 +39300,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - E_RABSubjecttoDataForwardingList if(msg->E_RABSubjecttoDataForwardingList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39319,7 +39319,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - E_RABtoReleaseListHOCmd if(msg->E_RABtoReleaseListHOCmd_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABtoReleaseListHOCmd, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39337,7 +39337,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( } // ProtocolIE - Target_ToSource_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39355,7 +39355,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - Target_ToSource_TransparentContainer_Secondary if(msg->Target_ToSource_TransparentContainer_Secondary_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39374,7 +39374,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39543,7 +39543,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39560,7 +39560,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39577,7 +39577,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39594,7 +39594,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - uEaggregateMaximumBitrate - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39611,7 +39611,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSetupListHOReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplisthoreq(&msg->E_RABToBeSetupListHOReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39628,7 +39628,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Source_ToTarget_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39645,7 +39645,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39663,7 +39663,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39682,7 +39682,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - TraceActivation if(msg->TraceActivation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39701,7 +39701,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - RequestType if(msg->RequestType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39720,7 +39720,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - SRVCCOperationPossible if(msg->SRVCCOperationPossible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39738,7 +39738,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( } // ProtocolIE - SecurityContext - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39756,7 +39756,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - NASSecurityParameterstoE_UTRAN if(msg->NASSecurityParameterstoE_UTRAN_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nassecurityparameterstoe_utran(&msg->NASSecurityParameterstoE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39775,7 +39775,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39794,7 +39794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39813,7 +39813,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39832,7 +39832,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39851,7 +39851,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - ManagementBasedMDTAllowed if(msg->ManagementBasedMDTAllowed_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39870,7 +39870,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - ManagementBasedMDTPLMNList if(msg->ManagementBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40091,7 +40091,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( uint8_t *tmp_ptr; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40108,7 +40108,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSwitchedDLList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddllist(&msg->E_RABToBeSwitchedDLList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40125,7 +40125,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SourceMME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->SourceMME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40142,7 +40142,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40159,7 +40159,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40176,7 +40176,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40194,7 +40194,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40213,7 +40213,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40232,7 +40232,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - SourceMME_GUMMEI if(msg->SourceMME_GUMMEI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->SourceMME_GUMMEI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40251,7 +40251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40270,7 +40270,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40289,7 +40289,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40466,7 +40466,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40483,7 +40483,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40501,7 +40501,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40520,7 +40520,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - E_RABToBeSwitchedULList if(msg->E_RABToBeSwitchedULList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedullist(&msg->E_RABToBeSwitchedULList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40539,7 +40539,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - E_RABToBeReleasedList if(msg->E_RABToBeReleasedList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40557,7 +40557,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( } // ProtocolIE - SecurityContext - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40575,7 +40575,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40594,7 +40594,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40613,7 +40613,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40765,7 +40765,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40782,7 +40782,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40800,7 +40800,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40818,7 +40818,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( } // ProtocolIE - E_RABToBeSetupListBearerSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplistbearersureq(&msg->E_RABToBeSetupListBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40938,7 +40938,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40955,7 +40955,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40973,7 +40973,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - E_RABSetupListBearerSURes if(msg->E_RABSetupListBearerSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetuplistbearersures(&msg->E_RABSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40992,7 +40992,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - E_RABFailedToSetupListBearerSURes if(msg->E_RABFailedToSetupListBearerSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41011,7 +41011,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41137,7 +41137,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41154,7 +41154,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41172,7 +41172,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41190,7 +41190,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( } // ProtocolIE - E_RABToBeModifiedListBearerModReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq(&msg->E_RABToBeModifiedListBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41310,7 +41310,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41327,7 +41327,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41345,7 +41345,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - E_RABModifyListBearerModRes if(msg->E_RABModifyListBearerModRes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifylistbearermodres(&msg->E_RABModifyListBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41364,7 +41364,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - E_RABFailedToModifyList if(msg->E_RABFailedToModifyList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToModifyList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41383,7 +41383,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41515,7 +41515,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41532,7 +41532,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41550,7 +41550,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - E_RABReleaseListBearerRelComp if(msg->E_RABReleaseListBearerRelComp_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaselistbearerrelcomp(&msg->E_RABReleaseListBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41569,7 +41569,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - E_RABFailedToReleaseList if(msg->E_RABFailedToReleaseList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToReleaseList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41588,7 +41588,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41607,7 +41607,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41764,7 +41764,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41781,7 +41781,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41798,7 +41798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - uEaggregateMaximumBitrate - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41815,7 +41815,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSetupListCtxtSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplistctxtsureq(&msg->E_RABToBeSetupListCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41832,7 +41832,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41849,7 +41849,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SecurityKey - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41867,7 +41867,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - TraceActivation if(msg->TraceActivation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41886,7 +41886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41905,7 +41905,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - UERadioCapability if(msg->UERadioCapability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41924,7 +41924,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41943,7 +41943,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - CSFallbackIndicator if(msg->CSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41962,7 +41962,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - SRVCCOperationPossible if(msg->SRVCCOperationPossible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41981,7 +41981,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42000,7 +42000,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - RegisteredLAI if(msg->RegisteredLAI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42019,7 +42019,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42038,7 +42038,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42057,7 +42057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - ManagementBasedMDTAllowed if(msg->ManagementBasedMDTAllowed_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42076,7 +42076,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - ManagementBasedMDTPLMNList if(msg->ManagementBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42095,7 +42095,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - AdditionalCSFallbackIndicator if(msg->AdditionalCSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42312,7 +42312,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42329,7 +42329,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42346,7 +42346,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABSetupListCtxtSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetuplistctxtsures(&msg->E_RABSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42364,7 +42364,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( // ProtocolIE - E_RABFailedToSetupListCtxtSURes if(msg->E_RABFailedToSetupListCtxtSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42383,7 +42383,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42511,7 +42511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( uint8_t *tmp_ptr; // ProtocolIE - UEIdentityIndexValue - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueidentityindexvalue(&msg->UEIdentityIndexValue, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42528,7 +42528,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( *ptr += tmp_msg.N_bits; // ProtocolIE - UEPagingID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uepagingid(&msg->UEPagingID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42546,7 +42546,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - pagingDRX if(msg->pagingDRX_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->pagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42564,7 +42564,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( } // ProtocolIE - CNDomain - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cndomain(&msg->CNDomain, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42581,7 +42581,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( *ptr += tmp_msg.N_bits; // ProtocolIE - TAIList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tailist(&msg->TAIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42599,7 +42599,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42618,7 +42618,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - PagingPriority if(msg->PagingPriority_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingpriority(&msg->PagingPriority, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42760,7 +42760,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42777,7 +42777,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42794,7 +42794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABAdmittedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmittedlist(&msg->E_RABAdmittedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42812,7 +42812,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - E_RABFailedToSetupListHOReqAck if(msg->E_RABFailedToSetupListHOReqAck_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack(&msg->E_RABFailedToSetupListHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42830,7 +42830,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( } // ProtocolIE - Target_ToSource_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42848,7 +42848,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42867,7 +42867,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42886,7 +42886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 687ced63b..32964daff 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -1806,7 +1806,7 @@ s1ap_nas_transport::pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *u act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check //set apn - act_def_eps_bearer_context_req.apn.apn = m_s1ap->m_s1ap_args.mme_apn; + strncpy(act_def_eps_bearer_context_req.apn.apn, m_s1ap->m_s1ap_args.mme_apn.c_str(), LIBLTE_STRING_LEN); act_def_eps_bearer_context_req.proc_transaction_id = ue_emm_ctx->procedure_transaction_id; //FIXME //Set DNS server @@ -1933,10 +1933,10 @@ s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_ LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; emm_info.full_net_name_present = true; - emm_info.full_net_name.name = std::string("Software Radio Systems LTE"); + strncpy(emm_info.full_net_name.name, "Software Radio Systems LTE", LIBLTE_STRING_LEN); emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.short_net_name_present = true; - emm_info.short_net_name.name = std::string("srsLTE"); + strncpy(emm_info.short_net_name.name, "srsLTE", LIBLTE_STRING_LEN); emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.local_time_zone_present = false; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index afb7a1f8b..6a1c8af1d 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -477,7 +477,6 @@ int main(int argc, char *argv[]) printf("Attaching UE...\n"); while (!ue->attach() && running) { sleep(1); - printf("Could not attach. Trying again...\n"); } if (running) { if (args.expert.pregenerate_signals) { diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 243d58177..291a3550f 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -546,10 +546,10 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { return; } - LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; - LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete; - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept; + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept = {0}; + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete = {0}; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req = {0}; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept = {0}; nas_log->info("Received Attach Accept\n"); @@ -588,7 +588,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[3]; nas_log->info("Network attach successful. APN: %s, IP: %u.%u.%u.%u\n", - act_def_eps_bearer_context_req.apn.apn.c_str(), + act_def_eps_bearer_context_req.apn.apn, act_def_eps_bearer_context_req.pdn_addr.addr[0], act_def_eps_bearer_context_req.pdn_addr.addr[1], act_def_eps_bearer_context_req.pdn_addr.addr[2], @@ -674,7 +674,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { } void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) { - LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej; + LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej = {0}; liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_rej); nas_log->warning("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause); @@ -686,7 +686,9 @@ void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) { void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; + bzero(&auth_req, sizeof(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT)); LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res; + bzero(&auth_res, sizeof(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT)); nas_log->info("Received Authentication Request\n"); liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &auth_req); @@ -741,8 +743,8 @@ void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) { } void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) { - LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; - LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req = {0}; + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp = {0}; liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &id_req); nas_log->info("Received Identity Request. ID type: %d\n", id_req.id_type); @@ -786,7 +788,9 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) } LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd; + bzero(&sec_mode_cmd, sizeof(LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT)); LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp; + bzero(&sec_mode_comp, sizeof(LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT)); liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &sec_mode_cmd); nas_log->info("Received Security Mode Command ksi: %d, eea: %s, eia: %s\n", @@ -919,6 +923,7 @@ void nas::gen_attach_request(byte_buffer_t *msg) { return; } LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + bzero(&attach_req, sizeof(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT)); nas_log->info("Generating attach request\n"); @@ -1029,7 +1034,7 @@ void nas::gen_service_request(byte_buffer_t *msg) { } void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { - LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req = {0}; nas_log->info("Generating PDN Connectivity Request\n"); @@ -1045,8 +1050,8 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { pdn_con_req.apn_present = false; } else { pdn_con_req.apn_present = true; - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; - apn.apn = cfg.apn; + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn = {0}; + strncpy(apn.apn, cfg.apn.c_str(), LIBLTE_STRING_LEN); pdn_con_req.apn = apn; } pdn_con_req.protocol_cnfg_opts_present = false; @@ -1063,7 +1068,7 @@ void nas::send_security_mode_reject(uint8_t cause) { return; } - LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej = {0}; sec_mode_rej.emm_cause = cause; liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg); if(pcap != NULL) { diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 8e9e60c4f..3f213979d 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1116,6 +1116,7 @@ void rrc::timer_expired(uint32_t timeout_id) { void rrc::send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause) { rrc_log->debug("Preparing RRC Connection Request\n"); + bzero(&ul_ccch_msg, sizeof(LIBLTE_RRC_UL_CCCH_MSG_STRUCT)); // Prepare ConnectionRequest packet ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; @@ -1142,6 +1143,7 @@ void rrc::send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause) { /* RRC connection re-establishment procedure (5.3.7) */ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause) { + bzero(&ul_ccch_msg, sizeof(LIBLTE_RRC_UL_CCCH_MSG_STRUCT)); uint16_t crnti; if (cause == LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE) { @@ -1239,6 +1241,8 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause) } void rrc::send_con_restablish_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); + rrc_log->debug("Preparing RRC Connection Reestablishment Complete\n"); rrc_log->console("RRC Connected\n"); @@ -1251,6 +1255,7 @@ void rrc::send_con_restablish_complete() { } void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing RRC Connection Setup Complete\n"); // Prepare ConnectionSetupComplete packet @@ -1267,6 +1272,8 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { } void rrc::send_ul_info_transfer(byte_buffer_t *nas_msg) { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); + rrc_log->debug("Preparing RX Info Transfer\n"); // Prepare RX INFO packet @@ -1281,6 +1288,7 @@ void rrc::send_ul_info_transfer(byte_buffer_t *nas_msg) { } void rrc::send_security_mode_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing Security Mode Complete\n"); ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE; @@ -1290,6 +1298,7 @@ void rrc::send_security_mode_complete() { } void rrc::send_rrc_con_reconfig_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing RRC Connection Reconfig Complete\n"); ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE; @@ -1561,7 +1570,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { 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()); - LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg; + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg = {0}; srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8); bit_buf.N_bits = pdu->N_bytes * 8; pool->deallocate(pdu); @@ -1676,7 +1685,7 @@ void rrc::process_pcch(byte_buffer_t *pdu) { rrc_log->info("PCCH message Stack latency: %ld us\n", pdu->get_latency_us()); rrc_log->console("PCCH message received %d bytes\n", pdu->N_bytes); - LIBLTE_RRC_PCCH_MSG_STRUCT pcch_msg; + LIBLTE_RRC_PCCH_MSG_STRUCT pcch_msg = {0}; srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8); bit_buf.N_bits = pdu->N_bytes * 8; pool->deallocate(pdu); From 49c0455b4af91451352da5b22627c495578d9205 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 18:08:24 +0200 Subject: [PATCH 39/52] Expose print buffer state option to ue.conf and disable by default --- srsue/hdr/ue_base.h | 1 + srsue/src/main.cc | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index e3acf4cff..547aefee8 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -112,6 +112,7 @@ typedef struct { phy_args_t phy; float metrics_period_secs; bool pregenerate_signals; + bool print_buffer_state; bool metrics_csv_enable; std::string metrics_csv_filename; }expert_args_t; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 6a1c8af1d..f155c0a98 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -159,6 +159,10 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.pregenerate_signals)->default_value(false), "Pregenerate uplink signals after attach. Improves CPU performance.") + ("expert.print_buffer_state", + bpo::value(&args->expert.print_buffer_state)->default_value(false), + "Prints on the console the buffer state every 10 seconds") + ("expert.rssi_sensor_enabled", bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") @@ -486,9 +490,16 @@ int main(int argc, char *argv[]) ue->start_plot(); } } + int cnt=0; while (running) { - ue->print_pool(); - sleep(10); + if (args.expert.print_buffer_state) { + cnt++; + if (cnt==10) { + cnt=0; + ue->print_pool(); + } + } + sleep(1); } pthread_cancel(input); metricshub.stop(); From 28dc194e2ff4d63f501eaf5d8c863b1089a15a74 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 19:46:10 +0200 Subject: [PATCH 40/52] Fix UE blocking on Reestablishment when Overflow --- srsue/src/phy/phch_recv.cc | 12 +++++++----- srsue/src/upper/nas.cc | 1 + srsue/src/upper/rrc.cc | 28 ++++++++++++---------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 780f2c72a..3d8d7f3cf 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -257,19 +257,21 @@ phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::p bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { pthread_mutex_lock(&rrc_mutex); + bool ret = false; + int cnt = 0; + // Move state to IDLE if (!new_cell) { Info("Cell Select: Starting cell resynchronization\n"); } else { if (!srslte_cell_isvalid(&cell)) { log_h->error("Cell Select: Invalid cell. ID=%d, PRB=%d, ports=%d\n", cell.id, cell.nof_prb, cell.nof_ports); - return false; + goto unlock; } Info("Cell Select: Starting cell selection for PCI=%d, EARFCN=%d\n", new_cell->cell.id, new_cell->earfcn); } // Wait for any pending PHICH - int cnt = 0; while(worker_com->is_any_pending_ack() && cnt < 10) { usleep(1000); cnt++; @@ -296,7 +298,7 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { cell = new_cell->cell; if (!set_cell()) { Error("Cell Select: Reconfiguring cell\n"); - return false; + goto unlock; } } @@ -305,7 +307,7 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { Info("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); if (set_frequency()) { Error("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); - return false; + goto unlock; } current_earfcn = new_cell->earfcn; } @@ -318,7 +320,6 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { } /* SFN synchronization */ - bool ret = false; phy_state.run_sfn_sync(); if (phy_state.is_camping()) { Info("Cell Select: SFN synchronized. CAMPING...\n"); @@ -327,6 +328,7 @@ bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { Info("Cell Select: Could not synchronize SFN\n"); } +unlock: pthread_mutex_unlock(&rrc_mutex); return ret; } diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 291a3550f..ad8ae39a8 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -242,6 +242,7 @@ bool nas::rrc_connect() { } } else { nas_log->error("Could not establish RRC connection\n"); + pool->deallocate(dedicatedInfoNAS); } return false; } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 3f213979d..773a46a53 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -220,21 +220,11 @@ void rrc::run_tti(uint32_t tti) { // If attached but not camping on the cell, perform cell reselection if (nas->is_attached()) { 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 - 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 { + if (cell_selection()) { // New cell has been selected, start receiving PCCH mac->pcch_start_rx(); + } else { + rrc_log->warning("Could not find any cell to camp on\n"); } } break; @@ -780,14 +770,12 @@ phy_interface_rrc::cell_search_ret_t rrc::cell_search() */ bool rrc::cell_selection() { - int candidates = 0; // Neighbour cells are sorted in descending order of RSRP for (uint32_t i = 0; i < neighbour_cells.size(); i++) { if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ neighbour_cells[i]->in_sync) // matches S criteria { - candidates++; // If currently connected, verify cell selection criteria if (!serving_cell->in_sync || (cell_selection_criteria(neighbour_cells[i]->get_rsrp()) && @@ -814,7 +802,15 @@ bool rrc::cell_selection() } } } - return false; + if (serving_cell->in_sync) { + return true; + } + // If can not find any suitable cell, search again + 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 + phy_interface_rrc::cell_search_ret_t ret = cell_search(); + + return ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND; } // Cell selection criteria Section 5.2.3.2 of 36.304 From 06db4e2a87603db8f04d0dc268f419963e50cd8b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Apr 2018 23:50:50 +0200 Subject: [PATCH 41/52] Start PCCH Only when switching cell in IDLE mode --- srsue/hdr/upper/rrc.h | 8 +++++++- srsue/src/upper/gw.cc | 3 +-- srsue/src/upper/nas.cc | 6 +++--- srsue/src/upper/rrc.cc | 23 ++++++++++++++--------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 1e099351d..fb89fbbe9 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -564,7 +564,13 @@ private: float get_srxlev(float Qrxlevmeas); float get_squal(float Qqualmeas); - bool cell_selection(); + typedef enum { + CHANGED_CELL = 0, + SAME_CELL = 1, + NO_CELL = 2 + } cs_ret_t; + + cs_ret_t cell_selection(); bool cell_selection_criteria(float rsrp, float rsrq = 0); void cell_reselection(float rsrp, float rsrq); diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index c4b482b92..4c3cf6301 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -280,8 +280,7 @@ void gw::run_thread() if (!attach_wait) { gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_wait, ATTACH_WAIT_TOUT); if (!nas->attach_request()) { - gw_log->info("Could not re-establish the connection\n"); - break; + gw_log->warning("Could not re-establish the connection\n"); } } usleep(100000); diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index ad8ae39a8..d6b347977 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -138,7 +138,7 @@ bool nas::attach_request() { nas_log->info("NAS attached successfully.\n"); return true; } else { - nas_log->error("Could not attach\n"); + nas_log->error("Could not attach in attach request\n"); } } else { nas_log->error("PLMN is not selected because no suitable PLMN was found\n"); @@ -154,7 +154,7 @@ bool nas::attach_request() { nas_log->info("NAS attached successfully.\n"); return true; } else { - nas_log->error("Could not attach\n"); + nas_log->error("Could not attach from attach_request\n"); } } break; @@ -181,7 +181,7 @@ void nas::paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) { if (rrc_connect()) { nas_log->info("Attached successfully\n"); } else { - nas_log->error("Could not attach\n"); + nas_log->error("Could not attach from paging\n"); } } else { nas_log->warning("Received paging while in state %s\n", emm_state_text[state]); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 773a46a53..59b1b04a0 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -220,11 +220,16 @@ void rrc::run_tti(uint32_t tti) { // If attached but not camping on the cell, perform cell reselection if (nas->is_attached()) { rrc_log->debug("Running cell selection and reselection in IDLE\n"); - if (cell_selection()) { - // New cell has been selected, start receiving PCCH - mac->pcch_start_rx(); - } else { - rrc_log->warning("Could not find any cell to camp on\n"); + switch(cell_selection()) { + case rrc::CHANGED_CELL: + // New cell has been selected, start receiving PCCH + mac->pcch_start_rx(); + break; + case rrc::NO_CELL: + rrc_log->warning("Could not find any cell to camp on\n"); + break; + case rrc::SAME_CELL: + break; } } break; @@ -768,7 +773,7 @@ phy_interface_rrc::cell_search_ret_t rrc::cell_search() /* Cell selection procedure 36.304 5.2.3 * Select the best cell to camp on among the list of known cells */ -bool rrc::cell_selection() +rrc::cs_ret_t rrc::cell_selection() { // Neighbour cells are sorted in descending order of RSRP for (uint32_t i = 0; i < neighbour_cells.size(); i++) { @@ -791,7 +796,7 @@ bool rrc::cell_selection() if (phy->cell_select(&serving_cell->phy_cell)) { if (configure_serving_cell()) { rrc_log->info("Selected and configured cell successfully\n"); - return true; + return CHANGED_CELL; } else { rrc_log->error("While configuring serving cell\n"); } @@ -803,14 +808,14 @@ bool rrc::cell_selection() } } if (serving_cell->in_sync) { - return true; + return SAME_CELL; } // If can not find any suitable cell, search again 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 phy_interface_rrc::cell_search_ret_t ret = cell_search(); - return ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND; + return (ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND)?CHANGED_CELL:NO_CELL; } // Cell selection criteria Section 5.2.3.2 of 36.304 From c17fbfcde19b6ed5418bfee7646c1c041d9b6255 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 11:45:46 +0200 Subject: [PATCH 42/52] Fixed buffer overflow in SIB generation --- srsenb/src/upper/rrc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 2afedad08..a18df9a59 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -121,7 +121,7 @@ uint32_t rrc::generate_sibs() // msg is array of SI messages, each SI message msg[i] may contain multiple SIBs // all SIBs in a SI message msg[i] share the same periodicity - LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages+1, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); // Copy SIB1 to first SI message msg[0].N_sibs = 1; From b237d6063e31bc5915cf14976d6a8bb74f3c38ab Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 11:46:22 +0200 Subject: [PATCH 43/52] Align header buffer to 8-byte boundary as expected by S1AP pack/unpack functions --- lib/include/srslte/asn1/liblte_common.h | 2 +- lib/include/srslte/common/common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/asn1/liblte_common.h b/lib/include/srslte/asn1/liblte_common.h index 053f64d70..3b7eccf6f 100644 --- a/lib/include/srslte/asn1/liblte_common.h +++ b/lib/include/srslte/asn1/liblte_common.h @@ -55,7 +55,7 @@ // Caution these values must match SRSLTE_ ones in common.h #define LIBLTE_MAX_MSG_SIZE_BITS 102048 #define LIBLTE_MAX_MSG_SIZE_BYTES 12756 -#define LIBLTE_MSG_HEADER_OFFSET 1024 +#define LIBLTE_MSG_HEADER_OFFSET 1020 /******************************************************************************* TYPEDEFS diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 754b7423d..6477a4efd 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -61,7 +61,7 @@ // 3GPP 36.306 Table 4.1.1 #define SRSLTE_MAX_BUFFER_SIZE_BITS 102048 #define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756 -#define SRSLTE_BUFFER_HEADER_OFFSET 1024 +#define SRSLTE_BUFFER_HEADER_OFFSET 1020 #define SRSLTE_BUFFER_POOL_LOG_ENABLED From 462de6607d0d6214171e3e2f80157b0e37c84f22 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 11:48:38 +0200 Subject: [PATCH 44/52] Do not assume initialized variable in S1AP packing --- lib/src/asn1/liblte_s1ap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/asn1/liblte_s1ap.cc b/lib/src/asn1/liblte_s1ap.cc index 0a589e709..ea0b1ec92 100644 --- a/lib/src/asn1/liblte_s1ap.cc +++ b/lib/src/asn1/liblte_s1ap.cc @@ -44006,7 +44006,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1ap_pdu( } liblte_align_up_zero(ptr, 8); - bit_msg.N_bits += (*ptr - bit_msg.msg); + bit_msg.N_bits = (*ptr - bit_msg.msg); liblte_pack(&bit_msg, msg); err = LIBLTE_SUCCESS; From 62787bdd41c0e98ff494812844b24ff4851fd738 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 12:46:17 +0200 Subject: [PATCH 45/52] Remove unused include --- lib/include/srslte/upper/pdcp_entity.h | 1 - lib/include/srslte/upper/rlc.h | 1 - srsenb/hdr/upper/s1ap.h | 1 - srsue/hdr/upper/gw.h | 1 - 4 files changed, 4 deletions(-) diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index e8a5d9561..de51ed1de 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -32,7 +32,6 @@ #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/threads.h" diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index c4d57b9bb..05472e0e8 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -31,7 +31,6 @@ #include "srslte/common/log.h" #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" -#include "srslte/common/msg_queue.h" #include "srslte/upper/rlc_entity.h" #include "srslte/upper/rlc_metrics.h" #include "srslte/upper/rlc_common.h" diff --git a/srsenb/hdr/upper/s1ap.h b/srsenb/hdr/upper/s1ap.h index 35369790f..35b871bdc 100644 --- a/srsenb/hdr/upper/s1ap.h +++ b/srsenb/hdr/upper/s1ap.h @@ -32,7 +32,6 @@ #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/common.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/threads.h" #include "srslte/interfaces/enb_interfaces.h" #include "common_enb.h" diff --git a/srsue/hdr/upper/gw.h b/srsue/hdr/upper/gw.h index 10ab50e56..3b17eb75b 100644 --- a/srsue/hdr/upper/gw.h +++ b/srsue/hdr/upper/gw.h @@ -30,7 +30,6 @@ #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/common.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/interfaces_common.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/threads.h" From 6ac39ee1a925946b458a255daa960ec51d33d7a6 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 13:17:55 +0200 Subject: [PATCH 46/52] Do not block in RLC TM read queue --- lib/src/upper/rlc_tm.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index b9d41d3f2..2ae7515a7 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -60,8 +60,9 @@ void rlc_tm::empty_queue() // Drop all messages in TX queue byte_buffer_t *buf; while(ul_queue.size() > 0) { - ul_queue.read(&buf); - pool->deallocate(buf); + if (ul_queue.try_read(&buf)) { + pool->deallocate(buf); + } } } @@ -112,14 +113,18 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) return 0; } byte_buffer_t *buf; - ul_queue.read(&buf); - pdu_size = buf->N_bytes; - memcpy(payload, buf->msg, buf->N_bytes); - log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); - pool->deallocate(buf); - log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); - return pdu_size; + if (ul_queue.try_read(&buf)) { + pdu_size = buf->N_bytes; + memcpy(payload, buf->msg, buf->N_bytes); + log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", + rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); + pool->deallocate(buf); + log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); + return pdu_size; + } else { + log->warning("Queue empty while trying to read\n"); + return 0; + } } void rlc_tm::write_pdu(uint8_t *payload, uint32_t nof_bytes) From d8bfd2713c1d7982e8ae17aea058af6327b3ccf0 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 26 Apr 2018 13:20:34 +0200 Subject: [PATCH 47/52] initialize byte_buffer content in ctors --- lib/include/srslte/common/common.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 6477a4efd..b7130f6d5 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -116,15 +116,17 @@ public: byte_buffer_t():N_bytes(0) { - timestamp_is_set = false; + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); + timestamp_is_set = false; msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; next = NULL; #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED - debug_name[0] = 0; + bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN); #endif } byte_buffer_t(const byte_buffer_t& buf) { + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); N_bytes = buf.N_bytes; memcpy(msg, buf.msg, N_bytes); } @@ -133,6 +135,7 @@ public: // avoid self assignment if (&buf == this) return *this; + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); N_bytes = buf.N_bytes; memcpy(msg, buf.msg, N_bytes); return *this; From 8df9f46e130d9a938878ef8cd5b374fdcf2000f4 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 26 Apr 2018 13:21:13 +0200 Subject: [PATCH 48/52] fix NAS and NAS test --- srsue/src/upper/nas.cc | 10 ++++--- srsue/test/upper/nas_test.cc | 54 ++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index d6b347977..0488f4b45 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -49,6 +49,9 @@ nas::nas() { ctxt.rx_count = 0; ctxt.tx_count = 0; + ctxt.cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; + ctxt.integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; + plmn_is_selected = false; } void nas::init(usim_interface_nas *usim_, @@ -103,7 +106,6 @@ 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"); switch (state) { case EMM_STATE_DEREGISTERED: @@ -233,7 +235,7 @@ bool nas::rrc_connect() { 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->error("Timeout or 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"); @@ -423,7 +425,7 @@ bool nas::integrity_check(byte_buffer_t *pdu) return NULL; } if (pdu->N_bytes > 5) { - uint8_t exp_mac[4]; + uint8_t exp_mac[4] = {0}; uint8_t *mac = &pdu->msg[1]; int i; @@ -481,7 +483,7 @@ void nas::cipher_encrypt(byte_buffer_t *pdu) memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); break; default: - nas_log->error("Ciphering algorithmus not known"); + nas_log->error("Ciphering algorithm not known\n"); break; } } diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 2a51392ed..91b9c1d24 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -50,6 +50,15 @@ uint8_t auth_request_pdu[] = { 0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0 uint8_t sec_mode_command_pdu[] = { 0x37, 0x37, 0xc7, 0x67, 0xae, 0x00, 0x07, 0x5d, 0x02, 0x01, 0x02, 0xe0, 0x60, 0xc1 }; +uint8_t attach_accept_pdu[] = { 0x27, 0x0f, 0x4f, 0xb3, 0xef, 0x01, 0x07, 0x42, 0x01, 0x3e, + 0x06, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, + 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, + 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, 0x31, + 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, + 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, + 0x80, 0x50, 0x0b, 0xf6, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01, + 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00 }; + uint16 mcc = 61441; uint16 mnc = 65281; @@ -71,22 +80,35 @@ public: class rrc_dummy : public rrc_interface_nas { public: + rrc_dummy() : last_sdu_len(0) { + plmns.plmn_id.mcc = mcc; + plmns.plmn_id.mnc = mnc; + plmns.tac = 0xffff; + } void write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); last_sdu_len = sdu->N_bytes; - srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + //printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + //srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); byte_buffer_pool::get_instance()->deallocate(sdu); } std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } uint32_t get_last_sdu_len() { return last_sdu_len; } - int plmn_search(srsue::rrc_interface_nas::found_plmn_t*) { return 0; }; + int plmn_search(srsue::rrc_interface_nas::found_plmn_t* found) { + memcpy(found, &plmns, sizeof(found_plmn_t)); + return 1; + }; void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {}; 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;} + bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, srslte::byte_buffer_t *sdu) { + printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + last_sdu_len = sdu->N_bytes; + srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + byte_buffer_pool::get_instance()->deallocate(sdu); + return true; + } + bool is_connected() {return false;} uint16_t get_mcc() { return mcc; } uint16_t get_mnc() { return mnc; } @@ -94,6 +116,7 @@ public: private: uint32_t last_sdu_len; + found_plmn_t plmns; }; class gw_dummy : public gw_interface_nas, public gw_interface_pdcp @@ -134,15 +157,12 @@ int security_command_test() uint8_t res[16]; usim.init(&args, &usim_log); - srslte::byte_buffer_pool *pool; - pool = byte_buffer_pool::get_instance(); - srsue::nas nas; srslte_nas_config_t cfg; nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg); // push auth request PDU to NAS to generate security context - byte_buffer_t* tmp = pool->allocate(); + byte_buffer_t* tmp = byte_buffer_pool::get_instance()->allocate(); memcpy(tmp->msg, auth_request_pdu, sizeof(auth_request_pdu)); tmp->N_bytes = sizeof(auth_request_pdu); nas.write_pdu(LCID, tmp); @@ -159,7 +179,7 @@ int security_command_test() ret = SRSLTE_SUCCESS; } - pool->cleanup(); + byte_buffer_pool::get_instance()->cleanup(); return ret; } @@ -195,11 +215,21 @@ int mme_attach_request_test() nas.attach_request(); - // check length of generated NAS SDU + // this will time out in the first place + + // finally push attach accept + byte_buffer_t* tmp = byte_buffer_pool::get_instance()->allocate(); + memcpy(tmp->msg, attach_accept_pdu, sizeof(attach_accept_pdu)); + tmp->N_bytes = sizeof(attach_accept_pdu); + nas.write_pdu(LCID, tmp); + + // check length of generated NAS SDU (attach complete) if (rrc_dummy.get_last_sdu_len() > 3) { ret = SRSLTE_SUCCESS; } + byte_buffer_pool::get_instance()->cleanup(); + return ret; } From 7c210c3fc202de67c53e11fe0c126b5991adc290 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 14:03:39 +0200 Subject: [PATCH 49/52] Deallocate measurement timers on RLF. Force cell reselection during attach request from gw after RLF --- srsue/src/upper/rrc.cc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 59b1b04a0..ff6024b8a 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -229,6 +229,10 @@ void rrc::run_tti(uint32_t tti) { rrc_log->warning("Could not find any cell to camp on\n"); break; case rrc::SAME_CELL: + if (!phy->cell_is_camping()) { + rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + serving_cell->in_sync = false; + } break; } } @@ -378,7 +382,7 @@ bool rrc::connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, rrc_log->info("Initiation of Connection establishment procedure\n"); // Perform cell selection & reselection for the selected PLMN - cell_selection(); + cs_ret_t cs_ret = cell_selection(); // .. and SI acquisition if (phy->cell_is_camping()) { @@ -431,7 +435,18 @@ bool rrc::connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, rrc_log->error("Configuring serving cell\n"); } } else { - rrc_log->error("Could not find any suitable cell to connect\n"); + switch(cs_ret) { + case SAME_CELL: + rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + serving_cell->in_sync = false; + break; + case CHANGED_CELL: + rrc_log->warning("Selected a new cell but could not camp on. Setting out-of-sync.\n"); + serving_cell->in_sync = false; + break; + default: + rrc_log->warning("Could not find any suitable cell to connect\n"); + } } pthread_mutex_unlock(&mutex); @@ -1523,6 +1538,7 @@ void rrc::leave_connected() { rrc_log->console("RRC IDLE\n"); rrc_log->info("Leaving RRC_CONNECTED state\n"); + state = RRC_STATE_IDLE; drb_up = false; security_is_activated = false; measurements.reset(); @@ -1537,7 +1553,6 @@ void rrc::leave_connected() 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()) { // Receive paging mac->pcch_start_rx(); @@ -2630,8 +2645,15 @@ void rrc::rrc_meas::reset() { filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; + + // FIXME: Turn struct into a class and use destructor + std::map::iterator iter = active.begin(); + while (iter != active.end()) { + remove_meas_id(iter++); + } + + // These objects do not need destructor objects.clear(); - active.clear(); reports_cfg.clear(); phy->meas_reset(); bzero(&pcell_measurement, sizeof(meas_value_t)); From 3bf9ca61954f71d7746f0d02ba8376739abf7140 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Apr 2018 17:33:21 +0200 Subject: [PATCH 50/52] Send end of burst on idle --- lib/include/srslte/phy/ch_estimation/chest_dl.h | 2 +- srsue/src/phy/phch_recv.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 5f7731305..653ee0075 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -113,10 +113,10 @@ SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q); SRSLTE_API int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_id); + SRSLTE_API int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell); - SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 3d8d7f3cf..143fd3b2f 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -363,6 +363,8 @@ void phch_recv::run_thread() cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; uint32_t sf_idx = 0; + bool is_end_of_burst = false; + cf_t *dummy_buffer[SRSLTE_MAX_PORTS]; for (int i=0;istart_worker(worker); @@ -505,6 +509,10 @@ void phch_recv::run_thread() if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) { printf("SYNC: Receiving from radio while in IDLE_RX\n"); } + if (is_end_of_burst) { + radio_h->tx_end(); + is_end_of_burst = true; + } } else { usleep(1000); } @@ -896,6 +904,7 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) if (p->srate_mode != SRATE_FIND) { p->srate_mode = SRATE_FIND; p->radio_h->set_rx_srate(1.92e6); + p->radio_h->set_tx_srate(1.92e6); Info("SYNC: Setting Cell Search sampling rate\n"); } From 68cbb6ca7fd000d1c466b2e01c05ed41f1eac432 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 27 Apr 2018 10:13:49 +0200 Subject: [PATCH 51/52] Do not lock on ConnectionReconfiguration --- srsue/src/phy/phch_recv.cc | 2 +- srsue/src/upper/rrc.cc | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 143fd3b2f..3bb6f4a40 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -1233,7 +1233,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in return MEASURE_OK; } } else { - Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); + Error("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); ret = ERROR; } return ret; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index ff6024b8a..0f5975705 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1506,10 +1506,8 @@ void rrc::con_reconfig_failed() } } -void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { - - pthread_mutex_lock(&mutex); - +void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) +{ phy->get_config(&previous_phy_cfg); mac->get_config(&previous_mac_cfg); @@ -1522,8 +1520,6 @@ 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 */ From 3ab74fb552b766c22151a3afbddd2086d6503848 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 27 Apr 2018 10:23:38 +0200 Subject: [PATCH 52/52] Exposed continuous TX mode to ue.conf --- lib/include/srslte/radio/radio.h | 282 ++++++++++++++++--------------- lib/src/radio/radio.cc | 14 +- srsue/hdr/phy/phch_common.h | 3 - srsue/hdr/ue_base.h | 1 + srsue/src/main.cc | 1 + srsue/src/phy/phch_common.cc | 2 +- srsue/src/ue.cc | 5 +- srsue/ue.conf.example | 5 +- 8 files changed, 165 insertions(+), 148 deletions(-) diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 26775777b..5137bd13b 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -34,150 +34,152 @@ #define SRSLTE_RADIO_H typedef struct { - float tx_corr_dc_gain; - float tx_corr_dc_phase; - float tx_corr_iq_i; - float tx_corr_iq_q; - float rx_corr_dc_gain; - float rx_corr_dc_phase; - float rx_corr_iq_i; - float rx_corr_iq_q; -}rf_cal_t; - + float tx_corr_dc_gain; + float tx_corr_dc_phase; + float tx_corr_iq_i; + float tx_corr_iq_q; + float rx_corr_dc_gain; + float rx_corr_dc_phase; + float rx_corr_iq_i; + float rx_corr_iq_q; +} rf_cal_t; namespace srslte { - + /* Interface to the RF frontend. */ - class radio - { - public: - radio() : tr_local_time(1024*10), tr_usrp_time(1024*10), tr_tx_time(1024*10), tr_is_eob(1024*10) { - bzero(&rf_device, sizeof(srslte_rf_t)); - bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); - bzero(zeros, burst_preamble_max_samples*sizeof(cf_t)); - - burst_preamble_sec = 0; - is_start_of_burst = false; - burst_preamble_samples = 0; - burst_preamble_time_rounded = 0; - - cur_tx_srate = 0; - tx_adv_sec = 0; - tx_adv_nsamples = 0; - tx_adv_auto = false; - tx_adv_negative = false; - tx_freq = 0; - rx_freq = 0; - trace_enabled = false; - tti = 0; - agc_enabled = false; - radio_is_streaming = false; - is_initialized = false; - }; - - bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); - void stop(); - void reset(); - bool start_agc(bool tx_gain_same_rx); - - void set_burst_preamble(double preamble_us); - void set_tx_adv(int nsamples); - void set_tx_adv_neg(bool tx_adv_is_neg); - - void set_manual_calibration(rf_cal_t *calibration); - - void get_time(srslte_timestamp_t *now); - bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); - bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); - void tx_end(); - bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); - bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); - - void set_tx_gain(float gain); - void set_rx_gain(float gain); - void set_tx_rx_gain_offset(float offset); - double set_rx_gain_th(float gain); - - void set_freq_offset(double freq); - void set_tx_freq(double freq); - void set_rx_freq(double freq); - - double get_freq_offset(); - double get_tx_freq(); - double get_rx_freq(); - - void set_master_clock_rate(double rate); - void set_tx_srate(double srate); - void set_rx_srate(double srate); - - float get_tx_gain(); - float get_rx_gain(); - - float get_max_tx_power(); - float set_tx_power(float power); - float get_rssi(); - bool has_rssi(); - - void start_trace(); - void write_trace(std::string filename); - - void set_tti(uint32_t tti); - - bool is_first_of_burst(); - - bool is_init(); - - void register_error_handler(srslte_rf_error_handler_t h); - - protected: - - void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time); - - srslte_rf_t rf_device; - - - const static uint32_t burst_preamble_max_samples = 30720000; // 30.72 MHz is maximum frequency - double burst_preamble_sec;// Start of burst preamble time (off->on RF transition time) - srslte_timestamp_t end_of_burst_time; - bool is_start_of_burst; - uint32_t burst_preamble_samples; - double burst_preamble_time_rounded; // preamble time rounded to sample time - cf_t zeros[burst_preamble_max_samples]; - double cur_tx_srate; - - double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay - int tx_adv_nsamples; // Transmision time advance in number of samples - - // Define default values for known radios - bool tx_adv_auto; - bool tx_adv_negative; - const static double uhd_default_burst_preamble_sec = 600*1e-6; - const static double uhd_default_tx_adv_samples = 98; - const static double uhd_default_tx_adv_offset_sec = 4*1e-6; - - const static double blade_default_burst_preamble_sec = 0.0; - const static double blade_default_tx_adv_samples = 27; - const static double blade_default_tx_adv_offset_sec = 1e-6; - - double tx_freq, rx_freq, freq_offset; - - trace tr_local_time; - trace tr_usrp_time; - trace tr_tx_time; - trace tr_is_eob; - bool trace_enabled; - uint32_t tti; - bool agc_enabled; - - bool is_initialized = true;; - bool radio_is_streaming; - - uint32_t saved_nof_channels; - char saved_args[128]; - char saved_devname[128]; - - }; +class radio { + public: + radio() : tr_local_time(1024 * 10), tr_usrp_time(1024 * 10), tr_tx_time(1024 * 10), tr_is_eob(1024 * 10) { + bzero(&rf_device, sizeof(srslte_rf_t)); + bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); + bzero(zeros, burst_preamble_max_samples * sizeof(cf_t)); + + burst_preamble_sec = 0; + is_start_of_burst = false; + burst_preamble_samples = 0; + burst_preamble_time_rounded = 0; + + cur_tx_srate = 0; + tx_adv_sec = 0; + tx_adv_nsamples = 0; + tx_adv_auto = false; + tx_adv_negative = false; + tx_freq = 0; + rx_freq = 0; + trace_enabled = false; + tti = 0; + agc_enabled = false; + radio_is_streaming = false; + is_initialized = false; + continuous_tx = false; + }; + + bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); + void stop(); + void reset(); + bool start_agc(bool tx_gain_same_rx); + + void set_burst_preamble(double preamble_us); + void set_tx_adv(int nsamples); + void set_tx_adv_neg(bool tx_adv_is_neg); + + void set_manual_calibration(rf_cal_t *calibration); + + bool is_continuous_tx(); + void set_continuous_tx(bool enable); + + void get_time(srslte_timestamp_t *now); + bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); + void tx_end(); + bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); + bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); + + void set_tx_gain(float gain); + void set_rx_gain(float gain); + void set_tx_rx_gain_offset(float offset); + double set_rx_gain_th(float gain); + + void set_freq_offset(double freq); + void set_tx_freq(double freq); + void set_rx_freq(double freq); + + double get_freq_offset(); + double get_tx_freq(); + double get_rx_freq(); + + void set_master_clock_rate(double rate); + void set_tx_srate(double srate); + void set_rx_srate(double srate); + + float get_tx_gain(); + float get_rx_gain(); + + float get_max_tx_power(); + float set_tx_power(float power); + float get_rssi(); + bool has_rssi(); + + void start_trace(); + void write_trace(std::string filename); + + void set_tti(uint32_t tti); + + bool is_first_of_burst(); + + bool is_init(); + + void register_error_handler(srslte_rf_error_handler_t h); + + protected: + + void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time); + + srslte_rf_t rf_device; + + const static uint32_t burst_preamble_max_samples = 30720000; // 30.72 MHz is maximum frequency + double burst_preamble_sec;// Start of burst preamble time (off->on RF transition time) + srslte_timestamp_t end_of_burst_time; + bool is_start_of_burst; + uint32_t burst_preamble_samples; + double burst_preamble_time_rounded; // preamble time rounded to sample time + cf_t zeros[burst_preamble_max_samples]; + double cur_tx_srate; + + double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay + int tx_adv_nsamples; // Transmision time advance in number of samples + + // Define default values for known radios + bool tx_adv_auto; + bool tx_adv_negative; + const static double uhd_default_burst_preamble_sec = 600 * 1e-6; + const static double uhd_default_tx_adv_samples = 98; + const static double uhd_default_tx_adv_offset_sec = 4 * 1e-6; + + const static double blade_default_burst_preamble_sec = 0.0; + const static double blade_default_tx_adv_samples = 27; + const static double blade_default_tx_adv_offset_sec = 1e-6; + + double tx_freq, rx_freq, freq_offset; + + trace tr_local_time; + trace tr_usrp_time; + trace tr_tx_time; + trace tr_is_eob; + bool trace_enabled; + uint32_t tti; + bool agc_enabled; + + bool continuous_tx; + bool is_initialized; + bool radio_is_streaming; + + uint32_t saved_nof_channels; + char saved_args[128]; + char saved_devname[128]; + +}; } #endif // SRSLTE_RADIO_H diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 3be26e6b3..7b53f7405 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -50,12 +50,14 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels) // Suppress radio stdout srslte_rf_suppress_stdout(&rf_device); - - tx_adv_auto = true; + + continuous_tx = false; + tx_adv_auto = true; // Set default preamble length each known device // We distinguish by device family, maybe we should calibrate per device if (strstr(srslte_rf_name(&rf_device), "uhd")) { burst_preamble_sec = uhd_default_burst_preamble_sec; + continuous_tx = true; } else if (strstr(srslte_rf_name(&rf_device), "bladerf")) { burst_preamble_sec = blade_default_burst_preamble_sec; } else { @@ -111,6 +113,14 @@ void radio::set_burst_preamble(double preamble_us) burst_preamble_sec = (double) preamble_us/1e6; } +void radio::set_continuous_tx(bool enable) { + continuous_tx = enable; +} + +bool radio::is_continuous_tx() { + return continuous_tx; +} + void radio::set_tx_adv(int nsamples) { tx_adv_auto = false; diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 4d2536f53..b036f3869 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -27,9 +27,6 @@ #ifndef SRSUE_PHCH_COMMON_H #define SRSUE_PHCH_COMMON_H -#define TX_MODE_CONTINUOUS 1 - - #include #include #include diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 547aefee8..63bb19533 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -64,6 +64,7 @@ typedef struct { std::string device_args; std::string time_adv_nsamples; std::string burst_preamble; + std::string continuous_tx; }rf_args_t; typedef struct { diff --git a/srsue/src/main.cc b/srsue/src/main.cc index f155c0a98..d8469f3ae 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -77,6 +77,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("rf.time_adv_nsamples", bpo::value(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") ("rf.burst_preamble_us", bpo::value(&args->rf.burst_preamble)->default_value("auto"), "Transmission time advance") + ("rf.continuous_tx", bpo::value(&args->rf.continuous_tx)->default_value("auto"), "Transmit samples continuously to the radio or on bursts (auto/yes/no). Default is auto (yes for UHD, no for rest)") ("rrc.feature_group", bpo::value(&args->rrc.feature_group)->default_value(0xe6041c00), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041c00") diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 1129e7c6e..120f2ee51 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -248,7 +248,7 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, radio_h->tx_single(buffer, nof_samples, tx_time); is_first_of_burst = false; } else { - if (TX_MODE_CONTINUOUS) { + if (radio_h->is_continuous_tx()) { if (!is_first_of_burst) { radio_h->tx_single(zeros, nof_samples, tx_time); } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 8c10f9a51..b8db55e5e 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -160,7 +160,10 @@ bool ue::init(all_args_t *args_) if (args->rf.burst_preamble.compare("auto")) { radio.set_burst_preamble(atof(args->rf.burst_preamble.c_str())); } - + if (args->rf.continuous_tx.compare("auto")) { + radio.set_continuous_tx(args->rf.continuous_tx.compare("yes")?false:true); + } + radio.set_manual_calibration(&args->rf_cal); // Set PHY options diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 531381431..7224cf8e3 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -20,7 +20,9 @@ # from antenna to timestamp insertion. # Default "auto". B210 USRP: 100 samples, bladeRF: 27. # burst_preamble_us: Preamble length to transmit before start of burst. -# Default "auto". B210 USRP: 400 us, bladeRF: 0 us. +# Default "auto". B210 USRP: 400 us, bladeRF: 0 us. +# continuous_tx: Transmit samples continuously to the radio or on bursts (auto/yes/no). +# Default is auto (yes for UHD, no for rest) ##################################################################### [rf] dl_earfcn = 3400 @@ -33,6 +35,7 @@ rx_gain = 40 #device_args = auto #time_adv_nsamples = auto #burst_preamble_us = auto +#continuous_tx = auto #####################################################################