Merge branch 'next' into guti_attach

master
Pedro Alvarez 7 years ago
commit 406a1d01b6

@ -30,6 +30,8 @@
#include <pthread.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <algorithm>
/*******************************************************************************
@ -76,8 +78,13 @@ public:
{
printf("%d buffers in queue\n", (int) used.size());
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
std::map<std::string, uint32_t> buffer_cnt;
for (uint32_t i=0;i<used.size();i++) {
printf("%s\n", strlen(used[i]->debug_name)?used[i]->debug_name:"Undefined");
buffer_cnt[strlen(used[i]->debug_name)?used[i]->debug_name:"Undefined"]++;
}
std::map<std::string, uint32_t>::iterator it;
for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) {
printf(" - %dx %s\n", it->second, it->first.c_str());
}
#endif
}

@ -63,7 +63,7 @@
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
#define SRSLTE_BUFFER_HEADER_OFFSET 1024
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
#define SRSLTE_BUFFER_POOL_LOG_ENABLED
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
#define pool_allocate (pool->allocate(__FUNCTION__))

@ -160,7 +160,7 @@ public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
virtual void earfcn_end() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 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;
};
@ -580,9 +580,8 @@ public:
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_stop() = 0;
virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 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? */

@ -60,6 +60,7 @@ typedef struct {
SRSLTE_RF_ERROR_LATE,
SRSLTE_RF_ERROR_UNDERFLOW,
SRSLTE_RF_ERROR_OVERFLOW,
SRSLTE_RF_ERROR_RX,
SRSLTE_RF_ERROR_OTHER
} type;
int opt;

@ -72,6 +72,8 @@ namespace srslte {
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);
@ -119,13 +121,13 @@ namespace srslte {
void start_trace();
void write_trace(std::string filename);
void start_rx(bool now = false);
void stop_rx();
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:
@ -168,6 +170,9 @@ namespace srslte {
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];

@ -40,6 +40,7 @@ log_filter::log_filter()
do_tti = false;
time_src = NULL;
time_format = TIME;
logger_h = NULL;
}
log_filter::log_filter(std::string layer)

@ -35,6 +35,7 @@ namespace srslte{
logger_file::logger_file()
:inited(false)
,logfile(NULL)
,not_done(true)
,cur_length(0)
,max_length(0)
@ -46,8 +47,10 @@ logger_file::~logger_file() {
if(inited) {
wait_thread_finish();
flush();
if (logfile) {
fclose(logfile);
}
}
}
void logger_file::init(std::string file, int max_length_) {

@ -76,10 +76,14 @@ void pdu_queue::deallocate(uint8_t* pdu)
*/
void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp)
{
if (ptr) {
pdu_t *pdu = (pdu_t*) ptr;
pdu->len = len;
pdu->tstamp = tstamp;
pdu_q.push(pdu);
} else {
log_h->warning("Error pushing pdu: ptr is empty\n");
}
}
bool pdu_queue::process_pdus()

@ -540,22 +540,23 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui
}
}
}
/* Compute RSRP for the channel estimates in this port */
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_estimates, npilots);
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
}
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
{
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
/* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
q->pilot_estimates, npilots);
/* Compute RSRP for the channel estimates in this port */
double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots);
q->rsrp[rxant_id][port_id] = energy*energy;
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM);

@ -45,6 +45,7 @@
#define FFTW_TYPE 0
#endif
pthread_mutex_t fft_mutex = PTHREAD_MUTEX_INITIALIZER;
void srslte_dft_load() {
#ifdef FFTW_WISDOM_FILE
@ -58,10 +59,12 @@ void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE
fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE);
#endif
fftwf_cleanup();
}
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
srslte_dft_mode_t mode) {
bzero(plan, sizeof(srslte_dft_plan_t));
if(mode == SRSLTE_DFT_COMPLEX){
return srslte_dft_plan_c(plan,dft_points,dir);
} else {
@ -99,10 +102,15 @@ int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points,
const fftwf_iodim iodim = {new_dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
pthread_mutex_lock(&fft_mutex);
/* Destroy current plan */
fftwf_destroy_plan(plan->p);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) {
return -1;
}
@ -114,11 +122,15 @@ int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points,
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
pthread_mutex_lock(&fft_mutex);
if (plan->p) {
fftwf_destroy_plan(plan->p);
plan->p = NULL;
}
plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) {
return -1;
}
@ -134,10 +146,14 @@ int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte
const fftwf_iodim iodim = {dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
pthread_mutex_lock(&fft_mutex);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
pthread_mutex_unlock(&fft_mutex);
plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX;
@ -154,8 +170,14 @@ int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
pthread_mutex_lock(&fft_mutex);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) {
return -1;
}
@ -175,11 +197,15 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
pthread_mutex_lock(&fft_mutex);
if (plan->p) {
fftwf_destroy_plan(plan->p);
plan->p = NULL;
}
plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) {
return -1;
}
@ -190,7 +216,11 @@ int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(float),sizeof(float), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
pthread_mutex_lock(&fft_mutex);
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) {
return -1;
}
@ -309,11 +339,15 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, const float *in, float *out) {
void srslte_dft_plan_free(srslte_dft_plan_t *plan) {
if (!plan) return;
if (!plan->size) return;
pthread_mutex_lock(&fft_mutex);
if (!plan->is_guru) {
if (plan->in) fftwf_free(plan->in);
if (plan->out) fftwf_free(plan->out);
}
if (plan->p) fftwf_destroy_plan(plan->p);
pthread_mutex_unlock(&fft_mutex);
bzero(plan, sizeof(srslte_dft_plan_t));
}

@ -128,6 +128,8 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, c
if (sf_type == SRSLTE_SF_MBSFN) {
q->mbsfn_subframe = true;
q->non_mbsfn_region = 2; // default set to 2
} else {
q->mbsfn_subframe = false;
}
return SRSLTE_SUCCESS;

@ -171,5 +171,8 @@ int main(int argc, char **argv) {
n_prb++;
}
srslte_dft_exit();
exit(0);
}

@ -198,6 +198,8 @@ int main(int argc, char **argv) {
}
srslte_rm_turbo_free_tables();
free(rm_bits_s);
free(rm_bits_f);
free(rm_bits);
free(rm_bits2);
free(rm_bits2_bytes);

@ -96,6 +96,19 @@ static void log_underflow(rf_uhd_handler_t *h) {
}
}
static void log_rx_error(rf_uhd_handler_t *h) {
if (h->uhd_error_handler) {
char error_string[512];
uhd_usrp_last_error(h->usrp, error_string, 512);
fprintf(stderr, "USRP reported the following error: %s\n", error_string);
srslte_rf_error_t error;
bzero(&error, sizeof(srslte_rf_error_t));
error.type = SRSLTE_RF_ERROR_RX;
h->uhd_error_handler(error);
}
}
static void* async_thread(void *h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_async_metadata_handle md;
@ -334,6 +347,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
perror("malloc");
return -1;
}
bzero(handler, sizeof(rf_uhd_handler_t));
*h = handler;
/* Set priority to UHD threads */
@ -557,11 +571,12 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
uhd_meta_range_free(&gain_range);
// Start low priority thread to receive async commands
/*
handler->async_thread_running = true;
if (pthread_create(&handler->async_thread, NULL, async_thread, handler)) {
perror("pthread_create");
return -1;
}
}*/
/* Restore priorities */
uhd_set_thread_priority(0, false);
@ -738,6 +753,7 @@ int rf_uhd_recv_with_time_multi(void *h,
num_rx_samples, md, 1.0, false, &rxd_samples);
if (error) {
fprintf(stderr, "Error receiving from UHD: %d\n", error);
log_rx_error(handler);
return -1;
}
@ -760,8 +776,12 @@ int rf_uhd_recv_with_time_multi(void *h,
}
}
} else {
return uhd_rx_streamer_recv(handler->rx_stream, data,
nsamples, md, 0.0, false, &rxd_samples);
uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, nsamples, md, 0.0, false, &rxd_samples);
if (error) {
fprintf(stderr, "Error receiving from UHD: %d\n", error);
log_rx_error(handler);
return -1;
}
}
if (secs && frac_secs) {
uhd_rx_metadata_time_spec(handler->rx_md_first, secs, frac_secs);

@ -74,7 +74,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) {
while ((opt = getopt(argc, argv, "adgetvnsfil")) != -1) {
switch (opt) {
case 'a':
rf_args = argv[optind];

@ -756,6 +756,8 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
srslte_agc_process(&q->agc, input_buffer[0], q->sf_len);
}
INFO("SYNC FIND: sf_idx=%d, ret=%d, next_state=%d\n", q->sf_idx, ret, q->state);
break;
case SF_TRACK:
@ -817,6 +819,9 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->frame_total_cnt++;
}
INFO("SYNC TRACK: sf_idx=%d, ret=%d, next_state=%d\n", q->sf_idx, ret, q->state);
break;
}
}

@ -157,6 +157,8 @@ int main(int argc, char **argv) {
if(test_dft(in) != 0)
return -1;
srslte_dft_exit();
free(in);
printf("Done\n");
exit(0);

@ -71,9 +71,14 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels)
}
saved_nof_channels = nof_channels;
is_initialized = true;
return true;
}
bool radio::is_init() {
return is_initialized;
}
void radio::stop()
{
srslte_rf_close(&rf_device);
@ -82,11 +87,8 @@ void radio::stop()
void radio::reset()
{
printf("Resetting Radio...\n");
srslte_rf_close(&rf_device);
sleep(3);
if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args, saved_nof_channels)) {
fprintf(stderr, "Error opening RF device\n");
}
srslte_rf_stop_rx_stream(&rf_device);
radio_is_streaming = false;
}
void radio::set_manual_calibration(rf_cal_t* calibration)
@ -141,6 +143,10 @@ bool radio::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time
bool radio::rx_now(void* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time)
{
if (!radio_is_streaming) {
srslte_rf_start_rx_stream(&rf_device, false);
radio_is_streaming = true;
}
if (srslte_rf_recv_with_time_multi(&rf_device, buffer, nof_samples, true,
rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) {
return true;
@ -295,7 +301,9 @@ void radio::set_master_clock_rate(double rate)
void radio::set_rx_srate(double srate)
{
srslte_rf_stop_rx_stream(&rf_device);
srslte_rf_set_rx_srate(&rf_device, srate);
srslte_rf_start_rx_stream(&rf_device, false);
}
void radio::set_tx_freq(double freq)
@ -446,16 +454,6 @@ void radio::set_tx_srate(double srate)
tx_adv_sec = nsamples/cur_tx_srate;
}
void radio::start_rx(bool now)
{
srslte_rf_start_rx_stream(&rf_device, now);
}
void radio::stop_rx()
{
srslte_rf_stop_rx_stream(&rf_device);
}
void radio::register_error_handler(srslte_rf_error_handler_t h)
{
srslte_rf_register_error_handler(&rf_device, h);

@ -37,6 +37,7 @@ bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname
strncpy(saved_devname, devname, 127);
}
is_initialized = true;
return true;
}
@ -46,6 +47,10 @@ bool radio_multi::rx_now(cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, s
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ptr[i] = buffer[i];
}
if (!radio_is_streaming) {
srslte_rf_start_rx_stream(&rf_device, false);
radio_is_streaming = true;
}
if (srslte_rf_recv_with_time_multi(&rf_device, ptr, nof_samples, true,
rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) {
return true;

@ -72,6 +72,14 @@ rlc_am::~rlc_am()
{
// reset RLC and dealloc SDUs
stop();
if(rx_sdu) {
pool->deallocate(rx_sdu);
}
if(tx_sdu) {
pool->deallocate(tx_sdu);
}
}
void rlc_am::init(srslte::log *log_,

@ -136,11 +136,11 @@ void rlc_um::reset()
vr_uh = 0;
pdu_lost = false;
if(rx_sdu) {
rx_sdu->reset();
pool->deallocate(rx_sdu);
}
if(tx_sdu) {
tx_sdu->reset();
pool->deallocate(tx_sdu);
}
if(mac_timers) {

@ -31,7 +31,8 @@ target_link_libraries(rlc_am_test srslte_upper srslte_phy srslte_common)
add_test(rlc_am_test rlc_am_test)
add_executable(rlc_am_stress_test rlc_am_stress_test.cc)
target_link_libraries(rlc_am_stress_test srslte_upper srslte_phy srslte_common)
target_link_libraries(rlc_am_stress_test srslte_upper srslte_phy srslte_common ${Boost_LIBRARIES})
add_test(rlc_am_stress_test rlc_am_stress_test --duration 10)
add_executable(rlc_um_data_test rlc_um_data_test.cc)
target_link_libraries(rlc_um_data_test srslte_upper srslte_phy srslte_common)

@ -31,23 +31,70 @@
#include "srslte/common/logger_stdout.h"
#include "srslte/common/threads.h"
#include "srslte/upper/rlc.h"
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <assert.h>
#define NBUFS 5
using namespace std;
using namespace srsue;
using namespace srslte;
namespace bpo = boost::program_options;
typedef struct {
uint32_t test_duration_sec;
float error_rate;
uint32_t sdu_gen_delay_usec;
uint32_t pdu_tx_delay_usec;
bool reestablish;
} stress_test_args_t;
void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
// Command line only options
bpo::options_description general("General options");
general.add_options()
("help,h", "Produce help message")
("version,v", "Print version information and exit");
// Command line or config file options
bpo::options_description common("Configuration options");
common.add_options()
("duration", bpo::value<uint32_t>(&args->test_duration_sec)->default_value(10), "Duration (sec)")
("sdu_gen_delay", bpo::value<uint32_t>(&args->sdu_gen_delay_usec)->default_value(10), "SDU generation delay (usec)")
("pdu_tx_delay", bpo::value<uint32_t>(&args->pdu_tx_delay_usec)->default_value(10), "Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec)")
("error_rate", bpo::value<float>(&args->error_rate)->default_value(0.1), "Rate at which RLC PDUs are dropped")
("reestablish", bpo::value<bool>(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution");
// these options are allowed on the command line
bpo::options_description cmdline_options;
cmdline_options.add(common).add(general);
// parse the command line and store result in vm
bpo::variables_map vm;
bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm);
bpo::notify(vm);
// help option was given - print usage and exit
if (vm.count("help")) {
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
cout << common << endl << general << endl;
exit(0);
}
}
class mac_reader
:public thread
{
public:
mac_reader(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_)
mac_reader(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, uint32_t pdu_tx_delay_usec_)
{
rlc1 = rlc1_;
rlc2 = rlc2_;
fail_rate = fail_rate_;
run_enable = true;
running = false;
pdu_tx_delay_usec = pdu_tx_delay_usec_;
}
void stop()
@ -82,7 +129,7 @@ private:
if(((float)rand()/RAND_MAX > fail_rate) && read>0) {
rlc2->write_pdu(1, pdu->msg, opp_size);
}
usleep(100);
usleep(pdu_tx_delay_usec);
}
running = false;
byte_buffer_pool::get_instance()->deallocate(pdu);
@ -91,6 +138,7 @@ private:
rlc_interface_mac *rlc1;
rlc_interface_mac *rlc2;
float fail_rate;
uint32_t pdu_tx_delay_usec;
bool run_enable;
bool running;
@ -100,9 +148,9 @@ class mac_dummy
:public srslte::mac_interface_timers
{
public:
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_)
:r1(rlc1_, rlc2_, fail_rate_)
,r2(rlc2_, rlc1_, fail_rate_)
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, uint32_t pdu_tx_delay)
:r1(rlc1_, rlc2_, fail_rate_, pdu_tx_delay)
,r2(rlc2_, rlc1_, fail_rate_, pdu_tx_delay)
{
}
@ -140,12 +188,13 @@ class rlc_am_tester
,public thread
{
public:
rlc_am_tester(rlc_interface_pdcp *rlc_, std::string name_=""){
rlc_am_tester(rlc_interface_pdcp *rlc_, std::string name_, uint32_t sdu_gen_delay_usec_){
rlc = rlc_;
run_enable = true;
running = false;
rx_pdus = 0;
name = name_;
sdu_gen_delay_usec = sdu_gen_delay_usec_;
}
void stop()
@ -191,7 +240,7 @@ private:
pdu->N_bytes = 1500;
pdu->msg[0] = sn++;
rlc->write_sdu(1, pdu);
usleep(100);
usleep(sdu_gen_delay_usec);
}
running = false;
}
@ -202,10 +251,12 @@ private:
std::string name;
uint32_t sdu_gen_delay_usec;
rlc_interface_pdcp *rlc;
};
void stress_test()
void stress_test(stress_test_args_t args)
{
srslte::log_filter log1("RLC_AM_1");
srslte::log_filter log2("RLC_AM_2");
@ -214,14 +265,12 @@ void stress_test()
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
float fail_rate = 0.1;
rlc rlc1;
rlc rlc2;
rlc_am_tester tester1(&rlc1, "tester1");
rlc_am_tester tester2(&rlc2, "tester2");
mac_dummy mac(&rlc1, &rlc2, fail_rate);
rlc_am_tester tester1(&rlc1, "tester1", args.sdu_gen_delay_usec);
rlc_am_tester tester2(&rlc2, "tester2", args.sdu_gen_delay_usec);
mac_dummy mac(&rlc1, &rlc2, args.error_rate, args.pdu_tx_delay_usec);
ue_interface ue;
rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0);
@ -245,7 +294,14 @@ void stress_test()
tester2.start(7);
mac.start();
usleep(100e6);
for (uint32_t i = 0; i < args.test_duration_sec; i++) {
// if enabled, mimic reestablishment every second
if (args.reestablish) {
rlc1.reestablish();
rlc2.reestablish();
}
usleep(1e6);
}
tester1.stop();
tester2.stop();
@ -254,6 +310,9 @@ void stress_test()
int main(int argc, char **argv) {
stress_test();
stress_test_args_t args;
parse_args(&args, argc, argv);
stress_test(args);
byte_buffer_pool::get_instance()->cleanup();
}

@ -13,6 +13,8 @@
# mme_addr: IP address of MME for S1 connnection
# gtp_bind_addr: Local IP address to bind for GTP connection
# n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100)
# tm: Transmission mode 1-4 (TM1 default)
# nof_ports: Number of Tx ports (1 port default, set to 2 for TM2/3/4)
#
#####################################################################
[enb]
@ -25,6 +27,9 @@ mnc = 01
mme_addr = 127.0.1.100
gtp_bind_addr = 127.0.0.1
n_prb = 50
#tm = 4
#nof_ports = 2
#####################################################################
# eNB configuration files

@ -104,8 +104,6 @@ void txrx::run_thread()
log_h->info("Starting RX/TX thread nof_prb=%d, sf_len=%d\n",worker_com->cell.nof_prb, sf_len);
// Start streaming RX samples
radio_h->start_rx();
// Set TTI so that first TX is at tti=0
tti = 10235;

@ -196,6 +196,8 @@ private:
is_initiated = false;
ack = false;
bzero(&cur_grant, sizeof(Tgrant));
payload_buffer_ptr = NULL;
pthread_mutex_init(&mutex, NULL);
}
~dl_tb_process() {
@ -220,16 +222,24 @@ private:
}
void reset(void) {
pthread_mutex_lock(&mutex);
is_first_tb = true;
ack = false;
if (payload_buffer_ptr) {
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
payload_buffer_ptr = NULL;
}
bzero(&cur_grant, sizeof(Tgrant));
if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer);
}
pthread_mutex_unlock(&mutex);
}
void new_grant_dl(Tgrant grant, Taction *action) {
pthread_mutex_lock(&mutex);
// Compute RV for BCCH when not specified in PDCCH format
if (pid == HARQ_BCCH_PID && grant.rv[tid] == -1) {
uint32_t k;
@ -253,14 +263,14 @@ private:
n_retx = 0;
}
// If data has not yet been successfully decoded
if (!ack) {
// Save grant
grant.last_ndi[tid] = cur_grant.ndi[tid];
grant.last_tti = cur_grant.tti;
memcpy(&cur_grant, &grant, sizeof(Tgrant));
// If data has not yet been successfully decoded
if (!ack) {
// Instruct the PHY To combine the received data and attempt to decode it
if (pid == HARQ_BCCH_PID) {
payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]);
@ -271,6 +281,7 @@ private:
if (!action->payload_ptr[tid]) {
action->decode_enabled[tid] = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
pthread_mutex_unlock(&mutex);
return;
}
action->decode_enabled[tid]= true;
@ -281,7 +292,8 @@ private:
} else {
action->default_ack[tid] = true;
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK (grant_tti=%d, ndi=%d, sz=%d)\n",
pid, cur_grant.tti, cur_grant.ndi[tid], cur_grant.n_bytes[tid]);
}
if (pid == HARQ_BCCH_PID || harq_entity->timer_aligment_timer->is_expired()) {
@ -298,9 +310,12 @@ private:
Debug("Generating ACK\n");
}
}
pthread_mutex_unlock(&mutex);
}
void tb_decoded(bool ack_) {
pthread_mutex_lock(&mutex);
ack = ack_;
if (ack) {
if (pid == HARQ_BCCH_PID) {
@ -331,11 +346,15 @@ private:
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
}
payload_buffer_ptr = NULL;
Info("DL %d (TB %d): %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n",
pid, tid, is_new_transmission ? "newTX" : "reTX ",
cur_grant.n_bytes[tid], cur_grant.rv[tid], ack ? "OK" : "KO",
cur_grant.ndi[tid], cur_grant.last_ndi[tid], cur_grant.tti, cur_grant.last_tti);
pthread_mutex_unlock(&mutex);
if (ack && pid == HARQ_BCCH_PID) {
reset();
}
@ -363,6 +382,8 @@ private:
return is_new_transmission;
}
pthread_mutex_t mutex;
bool is_initiated;
dl_harq_entity *harq_entity;
srslte::log *log_h;

@ -162,14 +162,25 @@ private:
void timer_alignment_expire();
srslte::timers timers;
// pointer to MAC PCAP object
srslte::mac_pcap* pcap;
bool is_first_ul_grant;
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:

@ -104,6 +104,7 @@ private:
/* Msg3 Buffer */
static const uint32_t MSG3_BUFF_SZ = 1024;
uint8_t msg3_buff[MSG3_BUFF_SZ];
uint8_t *msg3_buff_start_pdu;
/* PDU Buffer */
srslte::sch_pdu pdu_msg;

@ -246,7 +246,6 @@ private:
} else {
Warning("UL RAR grant available but no Msg3 on buffer\n");
}
printf("Transmitted Msg3\n");
// Normal UL grant
} else {

@ -61,9 +61,8 @@ public:
void reset_sync();
void cell_search_start();
void cell_search_stop();
void cell_search_next(bool reset = false);
bool cell_select(uint32_t earfcn, srslte_cell_t cell);
void cell_select(uint32_t earfcn, srslte_cell_t cell);
bool cell_handover(srslte_cell_t cell);
void meas_reset();
@ -95,7 +94,6 @@ private:
void reset();
void radio_error();
bool wait_radio_reset();
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
void run_thread();
@ -104,14 +102,11 @@ private:
bool set_cell();
void cell_search_inc();
void resync_sfn(bool is_connected = false, bool rx_now = false);
bool stop_sync();
void cell_reselect();
void stop_rx();
void start_rx(bool now = false);
bool radio_is_rx;
uint32_t new_earfcn;
srslte_cell_t new_cell;
bool radio_is_resetting;
bool running;
// Class to run cell search
@ -167,13 +162,14 @@ private:
typedef enum {IDLE, MEASURE_OK, ERROR} ret_code;
~measure();
void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, srslte::radio *radio_h,
void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h,
uint32_t nof_rx_antennas, uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES);
void reset();
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, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
float rssi();
float rsrp();
float rsrq();
float snr();
@ -183,7 +179,6 @@ private:
srslte::log *log_h;
srslte_ue_dl_t ue_dl;
cf_t *buffer[SRSLTE_MAX_PORTS];
srslte::radio *radio_h;
uint32_t cnt;
uint32_t nof_subframes;
uint32_t current_prb;
@ -235,7 +230,7 @@ private:
void write(uint32_t tti, cf_t *data, uint32_t nsamples);
private:
void run_thread();
const static int INTRA_FREQ_MEAS_LEN_MS = 20;
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;
@ -303,17 +298,18 @@ private:
const static uint32_t NOF_IN_SYNC_SF = 100;
// State for primary cell
enum {
typedef enum {
IDLE = 0,
CELL_SEARCH,
CELL_SELECT,
CELL_RESELECT,
CELL_MEASURE,
CELL_CAMP,
IDLE_RX
} phy_state;
} phy_state_t;
phy_state_t phy_state, prev_state;
bool is_in_idle, is_in_idle_rx;
bool is_in_idle;
// Sampling rate mode (find is 1.96 MHz, camp is the full cell BW)
enum {
@ -335,7 +331,6 @@ private:
float ul_dl_factor;
uint32_t current_earfcn;
int cur_earfcn_index;
bool cell_search_in_progress;
float dl_freq;
float ul_freq;

@ -120,6 +120,7 @@ private:
srslte::trace<uint32_t> tr_exec;
bool trace_enabled;
pthread_mutex_t mutex;
/* Common objects */
phch_common *phy;

@ -85,9 +85,8 @@ public:
void sync_reset();
void configure_ul_params(bool pregen_disabled = false);
void cell_search_start();
void cell_search_stop();
void cell_search_next();
bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell);
void cell_select(uint32_t earfcn, srslte_cell_t phy_cell);
bool cell_handover(srslte_cell_t cell);
void meas_reset();

@ -110,8 +110,6 @@ private:
srslte::log_filter gw_log;
srslte::log_filter usim_log;
srslte::byte_buffer_pool *pool;
all_args_t *args;
bool started;

@ -146,7 +146,7 @@ class ue_base
{
public:
ue_base();
virtual ~ue_base() {}
virtual ~ue_base();
static ue_base* get_instance(srsue_instance_type_t type);
@ -173,6 +173,9 @@ public:
std::string get_build_mode();
std::string get_build_info();
std::string get_build_string();
private:
srslte::byte_buffer_pool *pool;
};
} // namespace srsue

@ -37,6 +37,7 @@
#include "srslte/common/security.h"
#include "srslte/common/threads.h"
#include <math.h>
#include <map>
#include <queue>
@ -65,14 +66,16 @@ class cell_t
return earfcn == this->earfcn && pci == phy_cell.id;
}
bool greater(cell_t *x) {
return x->rsrp > rsrp;
return rsrp > x->rsrp;
}
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
if (has_valid_sib1) {
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) {
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) {
return true;
}
}
}
return false;
}
cell_t() {
@ -80,6 +83,7 @@ class cell_t
cell_t(tmp, 0, 0);
}
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
gettimeofday(&last_update, NULL);
this->has_valid_sib1 = false;
this->has_valid_sib2 = false;
this->has_valid_sib3 = false;
@ -94,14 +98,108 @@ class cell_t
bzero(&sib13, sizeof(sib13));
}
uint32_t earfcn;
uint32_t get_earfcn() {
return earfcn;
}
uint32_t get_pci() {
return phy_cell.id;
}
void set_rsrp(float rsrp) {
if (~isnan(rsrp)) {
this->rsrp = rsrp;
}
in_sync = true;
gettimeofday(&last_update, NULL);
}
float get_rsrp() {
return rsrp;
}
void set_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1) {
memcpy(&this->sib1, sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT));
has_valid_sib1 = true;
}
void set_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
memcpy(&this->sib2, sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
has_valid_sib2 = true;
}
void set_sib3(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3) {
memcpy(&this->sib3, sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
has_valid_sib3 = true;
}
void set_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) {
memcpy(&this->sib13, sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT));
has_valid_sib13 = true;
}
uint32_t timeout_secs(struct timeval now) {
struct timeval t[3];
memcpy(&t[2], &now, sizeof(struct timeval));
memcpy(&t[1], &last_update, sizeof(struct timeval));
get_time_interval(t);
return t[0].tv_sec;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1ptr() {
return &sib1;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2ptr() {
return &sib2;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() {
return &sib3;
}
uint32_t get_cell_id() {
return sib1.cell_id;
}
bool has_sib1() {
return has_valid_sib1;
}
bool has_sib2() {
return has_valid_sib2;
}
bool has_sib3() {
return has_valid_sib3;
}
bool has_sib13() {
return has_valid_sib13;
}
uint16_t get_mcc() {
if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) {
return sib1.plmn_id[0].id.mcc;
}
}
return 0;
}
uint16_t get_mnc() {
if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) {
return sib1.plmn_id[0].id.mnc;
}
}
return 0;
}
srslte_cell_t phy_cell;
bool in_sync;
private:
float rsrp;
uint32_t earfcn;
struct timeval last_update;
bool has_valid_sib1;
bool has_valid_sib2;
bool has_valid_sib3;
bool has_valid_sib13;
bool in_sync;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
@ -157,7 +255,7 @@ public:
void in_sync();
void out_of_sync();
void earfcn_end();
void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
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
@ -227,7 +325,7 @@ private:
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;
uint32_t select_cell_timeout;
static const uint32_t RRC_SELECT_CELL_TIMEOUT = 2000;
static const uint32_t RRC_SELECT_CELL_TIMEOUT = 1000;
uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32];
@ -274,6 +372,7 @@ private:
}
// List of strongest neighbour cell
const static int NEIGHBOUR_TIMEOUT = 5;
const static int NOF_NEIGHBOUR_CELLS = 8;
std::vector<cell_t*> neighbour_cells;
cell_t *serving_cell;
@ -285,6 +384,9 @@ private:
bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
bool add_neighbour_cell(cell_t *cell);
void sort_neighbour_cells();
void clean_neighbours();
std::vector<cell_t*>::iterator delete_neighbour(std::vector<cell_t*>::iterator it);
void delete_neighbour(uint32_t cell_idx);
typedef enum {
SI_ACQUIRE_IDLE = 0,
@ -315,6 +417,7 @@ private:
void run_tti(uint32_t tti);
bool timer_expired(uint32_t timer_id);
void ho_finish();
void delete_report(uint32_t earfcn, uint32_t pci);
private:
const static int NOF_MEASUREMENTS = 3;

@ -33,6 +33,7 @@ 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,
@ -44,11 +45,14 @@ typedef enum {
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"};
} // namespace srsue

@ -165,7 +165,14 @@ void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg)
// Route logical channel
if (route_pdu) {
Info("Delivering PDU for lcid=%d, %d bytes\n", pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_payload_size());
if (pdu_msg->get()->get_payload_size() < MAX_PDU_LEN) {
rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_payload_size());
} else {
char tmp[1024];
srslte_vec_sprint_hex(tmp, pdu_msg->get()->get_sdu_ptr(), 32);
Error("PDU size %d exceeds maximum PDU buffer size, lcid=%d, hex=[%s]\n",
pdu_msg->get()->get_payload_size(), pdu_msg->get()->get_sdu_lcid(), tmp);
}
}
} else {
// Process MAC Control Element

@ -82,6 +82,7 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac
started = true;
start(MAC_MAIN_THREAD_PRIO);
mactimers.init(&timers, log_h);
return started;
}
@ -94,6 +95,7 @@ void mac::stop()
ttisync.increase();
pdu_process_thread.stop();
wait_thread_finish();
mactimers.stop();
}
void mac::start_pcap(srslte::mac_pcap* pcap_)
@ -148,6 +150,17 @@ 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;
@ -165,7 +178,6 @@ void mac::run_thread() {
tti = ttisync.wait();
log_h->step(tti);
timers.step_all();
// Step all procedures
bsr_procedure.step(tti);

@ -47,6 +47,7 @@ mux::mux(uint8_t nof_harq_proc_) : pdu_msg(MAX_NOF_SUBHEADERS), pid_has_bsr(nof_
rlc = NULL;
bsr_procedure = NULL;
phr_procedure = NULL;
msg3_buff_start_pdu = NULL;
msg3_flush();
}
@ -347,6 +348,7 @@ void mux::msg3_flush()
msg3_has_been_transmitted = false;
msg3_pending = false;
bzero(msg3_buff, sizeof(MSG3_BUFF_SZ));
msg3_buff_start_pdu = NULL;
}
bool mux::msg3_is_transmitted()
@ -366,19 +368,22 @@ bool mux::msg3_is_pending() {
uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
{
if (pdu_sz < MSG3_BUFF_SZ - 32) {
uint8_t* msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0);
if (!msg3_buff_start_pdu) {
msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0);
if (!msg3_buff_start_pdu) {
Error("Moving PDU from Mux unit to Msg3 buffer\n");
return NULL;
}
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true;
msg3_pending = false;
return payload;
}
} else {
Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32);
return NULL;
}
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true;
return payload;
}

@ -159,11 +159,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
"Pregenerate uplink signals after attach. Improves CPU performance.")
("expert.rssi_sensor_enabled",
bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(true),
bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(false),
"Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault")
("expert.rx_gain_offset",
bpo::value<float>(&args->expert.phy.rx_gain_offset)->default_value(10),
bpo::value<float>(&args->expert.phy.rx_gain_offset)->default_value(62),
"RX Gain offset to add to rx_gain to correct RSRP value")
("expert.prach_gain",

@ -355,13 +355,16 @@ void phch_common::reset() {
void phch_common::reset_ul()
{
/*
is_first_tx = true;
is_first_of_burst = true;
for (uint32_t i=0;i<nof_mutex;i++) {
pthread_mutex_trylock(&tx_mutex[i]);
pthread_mutex_unlock(&tx_mutex[i]);
}
radio_h->tx_end();
*/
}
}

@ -91,7 +91,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma
sfn_p.init(&ue_sync, sf_buffer, log_h);
// Initialize measurement class for the primary cell
measure_p.init(sf_buffer, log_h, radio_h, nof_rx_antennas);
measure_p.init(sf_buffer, log_h, nof_rx_antennas);
// Start intra-frequency measurement
intra_freq_meas.init(worker_com, rrc, log_h);
@ -132,9 +132,7 @@ void phch_recv::reset()
next_offset = 0;
cell_is_set = false;
srate_mode = SRATE_NONE;
cell_search_in_progress = false;
current_earfcn = 0;
radio_is_resetting = false;
sfn_p.reset();
measure_p.reset();
search_p.reset();
@ -144,33 +142,16 @@ void phch_recv::reset()
void phch_recv::radio_error()
{
log_h->error("SYNC: Receiving from radio.\n");
phy_state = IDLE;
radio_is_resetting=true;
// Need to find a method to effectively reset radio, reloading the driver does not work
//radio_h->reset();
radio_h->stop();
fprintf(stdout, "Error while receiving samples. Restart srsUE\n");
exit(-1);
phy_state = CELL_SEARCH;
reset();
radio_is_resetting=false;
// 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);
}
bool phch_recv::wait_radio_reset() {
int cnt=0;
while(cnt < 20 && radio_is_resetting) {
sleep(1);
cnt++;
}
return radio_is_resetting;
}
void phch_recv::set_agc_enable(bool enable)
{
do_agc = enable;
@ -265,19 +246,6 @@ bool phch_recv::set_cell() {
return cell_is_set;
}
void phch_recv::resync_sfn(bool is_connected, bool now) {
if (!now) {
wait_radio_reset();
stop_rx();
}
start_rx(now);
sfn_p.reset();
Info("SYNC: Starting SFN synchronization\n");
phy_state = is_connected?CELL_RESELECT:CELL_SELECT;
}
void phch_recv::set_earfcn(std::vector<uint32_t> earfcn) {
this->earfcn = earfcn;
}
@ -287,42 +255,24 @@ void phch_recv::force_freq(float dl_freq, float ul_freq) {
this->ul_freq = ul_freq;
}
bool phch_recv::stop_sync() {
wait_radio_reset();
if (phy_state == IDLE && is_in_idle) {
return true;
} else {
Info("SYNC: Going to IDLE\n");
phy_state = IDLE;
int cnt = 0;
while (!is_in_idle && cnt < 100) {
usleep(10000);
cnt++;
}
if (!is_in_idle) {
Warning("SYNC: Could not go to IDLE\n");
}
return is_in_idle;
}
}
void phch_recv::reset_sync() {
Warning("SYNC: Resetting sync, cell_search_in_progress=%s\n", cell_search_in_progress?"yes":"no");
sfn_p.reset();
search_p.reset();
measure_p.reset();
srslte_ue_sync_reset(&ue_sync);
resync_sfn(true, true);
Info("----- PHY RESET----\n");
phy_state = CELL_SELECT;
}
void phch_recv::cell_search_inc()
{
Info("cell_search_inc, cur_idx=%d, size=%d\n", cur_earfcn_index, earfcn.size());
cur_earfcn_index++;
if (cur_earfcn_index >= 0) {
if (cur_earfcn_index >= (int) earfcn.size()) {
cur_earfcn_index = 0;
phy_state = IDLE;
rrc->earfcn_end();
} else {
Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size());
@ -330,23 +280,16 @@ void phch_recv::cell_search_inc()
current_earfcn = earfcn[cur_earfcn_index];
set_frequency();
}
phy_state = CELL_SEARCH;
}
}
}
void phch_recv::cell_search_next(bool reset) {
if (cell_search_in_progress || reset) {
cell_search_in_progress = false;
if (!stop_sync()) {
log_h->warning("SYNC: Couldn't stop PHY\n");
}
if (reset) {
cur_earfcn_index = -1;
}
cell_search_inc();
phy_state = CELL_SEARCH;
cell_search_in_progress = true;
}
}
void phch_recv::cell_search_start() {
@ -363,14 +306,6 @@ void phch_recv::cell_search_start() {
}
}
void phch_recv::cell_search_stop() {
Info("SYNC: Stopping Cell Search procedure...\n");
if (!stop_sync()) {
Error("SYNC: Stopping cell search\n");
}
cell_search_in_progress = false;
}
bool phch_recv::cell_handover(srslte_cell_t cell)
{
int cnt = 0;
@ -383,20 +318,21 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
bool ret = false;
this->cell = cell;
Info("Cell HO: Stopping sync with current cell\n");
worker_com->reset_ul();
phy_state = IDLE_RX;
phy_state = IDLE;
cnt = 0;
while(!is_in_idle_rx && cnt<20) {
while(!is_in_idle && cnt<20) {
usleep(1000);
cnt++;
}
if (is_in_idle_rx) {
for(uint32_t i=0;i<workers_pool->get_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()) {
//resync_sfn(true, true);
sfn_p.reset();
phy_state = CELL_RESELECT;
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);
@ -409,31 +345,35 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
return ret;
}
bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
/* interface from higher layers to select a new cell */
void phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
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;
Info("Reset from cell_reselect\n");
reset_sync();
// Check if we are already camping in this cell
// 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\n", earfcn);
cell_search_in_progress = false;
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");
}
if (phy_state < CELL_SELECT) {
resync_sfn();
}
return true;
} else {
cell_search_in_progress = false;
if (!stop_sync()) {
log_h->warning("Still not in idle\n");
}
if (earfcn != current_earfcn) {
if (set_frequency()) {
log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id);
return false;
}
current_earfcn = earfcn;
}
@ -443,13 +383,7 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
if (set_cell()) {
log_h->info("Cell Select: Synchronizing on cell...\n");
resync_sfn();
usleep(500000); // Time offset we set start_rx to start receiving samples
return true;
}
return false;
}
}
@ -514,22 +448,6 @@ void phch_recv::set_sampling_rate()
}
}
void phch_recv::stop_rx() {
if (radio_is_rx) {
Info("SYNC: Stopping RX streaming\n");
radio_h->stop_rx();
}
radio_is_rx = false;
}
void phch_recv::start_rx(bool now) {
if (!radio_is_rx) {
Info("SYNC: Starting RX streaming\n");
radio_h->start_rx(now);
}
radio_is_rx = true;
}
uint32_t phch_recv::get_current_tti() {
return tti;
}
@ -584,28 +502,29 @@ void phch_recv::run_thread()
uint32_t sf_idx = 0;
phy_state = IDLE;
is_in_idle = true;
is_in_idle_rx = false;
cf_t *dummy_buffer[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
dummy_buffer[i] = (cf_t*) malloc(sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
}
while (running)
{
if (phy_state != IDLE) {
is_in_idle = false;
Debug("SYNC: state=%d\n", phy_state);
}
if (phy_state != IDLE_RX) {
is_in_idle_rx = 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:
if (cell_search_in_progress)
{
switch(search_p.run(&cell))
{
case search::CELL_FOUND:
@ -616,28 +535,28 @@ void phch_recv::run_thread()
}
if (set_cell()) {
set_sampling_rate();
resync_sfn();
phy_state = CELL_SELECT;
}
break;
case search::CELL_NOT_FOUND:
if (cell_search_in_progress) {
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 (!cell_search_in_progress) {
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();
@ -645,13 +564,8 @@ void phch_recv::run_thread()
}
break;
case sfn_sync::TIMEOUT:
if (cell_search_in_progress) {
log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n");
phy_state = CELL_SEARCH;
} else {
log_h->warning("SYNC: Timeout while synchronizing SFN. Reselecting cell\n");
resync_sfn(true, true);
}
break;
case sfn_sync::IDLE:
break;
@ -661,12 +575,21 @@ void phch_recv::run_thread()
}
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_found(earfcn[cur_earfcn_index], cell, measure_p.rsrp());
rrc->cell_camping(earfcn[cur_earfcn_index], cell, measure_p.rsrp());
break;
case measure::IDLE:
break;
@ -718,10 +641,11 @@ void phch_recv::run_thread()
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");
worker_com->reset_ul();
}
radio_h->tx_end();
}*/
// Check if we need to TX a PRACH
if (prach_buffer->is_ready_to_send(tti)) {
@ -738,7 +662,9 @@ void phch_recv::run_thread()
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]);
}
if (srslte_cell_isvalid(&cell)) {
intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
break;
case 0:
Warning("SYNC: Out-of-sync detected in PSS/SSS\n");
@ -756,28 +682,18 @@ void phch_recv::run_thread()
}
break;
case IDLE:
if (!is_in_idle) {
stop_rx();
}
is_in_idle = true;
usleep(1000);
break;
case IDLE_RX:
if (!worker) {
worker = (phch_worker *) workers_pool->wait_worker(tti);
}
is_in_idle_rx = true;
if (worker) {
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
buffer[i] = worker->get_buffer(i);
if (radio_h->is_init()) {
uint32_t nsamples = 1920;
if (current_srate > 0) {
nsamples = current_srate/1000;
}
if (!radio_h->rx_now(buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), NULL)) {
Error("SYNC: Receiving from radio while in IDLE_RX\n");
if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) {
printf("SYNC: Receiving from radio while in IDLE_RX\n");
}
} else {
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here
running = false;
usleep(1000);
}
is_in_idle = true;
break;
}
@ -897,8 +813,8 @@ 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);
Info("SYNC: Setting Cell Search sampling rate\n");
}
p->start_rx();
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
uint32_t max_peak_cell = 0;
@ -918,7 +834,6 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
Error("SYNC: Error decoding MIB: Error searching PSS\n");
return ERROR;
} else if (ret == 0) {
p->stop_rx();
Info("SYNC: Could not find any cell in this frequency\n");
return CELL_NOT_FOUND;
}
@ -946,8 +861,6 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
ret = srslte_ue_mib_sync_decode(&ue_mib_sync,
40,
bch_payload, &cell->nof_ports, &sfn_offset);
p->stop_rx();
if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, cell, NULL);
@ -1022,7 +935,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
srslte_ue_sync_decode_sss_on_track(ue_sync, true);
int ret = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
if (ret < 0) {
Error("SYNC: Error calling ue_sync_get_buffer");
Error("SYNC: Error calling ue_sync_get_buffer.\n");
return ERROR;
}
@ -1060,7 +973,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++;
@ -1080,10 +993,9 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
/*********
* Measurement class
*/
void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, srslte::radio *radio_h, uint32_t nof_rx_antennas, uint32_t nof_subframes)
void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subframes)
{
this->radio_h = radio_h;
this->log_h = log_h;
this->nof_subframes = nof_subframes;
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
@ -1118,16 +1030,20 @@ void phch_recv::measure::set_cell(srslte_cell_t cell)
reset();
}
float phch_recv::measure::rssi() {
return 10*log10(mean_rssi);
}
float phch_recv::measure::rsrp() {
return mean_rsrp;
return 10*log10(mean_rsrp) + 30 - rx_gain_offset;
}
float phch_recv::measure::rsrq() {
return mean_rsrq;
return 10*log10(mean_rsrq);
}
float phch_recv::measure::snr() {
return mean_snr;
return 10*log10(mean_snr);
}
uint32_t phch_recv::measure::frame_st_idx() {
@ -1228,10 +1144,10 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
return ERROR;
}
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset;
float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest));
float rssi = 10*log10(srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb))) + 30;
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;
@ -1250,17 +1166,6 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
cnt, nof_subframes, sf_idx, rsrp, snr);
if (cnt >= nof_subframes) {
// Calibrate RSRP if no gain offset measurements
if (fabsf(rx_gain_offset) < 1.0 && radio_h) {
float temporal_offset = 0;
if (radio_h->has_rssi()) {
temporal_offset = mean_rssi - radio_h->get_rssi() + 30;
} else {
temporal_offset = radio_h->get_rx_gain();
}
mean_rsrp -= temporal_offset;
}
return MEASURE_OK;
} else {
return IDLE;
@ -1289,7 +1194,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);
input_cfo_corrected = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*15*max_sf_size);
measure_p.init(sf_buffer, log_h, NULL, 1, max_sf_window);
measure_p.init(sf_buffer, log_h, 1, max_sf_window);
//do this different we don't need all this search window.
if(srslte_sync_init(&sync_find, max_sf_window*max_sf_size, 5*max_sf_size, max_fft_sz)) {
@ -1594,6 +1499,7 @@ 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);

@ -140,29 +140,35 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph
mem_initiated = true;
pthread_mutex_init(&mutex, NULL);
return true;
}
bool phch_worker::set_cell(srslte_cell_t cell_)
{
bool ret = false;
pthread_mutex_lock(&mutex);
if (cell.id != cell_.id || !cell_initiated) {
memcpy(&cell, &cell_, sizeof(srslte_cell_t));
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
Error("Initiating UE DL\n");
return false;
goto unlock;
}
if (srslte_ue_ul_set_cell(&ue_ul, cell)) {
Error("Initiating UE UL\n");
return false;
goto unlock;
}
srslte_ue_ul_set_normalization(&ue_ul, true);
srslte_ue_ul_set_cfo_enable(&ue_ul, true);
cell_initiated = true;
}
return true;
ret = true;
unlock:
pthread_mutex_unlock(&mutex);
return ret;
}
cf_t* phch_worker::get_buffer(uint32_t antenna_idx)
@ -244,6 +250,8 @@ void phch_worker::work_imp()
return;
}
pthread_mutex_lock(&mutex);
Debug("TTI %d running\n", tti);
#ifdef LOG_EXECTIME
@ -402,7 +410,7 @@ void phch_worker::work_imp()
update_measurements();
if (chest_ok) {
if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -30.0) {
if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -20.0) {
log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), phy->avg_rsrp_dbm);
chest_loop->in_sync();
@ -413,6 +421,8 @@ void phch_worker::work_imp()
}
}
pthread_mutex_unlock(&mutex);
/* Tell the plotting thread to draw the plots */
#ifdef ENABLE_GUI
if ((int) get_id() == plot_worker_id) {
@ -1211,6 +1221,7 @@ void phch_worker::enable_pregen_signals(bool enabled)
void phch_worker::set_ul_params(bool pregen_disabled)
{
phy_interface_rrc::phy_cfg_common_t *common = &phy->config->common;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &phy->config->dedicated;
@ -1380,7 +1391,7 @@ void phch_worker::update_measurements()
/* Only worker 0 reads the RSSI sensor every ~1-nof_cores s */
if (get_id() == 0) {
if (rssi_read_cnt) {
if (!rssi_read_cnt) {
if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) {
phy->last_radio_rssi = phy->get_radio()->get_rssi();
phy->rx_gain_offset = phy->avg_rssi_dbm - phy->last_radio_rssi + 30;

@ -256,11 +256,6 @@ void phy::cell_search_start()
sf_recv.cell_search_start();
}
void phy::cell_search_stop()
{
sf_recv.cell_search_stop();
}
void phy::cell_search_next()
{
sf_recv.cell_search_next();
@ -282,9 +277,9 @@ int phy::meas_stop(uint32_t earfcn, int pci) {
return sf_recv.meas_stop(earfcn, pci);
}
bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
void phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
{
return sf_recv.cell_select(earfcn, phy_cell);
sf_recv.cell_select(earfcn, phy_cell);
}
bool phy::cell_handover(srslte_cell_t cell) {
@ -366,8 +361,6 @@ void phy::reset()
workers[i].reset();
}
workers_common.reset();
usleep(4000);
workers_common.reset_ul();
}
uint32_t phy::get_current_tti()

@ -40,12 +40,10 @@ namespace srsue{
ue::ue()
:started(false)
{
pool = byte_buffer_pool::get_instance();
}
ue::~ue()
{
byte_buffer_pool::cleanup();
}
bool ue::init(all_args_t *args_)
@ -306,8 +304,13 @@ void ue::rf_msg(srslte_rf_error_t error)
{
ue_base *ue = ue_base::get_instance(LTE);
ue->handle_rf_msg(error);
if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) {
if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) {
ue->radio_overflow();
} else
if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_RX) {
ue->stop();
ue->cleanup();
exit(-1);
}
}

@ -64,6 +64,12 @@ ue_base::ue_base() {
// load FFTW wisdom
srslte_dft_load();
pool = byte_buffer_pool::get_instance();
}
ue_base::~ue_base() {
byte_buffer_pool::cleanup();
}
void ue_base::cleanup(void)

@ -161,6 +161,7 @@ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_
// 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());
@ -168,10 +169,13 @@ void nas::plmn_search_end() {
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]);
} else {
nas_log->debug("Finished searching PLMN in current EARFCN set but no networks were found.\n");
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();
}
}
}

@ -54,6 +54,7 @@ rrc::rrc()
n310_cnt = 0;
n311_cnt = 0;
serving_cell = new cell_t();
neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS);
}
rrc::~rrc()
@ -168,6 +169,7 @@ void rrc::set_args(rrc_args_t *args) {
void rrc::run_thread() {
uint32_t failure_test = 0;
uint32_t cell_clean_cnt = 0;
while (thread_running) {
@ -185,6 +187,7 @@ void rrc::run_thread() {
sleep(1);
rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n");
plmn_select_rrc(selected_plmn_id);
connection_requested = true;
}
// If not camping on a cell
} else {
@ -200,15 +203,18 @@ void rrc::run_thread() {
// 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");
phy->cell_search_stop();
sleep(1);
rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n");
plmn_select_timeout = 0;
phy->cell_search_start();
rrc_log->console("\nRRC PLMN Search: timeout expired.\n");
state = RRC_STATE_IDLE;
}
break;
case RRC_STATE_CELL_SELECTING:
@ -217,26 +223,25 @@ void rrc::run_thread() {
* Cell is selected when all SIBs downloaded or applied.
*/
if (phy->sync_status()) {
if (!serving_cell->has_valid_sib1) {
if (!serving_cell->has_sib1()) {
si_acquire_state = SI_ACQUIRE_SIB1;
sysinfo_index = 0;
} else if (!serving_cell->has_valid_sib2) {
} else if (!serving_cell->has_sib2()) {
si_acquire_state = SI_ACQUIRE_SIB2;
} else {
apply_sib2_configs(&serving_cell->sib2);
apply_sib2_configs(serving_cell->sib2ptr());
si_acquire_state = SI_ACQUIRE_IDLE;
state = RRC_STATE_CELL_SELECTED;
}
}
// Don't time out during restablishment (T311 running)
if (!mac_timers->timer_get(t311)->is_running()) {
// Don't time out during reestablishment (T311 running)
if (!mac_timers->timer_get(t311)->is_running() || !phy->sync_status()) {
select_cell_timeout++;
if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) {
rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n");
plmn_select_timeout = 0;
select_cell_timeout = 0;
state = RRC_STATE_PLMN_START;
serving_cell->in_sync = false;
phy->cell_search_start();
}
}
break;
@ -302,6 +307,13 @@ void rrc::run_thread() {
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);
}
}
@ -342,7 +354,7 @@ void rrc::run_si_acquisition_procedure()
tti = mac->get_current_tti();
si_win_start = sib_start_tti(tti, 2, 0, 5);
if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > 20 && srslte_tti_interval(last_win_start, tti) < 1000))
(srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000))
{
last_win_start = si_win_start;
@ -363,24 +375,24 @@ void rrc::run_si_acquisition_procedure()
break;
case SI_ACQUIRE_SIB2:
// Instruct MAC to look for next SIB
if(sysinfo_index < serving_cell->sib1.N_sched_info) {
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
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->sib1.sched_info[sysinfo_index].si_periodicity];
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->sib1.si_window_length];
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length];
if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > period*10 && srslte_tti_interval(last_win_start, tti) < 1000))
(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, win_start=%d, win_len=%d\n",
rrc_log->debug("Instructed MAC to search for system info, win_start=%d, win_len=%d\n",
si_win_start, si_win_len);
}
@ -416,24 +428,15 @@ void rrc::run_si_acquisition_procedure()
*******************************************************************************/
uint16_t rrc::get_mcc() {
if (serving_cell->sib1.N_plmn_ids > 0) {
return serving_cell->sib1.plmn_id[0].id.mcc;
}
return 0;
return serving_cell->get_mcc();
}
uint16_t rrc::get_mnc() {
if (serving_cell->sib1.N_plmn_ids > 0) {
return serving_cell->sib1.plmn_id[0].id.mnc;
}
return 0;
return serving_cell->get_mnc();
}
void rrc::plmn_search() {
rrc_log->info("Starting PLMN search procedure\n");
state = RRC_STATE_PLMN_SELECTION;
phy->cell_search_start();
plmn_select_timeout = 0;
state = RRC_STATE_PLMN_START;
}
/* This is the NAS interface. When NAS requests to select a PLMN we have to
@ -452,17 +455,30 @@ void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) {
if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) {
rrc_log->info("Already camping on selected PLMN, connecting...\n");
state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} else {
rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str());
// Sort cells according to RSRP
selected_plmn_id = plmn_id;
select_cell_timeout = 0;
state = RRC_STATE_CELL_SELECTING;
if (serving_cell->plmn_equals(selected_plmn_id)) {
phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
} else {
bool found = false;
for (uint32_t i=0;i<neighbour_cells.size() && !found;i++) {
if (neighbour_cells[i]->plmn_equals(selected_plmn_id)) {
rrc_log->info("PLMN Id=%s selected, PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci());
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
found = true;
}
}
if (!found) {
rrc_log->warning("Could not find any cell for the selected PLMN\n");
state = RRC_STATE_IDLE;
return;
}
}
}
state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} else {
rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]);
}
@ -491,7 +507,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
// 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->earfcn, serving_cell->phy_cell.id);
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());
@ -506,7 +522,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
serving_cell = new_serving_cell;
rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n",
cell_idx, serving_cell->earfcn, serving_cell->phy_cell.id, neighbour_cells.size());
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);
@ -520,20 +536,14 @@ void rrc::select_next_cell_in_plmn() {
neighbour_cells[i]->in_sync) // matches S criteria
{
// Try to select Cell
if (phy->cell_select(neighbour_cells[i]->earfcn, neighbour_cells[i]->phy_cell)) {
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
set_serving_cell(i);
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn,
serving_cell->sib1.cell_id);
serving_cell->phy_cell.id, serving_cell->get_earfcn(),
serving_cell->get_cell_id());
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn,
serving_cell->sib1.cell_id);
} else {
// Set to out-of-sync if can't synchronize
neighbour_cells[i]->in_sync = false;
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n",
neighbour_cells[i]->earfcn, neighbour_cells[i]->sib1.cell_id);
}
serving_cell->phy_cell.id, serving_cell->get_earfcn(),
serving_cell->get_cell_id());
return;
}
}
@ -543,7 +553,7 @@ void rrc::select_next_cell_in_plmn() {
void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) {
if (earfcn_i < 0 || pci_i < 0) {
earfcn_i = serving_cell->earfcn;
earfcn_i = serving_cell->get_earfcn();
pci_i = serving_cell->phy_cell.id;
}
@ -560,7 +570,7 @@ 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_eval(rsrp, rsrq);
serving_cell->rsrp = rsrp;
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
@ -573,43 +583,45 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
}
// Verify cell selection criteria with strongest neighbour cell (always first)
if (cell_selection_eval(neighbour_cells[0]->rsrp) &&
neighbour_cells[0]->rsrp > serving_cell->rsrp + 5)
if (neighbour_cells.size() > 1 &&
cell_selection_eval(neighbour_cells[0]->get_rsrp()) &&
neighbour_cells[0]->get_rsrp() > serving_cell->get_rsrp() + 5)
{
set_serving_cell(0);
rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->rsrp);
rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->get_rsrp());
state = RRC_STATE_CELL_SELECTING;
phy->cell_select(serving_cell->earfcn, serving_cell->phy_cell);
phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
}
}
}
void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
/* 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) {
bool found = false;
int cell_idx = -1;
if (serving_cell->equals(earfcn, phy_cell.id)) {
serving_cell->rsrp = rsrp;
serving_cell->in_sync = true;
serving_cell->set_rsrp(rsrp);
found = true;
} else {
// Check if cell is in our list of neighbour cells
cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
if (cell_idx >= 0) {
set_serving_cell(cell_idx);
serving_cell->rsrp = rsrp;
serving_cell->in_sync = true;
serving_cell->set_rsrp(rsrp);
found = true;
}
}
if (found) {
if (!serving_cell->has_valid_sib1) {
if (!serving_cell->has_sib1()) {
si_acquire_state = SI_ACQUIRE_SIB1;
} else if (state == RRC_STATE_PLMN_SELECTION) {
for (uint32_t j = 0; j < serving_cell->sib1.N_plmn_ids; j++) {
nas->plmn_found(serving_cell->sib1.plmn_id[j].id, serving_cell->sib1.tracking_area_code);
for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) {
nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code);
}
usleep(5000);
phy->cell_search_next();
@ -623,7 +635,6 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
phy->cell_search_next();
} else {
set_serving_cell(earfcn, phy_cell.id);
si_acquire_state = SI_ACQUIRE_SIB1;
}
}
@ -631,22 +642,54 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n",
found?"Updating":"Adding",
cell_idx>=0?"neighbour":"serving",
serving_cell->earfcn,
serving_cell->get_earfcn(),
serving_cell->phy_cell.id,
serving_cell->rsrp);
serving_cell->get_rsrp());
}
bool sort_rsrp(cell_t *u1, cell_t *u2) {
return !u1->greater(u2);
return u1->greater(u2);
}
// Sort neighbour cells by decreasing order of RSRP
void rrc::sort_neighbour_cells() {
void rrc::delete_neighbour(uint32_t cell_idx) {
measurements.delete_report(neighbour_cells[cell_idx]->get_earfcn(), neighbour_cells[cell_idx]->get_pci());
delete neighbour_cells[cell_idx];
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end());
}
for (uint32_t i=1;i<neighbour_cells.size();i++) {
if (neighbour_cells[i]->in_sync == false) {
rrc_log->info("Removing neighbour cell PCI=%d, out_of_sync\n", neighbour_cells[i]->phy_cell.id);
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[i]), neighbour_cells.end());
std::vector<cell_t*>::iterator rrc::delete_neighbour(std::vector<cell_t*>::iterator it) {
measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci());
delete (*it);
return neighbour_cells.erase(it);
}
void rrc::clean_neighbours()
{
struct timeval now;
gettimeofday(&now, NULL);
std::vector<cell_t*>::iterator it = neighbour_cells.begin();
while(it != neighbour_cells.end()) {
if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) {
rrc_log->info("Neighbour PCI=%d timed out. Deleting\n", (*it)->get_pci());
it = delete_neighbour(it);
} else {
++it;
}
}
}
// Sort neighbour cells by decreasing order of RSRP
void rrc::sort_neighbour_cells()
{
// Remove out-of-sync cells
std::vector<cell_t*>::iterator it = neighbour_cells.begin();
while(it != neighbour_cells.end()) {
if ((*it)->in_sync == false) {
rrc_log->info("Neighbour PCI=%d is out-of-sync. Deleting\n", (*it)->get_pci());
it = delete_neighbour(it);
} else {
++it;
}
}
@ -654,28 +697,27 @@ void rrc::sort_neighbour_cells() {
char ordered[512];
int n=0;
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->rsrp);
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp());
for (uint32_t i=1;i<neighbour_cells.size();i++) {
n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->phy_cell.id, neighbour_cells[i]->rsrp);
n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp());
}
rrc_log->info("Sorted neighbour cells: %s]\n", ordered);
rrc_log->info("Neighbours: %s]\n", ordered);
}
bool rrc::add_neighbour_cell(cell_t *new_cell) {
bool ret = false;
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS - 1) {
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) {
ret = true;
} else if (!neighbour_cells[neighbour_cells.size()-1]->greater(new_cell)) {
// Delete old one
delete neighbour_cells[neighbour_cells.size()-1];
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[neighbour_cells.size()-1]), neighbour_cells.end());
} else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) {
// Replace old one by new one
delete_neighbour(neighbour_cells.size()-1);
ret = true;
}
if (ret) {
neighbour_cells.push_back(new_cell);
}
rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d\n",
new_cell->earfcn, new_cell->phy_cell.id, neighbour_cells.size());
new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size());
sort_neighbour_cells();
return ret;
}
@ -690,7 +732,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) {
bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
if (earfcn == 0) {
earfcn = serving_cell->earfcn;
earfcn = serving_cell->get_earfcn();
}
// First check if already exists
@ -700,7 +742,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp
// If exists, update RSRP, sort again and return
if (cell_idx >= 0) {
neighbour_cells[cell_idx]->rsrp = rsrp;
neighbour_cells[cell_idx]->set_rsrp(rsrp);
sort_neighbour_cells();
return true;
}
@ -727,10 +769,8 @@ void rrc::earfcn_end() {
// If searching for PLMN, indicate NAS we scanned all frequencies
if (state == RRC_STATE_PLMN_SELECTION) {
nas->plmn_search_end();
} else if (state == RRC_STATE_CELL_SELECTING) {
select_cell_timeout = 0;
rrc_log->info("Starting cell search again\n");
phy->cell_search_start();
} else if (state == RRC_STATE_CONNECTED) {
leave_connected();
}
}
@ -791,11 +831,11 @@ void rrc::out_of_sync() {
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;
phy->sync_reset();
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer\n", N310);
}
}
} else {
@ -822,7 +862,6 @@ void rrc::in_sync() {
void rrc::radio_link_failure() {
// TODO: Generate and store failure report
phy->sync_reset();
rrc_log->warning("Detected Radio-Link Failure\n");
rrc_log->console("Warning: Detected Radio-Link Failure\n");
if (state != RRC_STATE_CONNECTED) {
@ -929,7 +968,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
uint8_t *msg_ptr = varShortMAC;
// ASN.1 encode byte-aligned VarShortMAC-Input
liblte_rrc_pack_cell_identity_ie(serving_cell->sib1.cell_id, &msg_ptr);
liblte_rrc_pack_cell_identity_ie(serving_cell->get_cell_id(), &msg_ptr);
msg_ptr = &varShortMAC[4];
liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr);
msg_ptr = &varShortMAC[4+2];
@ -937,7 +976,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, (4+2+4)*8);
rrc_log->info("Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d\n",
serving_cell->sib1.cell_id, phy->get_current_pci(), crnti);
serving_cell->get_cell_id(), phy->get_current_pci(), crnti);
// Compute MAC-I
uint8_t mac_key[4];
@ -962,7 +1001,6 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
break;
default:
rrc_log->info("Unsupported integrity algorithm during reestablishment\n");
return;
}
// Prepare ConnectionRestalishmentRequest packet
@ -982,6 +1020,7 @@ 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();
state = RRC_STATE_CELL_SELECTING;
}
@ -1065,10 +1104,10 @@ bool rrc::ho_prepare() {
if (pending_mob_reconf) {
rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci);
int target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
int target_cell_idx = find_neighbour_cell(serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci);
if (target_cell_idx < 0) {
rrc_log->console("Received HO command to unknown PCI=%d\n", mob_reconf.mob_ctrl_info.target_pci);
rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci);
return false;
}
@ -1076,7 +1115,7 @@ bool rrc::ho_prepare() {
mac_timers->timer_get(t310)->stop();
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->earfcn) {
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");
}
@ -1095,13 +1134,14 @@ bool rrc::ho_prepare() {
pdcp->reestablish();
rlc->reestablish();
mac->reset();
phy->reset();
// PHY is reset inside cell_handover() function
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]->phy_cell.id);
rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci());
if (!phy->cell_handover(neighbour_cells[target_cell_idx]->phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->phy_cell.id);
rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci());
return false;
}
@ -1177,7 +1217,7 @@ void rrc::ho_failed() {
// Instruct PHY to resync with source PCI
if (!phy->cell_handover(ho_src_cell.phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.phy_cell.id);
rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.get_pci());
return;
}
@ -1302,27 +1342,23 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
rrc_log->info("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) {
memcpy(&serving_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT));
serving_cell->has_valid_sib1 = true;
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_valid_sib2) {
memcpy(&serving_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
serving_cell->has_valid_sib2 = true;
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) {
serving_cell->set_sib2(&dlsch_msg.sibs[i].sib.sib2);
handle_sib2();
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib3) {
memcpy(&serving_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
serving_cell->has_valid_sib3 = true;
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib3()) {
serving_cell->set_sib3(&dlsch_msg.sibs[i].sib.sib3);
handle_sib3();
}else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib13) {
memcpy(&serving_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT));
serving_cell->has_valid_sib13 = true;
}else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib13()) {
serving_cell->set_sib13(&dlsch_msg.sibs[i].sib.sib13);
handle_sib13();
}
}
last_win_start = 0;
if(serving_cell->has_valid_sib2) {
if(serving_cell->has_sib2()) {
sysinfo_index++;
}
}
@ -1330,16 +1366,16 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
void rrc::handle_sib1()
{
rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n",
serving_cell->sib1.cell_id&0xfff,
liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length],
liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[0].si_periodicity]);
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]);
// Print SIB scheduling info
uint32_t i,j;
for(i=0;i<serving_cell->sib1.N_sched_info;i++){
for(j=0;j<serving_cell->sib1.sched_info[i].N_sib_mapping_info;j++){
LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type;
LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1.sched_info[i].si_periodicity;
for(i=0;i<serving_cell->sib1ptr()->N_sched_info;i++){
for(j=0;j<serving_cell->sib1ptr()->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;
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]);
@ -1347,16 +1383,14 @@ void rrc::handle_sib1()
}
// Set TDD Config
if(serving_cell->sib1.tdd) {
phy->set_config_tdd(&serving_cell->sib1.tdd_cnfg);
if(serving_cell->sib1ptr()->tdd) {
phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg);
}
serving_cell->has_valid_sib1 = true;
// Send PLMN and TAC to NAS
std::stringstream ss;
for (uint32_t i = 0; i < serving_cell->sib1.N_plmn_ids; i++) {
nas->plmn_found(serving_cell->sib1.plmn_id[i].id, serving_cell->sib1.tracking_area_code);
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
@ -1379,7 +1413,7 @@ void rrc::handle_sib2()
{
rrc_log->info("SIB2 received\n");
apply_sib2_configs(&serving_cell->sib2);
apply_sib2_configs(serving_cell->sib2ptr());
}
@ -1387,7 +1421,7 @@ void rrc::handle_sib3()
{
rrc_log->info("SIB3 received\n");
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &serving_cell->sib3;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = serving_cell->sib3ptr();
// cellReselectionInfoCommon
cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst];
@ -1507,10 +1541,13 @@ byte_buffer_t* rrc::byte_align_and_pack(byte_buffer_t *pdu)
pdcp_buf = pool_allocate;
}
if (pdcp_buf != NULL) {
srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits);
pdcp_buf->N_bytes = bit_buf.N_bits / 8;
pdcp_buf->set_timestamp();
} else {
rrc_log->error("Fatal Error: Couldn't allocate PDU in byte_align_and_pack().\n");
}
return pdcp_buf;
}
@ -1518,7 +1555,7 @@ void rrc::send_ul_ccch_msg(byte_buffer_t *pdu)
{
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
pdu = byte_align_and_pack(pdu);
if (pdu) {
// Set UE contention resolution ID in MAC
uint64_t uecri = 0;
uint8_t *ue_cri_ptr = (uint8_t *) &uecri;
@ -1532,6 +1569,7 @@ void rrc::send_ul_ccch_msg(byte_buffer_t *pdu)
rrc_log->info("Sending %s\n", liblte_rrc_ul_ccch_msg_type_text[ul_ccch_msg.msg_type]);
pdcp->write_sdu(RB_ID_SRB0, pdu);
}
}
void rrc::send_ul_dcch_msg(byte_buffer_t *pdu)
@ -1539,9 +1577,10 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
pdu = byte_align_and_pack(pdu);
if (pdu) {
rrc_log->info("Sending %s\n", liblte_rrc_ul_dcch_msg_type_text[ul_dcch_msg.msg_type]);
pdcp->write_sdu(RB_ID_SRB1, pdu);
}
}
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
@ -1699,7 +1738,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
*
*******************************************************************************/
void rrc::enable_capabilities() {
bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam;
bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2ptr()->rr_config_common_sib.pusch_cnfg.enable_64_qam;
rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling");
phy->set_config_64qam_en(enable_ul_64);
}
@ -2373,15 +2412,18 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
L3_filter(&pcell_measurement, values);
// Update serving cell measurement
parent->serving_cell->rsrp = rsrp;
parent->serving_cell->set_rsrp(rsrp);
} else {
// Add to list of neighbour cells
parent->add_neighbour_cell(earfcn, pci, rsrp);
bool added = parent->add_neighbour_cell(earfcn, pci, rsrp);
log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti);
log_h->info("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
if (added) {
// Save PHY measurement for all active measurements whose earfcn/pci matches
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t *m = &iter->second;
@ -2398,6 +2440,20 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
}
}
}
}
}
// Remove all stored measurements for a given cell
void rrc::rrc_meas::delete_report(uint32_t earfcn, uint32_t pci) {
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t *m = &iter->second;
if (objects[m->object_id].earfcn == earfcn) {
if (m->cell_values.count(pci)) {
m->cell_values.erase(pci);
log_h->info("Deleting report PCI=%d from cell_values\n", pci);
}
}
}
}
void rrc::rrc_meas::run_tti(uint32_t tti) {

@ -118,6 +118,7 @@ enable = false
# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0
# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but
# can cause UHD instability for long-duration testing. Default true.
# rx_gain_offset: RX Gain offset to add to rx_gain to calibrate RSRP readings
# prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,
# Default is to use tx_gain in [rf] section.
# cqi_max: Upper bound on the maximum CQI to be reported. Default 15.
@ -176,6 +177,7 @@ enable = false
[expert]
#ip_netmask = 255.255.255.0
#rssi_sensor_enabled = false
#rx_gain_offset = 72
#prach_gain = 30
#cqi_max = 15
#cqi_fixed = 10

Loading…
Cancel
Save