From bf4c84ef7b75f8779db6ae391d64b76bbf7611ee Mon Sep 17 00:00:00 2001 From: David Rupprecht <18260006+davidrupprecht@users.noreply.github.com> Date: Wed, 25 Jul 2018 09:54:22 +0200 Subject: [PATCH 01/12] Fixed clear function in blocked queue (#199) --- lib/include/srslte/common/block_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srslte/common/block_queue.h b/lib/include/srslte/common/block_queue.h index 63b0e4177..2e476dd65 100644 --- a/lib/include/srslte/common/block_queue.h +++ b/lib/include/srslte/common/block_queue.h @@ -122,7 +122,7 @@ public: } void clear() { // remove all items - myobj item; + myobj *item = NULL; while (try_pop(item)); } From deab23c9ec526fc0dabddf0ea015c9f2f7ba3b5b Mon Sep 17 00:00:00 2001 From: Merlin Chlosta Date: Wed, 25 Jul 2018 16:40:23 +0200 Subject: [PATCH 02/12] Fix non-blocking rf_uhd_recv_with_time_multi (#195) Return the number of actually received samples, not the requested samples. --- lib/src/phy/rf/rf_uhd_imp.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 7fe291497..c1a4032bf 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -782,17 +782,17 @@ int rf_uhd_recv_with_time_multi(void *h, rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; uhd_rx_metadata_handle *md = &handler->rx_md_first; size_t rxd_samples = 0; + size_t rxd_samples_total = 0; int trials = 0; if (blocking) { - int n = 0; - while (n < nsamples && trials < 100) { + while (rxd_samples_total < nsamples && trials < 100) { void *buffs_ptr[4]; for (int i=0;inof_rx_channels;i++) { cf_t *data_c = (cf_t*) data[i]; - buffs_ptr[i] = &data_c[n]; + buffs_ptr[i] = &data_c[rxd_samples_total]; } - size_t num_samps_left = nsamples - n; + size_t num_samps_left = nsamples - rxd_samples_total; size_t num_rx_samples = (num_samps_left > handler->rx_nof_samples) ? handler->rx_nof_samples : num_samps_left; rxd_samples = 0; @@ -808,7 +808,7 @@ int rf_uhd_recv_with_time_multi(void *h, uhd_rx_metadata_error_code(*md, &error_code); md = &handler->rx_md; - n += rxd_samples; + rxd_samples_total += rxd_samples; trials++; if (error_code == UHD_RX_METADATA_ERROR_CODE_OVERFLOW) { @@ -824,6 +824,7 @@ int rf_uhd_recv_with_time_multi(void *h, } } else { uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, nsamples, md, 0.0, false, &rxd_samples); + rxd_samples_total = rxd_samples; if (error) { fprintf(stderr, "Error receiving from UHD: %d\n", error); log_rx_error(handler); @@ -833,7 +834,7 @@ int rf_uhd_recv_with_time_multi(void *h, if (secs && frac_secs) { uhd_rx_metadata_time_spec(handler->rx_md_first, secs, frac_secs); } - return nsamples; + return rxd_samples_total; } int rf_uhd_send_timed(void *h, From dfce3ea155955ae1ebd080edfabf0a2ef0a0fe8e Mon Sep 17 00:00:00 2001 From: wangqiang1588 Date: Wed, 25 Jul 2018 22:41:06 +0800 Subject: [PATCH 03/12] Fix crash if args is NULL ,enable multi rx channels setting (#198) --- lib/src/phy/rf/rf_soapy_imp.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index a0dcc6542..96f44ad80 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -228,7 +228,7 @@ int rf_soapy_start_rx_stream(void *h, bool now) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; if(handler->rx_stream_active == false){ - if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, 0, 0, 0) != 0) + if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST, 0, 0) != 0) return SRSLTE_ERROR; handler->rx_stream_active = true; } @@ -339,9 +339,19 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) rf_soapy_set_rx_srate(handler, 1.92e6); rf_soapy_set_tx_srate(handler, 1.92e6); - if(SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_RX) > 0){ + size_t channels = SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_RX); + + if((channels > 0) && (nof_rx_antennas > 0)){ printf("Setting up RX stream\n"); - if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { + size_t numChannels = channels; + if (channels > nof_rx_antennas) { + numChannels = nof_rx_antennas; + } + size_t rx_channels[numChannels]; + for(int i = 0 ; i < numChannels ; i++) { + rx_channels[i] = i; + } + if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, rx_channels, numChannels, NULL) != 0) { printf("Rx setupStream fail: %s\n", SoapySDRDevice_lastError()); return SRSLTE_ERROR; } @@ -439,9 +449,11 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) #if HAVE_ASYNC_THREAD bool start_async_thread = true; - if (strstr(args, "silent")) { - REMOVE_SUBSTRING_WITHCOMAS(args, "silent"); - start_async_thread = false; + if (args) { + if (strstr(args, "silent")) { + REMOVE_SUBSTRING_WITHCOMAS(args, "silent"); + start_async_thread = false; + } } #endif From 470953bf9c5875646e4d5049c8f213d202fa84fd Mon Sep 17 00:00:00 2001 From: Eric Schreiber Date: Thu, 26 Jul 2018 07:16:34 -0400 Subject: [PATCH 04/12] Change the calculation of UE group A random access preamble selection to choose a random number from [0 nof_groupA_preambles) rather than incrementing on the preambleTransmissionCounter. (#200) --- srsue/src/mac/proc_ra.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 5b5b56ee7..11e53195c 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -237,7 +237,8 @@ void ra_proc::step_resource_selection() { } if (sel_group == RA_GROUP_A) { if (nof_groupA_preambles) { - sel_preamble = preambleTransmissionCounter%nof_groupA_preambles; + // randomly choose preamble from [0 nof_groupA_preambles) + sel_preamble = rand() % nof_groupA_preambles; } else { rError("Selected group preamble A but nof_groupA_preambles=0\n"); state = RA_PROBLEM; @@ -245,7 +246,8 @@ void ra_proc::step_resource_selection() { } } else { if (nof_groupB_preambles) { - sel_preamble = nof_groupA_preambles + rand()%nof_groupB_preambles; + // randomly choose preamble from [nof_groupA_preambles nof_groupB_preambles) + sel_preamble = nof_groupA_preambles + rand() % nof_groupB_preambles; } else { rError("Selected group preamble B but nof_groupA_preambles=0\n"); state = RA_PROBLEM; @@ -254,7 +256,7 @@ void ra_proc::step_resource_selection() { } sel_maskIndex = 0; } - + rDebug("Selected preambleIndex=%d maskIndex=%d GroupA=%d, GroupB=%d\n", sel_preamble, sel_maskIndex,nof_groupA_preambles, nof_groupB_preambles); state = PREAMBLE_TRANSMISSION; From 8d48613c3882f10423c8332cecb3ebec6fce9aee Mon Sep 17 00:00:00 2001 From: Igor Kim Date: Mon, 17 Sep 2018 09:43:14 +0200 Subject: [PATCH 05/12] fix typo in metrics rssi CMA calculation (#230) --- srsenb/src/phy/phch_worker.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 36a260b6c..cf06babe3 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -1069,7 +1069,7 @@ void phch_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t { metrics.ul.mcs = SRSLTE_VEC_CMA((float) mcs, metrics.ul.mcs, metrics.ul.n_samples); metrics.ul.sinr = SRSLTE_VEC_CMA((float) sinr, metrics.ul.sinr, metrics.ul.n_samples); - metrics.ul.rssi = SRSLTE_VEC_CMA((float) sinr, metrics.ul.rssi, metrics.ul.n_samples); + metrics.ul.rssi = SRSLTE_VEC_CMA((float) rssi, metrics.ul.rssi, metrics.ul.n_samples); metrics.ul.turbo_iters = SRSLTE_VEC_CMA((float) turbo_iters, metrics.ul.turbo_iters, metrics.ul.n_samples); metrics.ul.n_samples++; } From 67c8bf13681c408e8545477c787ea9b182aff862 Mon Sep 17 00:00:00 2001 From: IgnasJ Date: Wed, 19 Sep 2018 18:34:59 +0300 Subject: [PATCH 06/12] Fixes for srsLTE on ARM (#229) * Fix ARM NEON code compilation Fix LV_HAVE_NEON defintion incorrecly used instead of HAVE_NEON in some places Replace vqabsq_s32 with vabsq_f32 as vqabsq_s32 requires int type (fails to compile) Fix missing NEON code path in mat.h in srslte_mat_2x2_mmse_csi_simd() * Fix timestamp overflow issue on 32-bit systems with Soapy driver 'time_t secs' can be 32-bit on some systems. This causes calculation: 'secs * 1000000000;' to overflow. --- lib/include/srslte/phy/utils/mat.h | 5 +++++ lib/include/srslte/phy/utils/simd.h | 28 ++++++++++++++-------------- lib/src/phy/rf/rf_soapy_imp.c | 2 +- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/include/srslte/phy/utils/mat.h b/lib/include/srslte/phy/utils/mat.h index 8db0205f9..c8465b34e 100644 --- a/lib/include/srslte/phy/utils/mat.h +++ b/lib/include/srslte/phy/utils/mat.h @@ -166,8 +166,13 @@ static inline void srslte_mat_2x2_mmse_csi_simd(simd_cf_t y0, simd_cf_t _noise_estimate; simd_f_t _norm = srslte_simd_f_set1(norm); +#if HAVE_NEON + _noise_estimate.val[0] = srslte_simd_f_set1(noise_estimate); + _noise_estimate.val[1] = srslte_simd_f_zero(); +#else /* HAVE_NEON */ _noise_estimate.re = srslte_simd_f_set1(noise_estimate); _noise_estimate.im = srslte_simd_f_zero(); +#endif /* HAVE_NEON */ /* 1. A = H' x H + No*/ simd_cf_t a00 = diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 2a7566e18..3f19b5e88 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -136,7 +136,7 @@ #define SRSLTE_SIMD_S_SIZE 8 #define SRSLTE_SIMD_C16_SIZE 8 -#else /* LV_HAVE_NEON */ +#else /* HAVE_NEON */ #define SRSLTE_SIMD_F_SIZE 0 #define SRSLTE_SIMD_CF_SIZE 0 @@ -511,7 +511,7 @@ static inline simd_f_t srslte_simd_f_abs(simd_f_t a) { return _mm_andnot_ps(_mm_set1_ps(-0.0f), a); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vqabsq_s32(a); + return vabsq_f32(a); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -987,13 +987,13 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { static inline simd_cf_t srslte_simd_cf_neg (simd_cf_t a) { simd_cf_t ret; -#if LV_HAVE_NEON +#if 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 */ +#else /* HAVE_NEON */ ret.re = srslte_simd_f_neg(a.re); ret.im = srslte_simd_f_neg(a.im); -#endif /* LV_HAVE_NEON */ +#endif /* HAVE_NEON */ return ret; } @@ -1004,37 +1004,37 @@ static inline simd_cf_t srslte_simd_cf_neg_mask (simd_cf_t a, simd_f_t mask) { 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 +#if 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 */ +#else /* 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 */ +#endif /* 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 +#if HAVE_NEON ret.val[0] = a.val[0]; ret.val[1] = srslte_simd_f_neg(a.val[1]); -#else /* LV_HAVE_NEON */ +#else /* HAVE_NEON */ ret.re = a.re; ret.im = srslte_simd_f_neg(a.im); -#endif /* LV_HAVE_NEON */ +#endif /* 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 +#if HAVE_NEON ret.val[0] = srslte_simd_f_neg(a.val[1]); ret.val[1] = a.val[0]; -#else /* LV_HAVE_NEON */ +#else /* HAVE_NEON */ ret.re = srslte_simd_f_neg(a.im); ret.im = a.re; -#endif /* LV_HAVE_NEON */ +#endif /* HAVE_NEON */ return ret; } diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 96f44ad80..26ad5bac0 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -851,7 +851,7 @@ int rf_soapy_send_timed_multi(void *h, // Convert initial tx time if (has_time_spec) { - timeNs = secs * 1000000000; + timeNs = (long long)secs * 1000000000; timeNs = timeNs + (frac_secs * 1000000000); } From 3433b0ffdea6456b23e9181f19b6368ff53a1053 Mon Sep 17 00:00:00 2001 From: Zhe Huang <13131185+ecefelix@users.noreply.github.com> Date: Wed, 19 Sep 2018 11:43:18 -0400 Subject: [PATCH 07/12] assign correct values from BladeRf manual calibration to correction * Assign correct values from BladeRf manual calibration to correction The rf_calibration function for blade RF was assgiing dc_gain to BLADERF_CORR_FPGA_PHASE and dc_phase to BLADERF_CORR_FPGA_GAIN. This hot fix corrects the value assignments in both rf_blade_set_tx_cal and rf_blade_set_rx_cal functions. --- lib/src/phy/rf/rf_blade_imp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/phy/rf/rf_blade_imp.c b/lib/src/phy/rf/rf_blade_imp.c index 4f624f8ce..031a1004a 100644 --- a/lib/src/phy/rf/rf_blade_imp.c +++ b/lib/src/phy/rf/rf_blade_imp.c @@ -393,16 +393,16 @@ double rf_blade_set_tx_freq(void *h, double freq) void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_PHASE, cal->dc_gain); - bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_GAIN, cal->dc_phase); + bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_PHASE, cal->dc_phase); + bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_GAIN, cal->dc_gain); bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i); bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q); } void rf_blade_set_rx_cal(void *h, srslte_rf_cal_t *cal) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_PHASE, cal->dc_gain); - bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_GAIN, cal->dc_phase); + bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_PHASE, cal->dc_phase); + bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_GAIN, cal->dc_gain); bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i); bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q); } From 2dddfa2aac0947591ad198b7593aa1b2a5bb0e57 Mon Sep 17 00:00:00 2001 From: Joseph Giovatto Date: Thu, 20 Sep 2018 05:22:22 -0400 Subject: [PATCH 08/12] added ability to track tput per bearer (#233) added mac_metrics for ul/dl harq retex counts --- lib/include/srslte/upper/rlc_metrics.h | 6 ++++-- lib/src/upper/rlc.cc | 8 +++----- srsue/hdr/mac/mac_metrics.h | 2 ++ srsue/src/mac/mac.cc | 2 ++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/include/srslte/upper/rlc_metrics.h b/lib/include/srslte/upper/rlc_metrics.h index ab6e83c02..153fba57b 100644 --- a/lib/include/srslte/upper/rlc_metrics.h +++ b/lib/include/srslte/upper/rlc_metrics.h @@ -27,13 +27,15 @@ #ifndef SRSLTE_RLC_METRICS_H #define SRSLTE_RLC_METRICS_H +#include "srslte/common/common.h" namespace srslte { struct rlc_metrics_t { - float dl_tput_mbps; - float ul_tput_mbps; + float dl_tput_mbps[SRSLTE_N_RADIO_BEARERS]; + float ul_tput_mbps[SRSLTE_N_RADIO_BEARERS]; + float dl_tput_mrb_mbps[SRSLTE_N_MCH_LCIDS]; }; } // namespace srslte diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index c24f0076b..fdc1d4a99 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -90,11 +90,9 @@ void rlc::get_metrics(rlc_metrics_t &m) get_time_interval(metrics_time); double secs = (double)metrics_time[0].tv_sec + metrics_time[0].tv_usec*1e-6; - m.dl_tput_mbps = 0; - m.ul_tput_mbps = 0; for (int i=0;iinfo("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n", i, @@ -105,7 +103,7 @@ void rlc::get_metrics(rlc_metrics_t &m) // Add multicast metrics for (int i=0;iinfo("MCH_LCID=%d, RX throughput: %4.6f Mbps.\n", i, diff --git a/srsue/hdr/mac/mac_metrics.h b/srsue/hdr/mac/mac_metrics.h index a201d2a7f..56d20dcdc 100644 --- a/srsue/hdr/mac/mac_metrics.h +++ b/srsue/hdr/mac/mac_metrics.h @@ -39,6 +39,8 @@ struct mac_metrics_t int rx_errors; int rx_brate; int ul_buffer; + float dl_retx_avg; + float ul_retx_avg; }; } // namespace srsue diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index ffa0ca1a3..8eb15e339 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -476,6 +476,8 @@ void mac::get_metrics(mac_metrics_t &m) ul_harq.get_average_retx()); metrics.ul_buffer = (int) bsr_procedure.get_buffer_state(); + metrics.dl_retx_avg = dl_harq.get_average_retx(); + metrics.ul_retx_avg = ul_harq.get_average_retx(); m = metrics; bzero(&metrics, sizeof(mac_metrics_t)); } From cd1fb0d81efca73676b09aa0f7f1d2b344317e90 Mon Sep 17 00:00:00 2001 From: Zhe Huang <13131185+ecefelix@users.noreply.github.com> Date: Thu, 20 Sep 2018 06:57:47 -0400 Subject: [PATCH 09/12] Set AMF to all zeros during resync (#213) During the resync procedure, the security_milenage_f1_star generates a MAC_S value that does not match the MAC_S value reported in AUTS. This posts a security risk. According to 3GPP TS 33.102 version 11.5.1 section 6.3.3, the AMF used to calculate MAC-S assumes a dummy value of all zeros so that it does not need to be transmitted in the clear in the re-synch message. This patch corrects this problem. MAC_S reported by AUTS matches the MAC_S calculated using f1_star function after the fix. --- srsepc/src/hss/hss.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 6bbf86097..d2bcfabab 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -594,6 +594,10 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) uint8_t mac_s_tmp[8]; + for(int i=0; i<2; i++){ + amf[i] = 0; + } + security_milenage_f1_star(k, opc, last_rand, sqn_ms, amf, mac_s_tmp); m_hss_log->debug_hex(mac_s_tmp, 8, "MAC calc : "); From 4b0171cceafec62ae4f1dfda4cc12c37f7c803ad Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 18 Sep 2018 17:31:12 +0200 Subject: [PATCH 10/12] fix MAC timer handling in rlc_stress_test --- lib/test/upper/rlc_stress_test.cc | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 9da13c12c..9bd181ee8 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -102,12 +102,20 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) { } } +// Interface for MAC reader to step timer +class mac_reader_interface { +public: + // MAC reader calls step_timers after each RLC transmission + virtual void step_timer() = 0; +}; + class mac_reader :public thread { public: - mac_reader(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, uint32_t pdu_tx_delay_usec_, rlc_pcap *pcap_, uint32_t lcid_, bool is_dl_ = true) + mac_reader(mac_reader_interface *mac_, rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, uint32_t pdu_tx_delay_usec_, rlc_pcap *pcap_, uint32_t lcid_, bool is_dl_ = true) { + mac = mac_; rlc1 = rlc1_; rlc2 = rlc2_; fail_rate = fail_rate_; @@ -152,10 +160,13 @@ private: } } } + // step timer + mac->step_timer(); } byte_buffer_pool::get_instance()->deallocate(pdu); } + mac_reader_interface *mac; rlc_interface_mac *rlc1; rlc_interface_mac *rlc2; float fail_rate; @@ -169,11 +180,13 @@ private: class mac_dummy :public srslte::mac_interface_timers + ,public mac_reader_interface { public: mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, int32_t pdu_tx_delay, uint32_t lcid, rlc_pcap* pcap = NULL) - :r1(rlc1_, rlc2_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, true) - ,r2(rlc2_, rlc1_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, false) + :r1(this, rlc1_, rlc2_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, true) + ,r2(this, rlc2_, rlc1_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, false) + ,timers(8) { } @@ -191,13 +204,20 @@ public: srslte::timers::timer* timer_get(uint32_t timer_id) { - return &t; + return timers.get(timer_id); + } + uint32_t timer_get_unique_id() { + return timers.get_unique_id(); + } + void timer_release_id(uint32_t timer_id) { + timers.release_id(timer_id); + } + void step_timer() { + timers.step_all(); } - uint32_t timer_get_unique_id(){return 0;} - void timer_release_id(uint32_t id){} private: - srslte::timers::timer t; + srslte::timers timers; mac_reader r1; mac_reader r2; From 9a4ce125fbabc0391b2636f17cdb8ec430ba295b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 20 Sep 2018 21:28:40 +0200 Subject: [PATCH 11/12] fix RLC stress test with respect to timer handling --- lib/test/upper/rlc_stress_test.cc | 181 ++++++++++++++---------------- 1 file changed, 83 insertions(+), 98 deletions(-) diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 9bd181ee8..b1bacd324 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -37,7 +37,8 @@ #include #include -#define SDU_SIZE 1500 +#define SDU_SIZE (1500) +#define LOG_HEX_LIMIT (-1) using namespace std; using namespace srsue; @@ -55,6 +56,7 @@ typedef struct { bool single_tx; bool write_pcap; float opp_sdu_ratio; + bool zero_seed; } stress_test_args_t; void parse_args(stress_test_args_t *args, int argc, char *argv[]) { @@ -78,7 +80,8 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) { ("reestablish", bpo::value(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution") ("loglevel", bpo::value(&args->log_level)->default_value(srslte::LOG_LEVEL_DEBUG), "Log level (1=Error,2=Warning,3=Info,4=Debug)") ("singletx", bpo::value(&args->single_tx)->default_value(false), "If set to true, only one node is generating data") - ("pcap", bpo::value(&args->write_pcap)->default_value(false), "Whether to write all RLC PDU to PCAP file"); + ("pcap", bpo::value(&args->write_pcap)->default_value(false), "Whether to write all RLC PDU to PCAP file") + ("zeroseed", bpo::value(&args->zero_seed)->default_value(false), "Whether to initialize random seed to zero"); // these options are allowed on the command line bpo::options_description cmdline_options; @@ -102,29 +105,25 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) { } } -// Interface for MAC reader to step timer -class mac_reader_interface { -public: - // MAC reader calls step_timers after each RLC transmission - virtual void step_timer() = 0; -}; - -class mac_reader - :public thread +class mac_dummy + :public srslte::mac_interface_timers + ,public thread { public: - mac_reader(mac_reader_interface *mac_, rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, uint32_t pdu_tx_delay_usec_, rlc_pcap *pcap_, uint32_t lcid_, bool is_dl_ = true) + mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, int32_t pdu_tx_delay_usec_, uint32_t lcid_, rlc_pcap* pcap_ = NULL) + :timers(8) + ,run_enable(true) + ,rlc1(rlc1_) + ,rlc2(rlc2_) + ,fail_rate(fail_rate_) + ,opp_sdu_ratio(opp_sdu_ratio_) + ,pdu_tx_delay_usec(pdu_tx_delay_usec_) + ,pcap(pcap_) + ,lcid(lcid_) + ,log("MAC ") { - mac = mac_; - rlc1 = rlc1_; - rlc2 = rlc2_; - fail_rate = fail_rate_; - opp_sdu_ratio = opp_sdu_ratio_; - run_enable = true; - pdu_tx_delay_usec = pdu_tx_delay_usec_; - pcap = pcap_; - is_dl = is_dl_; - lcid = lcid_; + log.set_level(srslte::LOG_LEVEL_ERROR); + log.set_hex_limit(LOG_HEX_LIMIT); } void stop() @@ -133,98 +132,77 @@ public: wait_thread_finish(); } + srslte::timers::timer* timer_get(uint32_t timer_id) + { + return timers.get(timer_id); + } + uint32_t timer_get_unique_id() { + return timers.get_unique_id(); + } + void timer_release_id(uint32_t timer_id) { + timers.release_id(timer_id); + } + void step_timer() { + timers.step_all(); + } + private: - void run_thread() + void run_tti(rlc_interface_mac *tx_rlc, rlc_interface_mac *rx_rlc, bool is_dl) { - byte_buffer_t *pdu = byte_buffer_pool::get_instance()->allocate("mac_reader::run_thread"); + byte_buffer_t *pdu = byte_buffer_pool::get_instance()->allocate(__PRETTY_FUNCTION__); if (!pdu) { printf("Fatal Error: Could not allocate PDU in mac_reader::run_thread\n"); exit(-1); } - while(run_enable) { - // generate MAC opportunities of random size or with fixed ratio - float r = opp_sdu_ratio ? opp_sdu_ratio : (float)rand()/RAND_MAX; - int opp_size = r*SDU_SIZE; - uint32_t buf_state = rlc1->get_buffer_state(lcid); - if (buf_state) { - int read = rlc1->read_pdu(lcid, pdu->msg, opp_size); - if (pdu_tx_delay_usec) usleep(pdu_tx_delay_usec); - if(((float)rand()/RAND_MAX > fail_rate) && read>0) { - pdu->N_bytes = read; - rlc2->write_pdu(lcid, pdu->msg, pdu->N_bytes); - if (is_dl) { - pcap->write_dl_am_ccch(pdu->msg, pdu->N_bytes); - } else { - pcap->write_ul_am_ccch(pdu->msg, pdu->N_bytes); - } + float r = opp_sdu_ratio ? opp_sdu_ratio : (float)rand()/RAND_MAX; + int opp_size = r*SDU_SIZE; + uint32_t buf_state = tx_rlc->get_buffer_state(lcid); + if (buf_state) { + int read = tx_rlc->read_pdu(lcid, pdu->msg, opp_size); + pdu->N_bytes = read; + if (pdu_tx_delay_usec) usleep(pdu_tx_delay_usec); + if(((float)rand()/RAND_MAX > fail_rate) && read>0) { + rx_rlc->write_pdu(lcid, pdu->msg, pdu->N_bytes); + if (is_dl) { + pcap->write_dl_am_ccch(pdu->msg, pdu->N_bytes); + } else { + pcap->write_ul_am_ccch(pdu->msg, pdu->N_bytes); } + } else { + log.info_hex(pdu->msg, pdu->N_bytes, "Dropping RLC PDU (%d B)\n", pdu->N_bytes); } - // step timer - mac->step_timer(); } byte_buffer_pool::get_instance()->deallocate(pdu); } - mac_reader_interface *mac; + void run_thread() + { + while (run_enable) { + // Downlink direction first (RLC1->RLC2) + run_tti(rlc1, rlc2, true); + + // UL direction (RLC2->RLC1) + run_tti(rlc2, rlc1, false); + + // step timer + step_timer(); + } + } + rlc_interface_mac *rlc1; rlc_interface_mac *rlc2; + srslte::timers timers; + bool run_enable; float fail_rate; float opp_sdu_ratio; uint32_t pdu_tx_delay_usec; rlc_pcap *pcap; uint32_t lcid; - bool is_dl; - bool run_enable; -}; - -class mac_dummy - :public srslte::mac_interface_timers - ,public mac_reader_interface -{ -public: - mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, int32_t pdu_tx_delay, uint32_t lcid, rlc_pcap* pcap = NULL) - :r1(this, rlc1_, rlc2_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, true) - ,r2(this, rlc2_, rlc1_, fail_rate_, opp_sdu_ratio_, pdu_tx_delay, pcap, lcid, false) - ,timers(8) - { - } - - void start() - { - r1.start(7); - r2.start(7); - } - - void stop() - { - r1.stop(); - r2.stop(); - } - - srslte::timers::timer* timer_get(uint32_t timer_id) - { - return timers.get(timer_id); - } - uint32_t timer_get_unique_id() { - return timers.get_unique_id(); - } - void timer_release_id(uint32_t timer_id) { - timers.release_id(timer_id); - } - void step_timer() { - timers.step_all(); - } - -private: - srslte::timers timers; - - mac_reader r1; - mac_reader r2; + srslte::log_filter log; }; - class rlc_tester :public pdcp_interface_rlc ,public rrc_interface_rlc @@ -251,10 +229,12 @@ public: { assert(rx_lcid == lcid); if (sdu->N_bytes != SDU_SIZE) { - printf("Received PDU with size %d, expected %d. Exiting.\n", sdu->N_bytes, SDU_SIZE); + srslte::log_filter log1("Testr");; + log1.set_level(srslte::LOG_LEVEL_ERROR); + log1.set_hex_limit(sdu->N_bytes); + log1.error_hex(sdu->msg, sdu->N_bytes, "Received PDU with size %d, expected %d. Exiting.\n", sdu->N_bytes, SDU_SIZE); exit(-1); } - byte_buffer_pool::get_instance()->deallocate(sdu); rx_pdus++; } @@ -265,13 +245,12 @@ public: // RRC interface void max_retx_attempted(){} - std::string get_rb_name(uint32_t rx_lcid) { return std::string(""); } + std::string get_rb_name(uint32_t rx_lcid) { return std::string("DRB1"); } int get_nof_rx_pdus() { return rx_pdus; } private: - void run_thread() - { + void run_thread() { uint8_t sn = 0; while(run_enable) { byte_buffer_t *pdu = byte_buffer_pool::get_instance()->allocate("rlc_tester::run_thread"); @@ -308,8 +287,8 @@ void stress_test(stress_test_args_t args) srslte::log_filter log2("RLC_2"); log1.set_level((LOG_LEVEL_ENUM)args.log_level); log2.set_level((LOG_LEVEL_ENUM)args.log_level); - log1.set_hex_limit(-1); - log2.set_hex_limit(-1); + log1.set_hex_limit(LOG_HEX_LIMIT); + log2.set_hex_limit(LOG_HEX_LIMIT); rlc_pcap pcap; uint32_t lcid = 1; @@ -411,6 +390,12 @@ int main(int argc, char **argv) { stress_test_args_t args; parse_args(&args, argc, argv); + if (args.zero_seed) { + srand(0); + } else { + srand(time(NULL)); + } + stress_test(args); byte_buffer_pool::get_instance()->cleanup(); From 3d4e90029c87046cf9c53f8727934c26e6028a20 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 20 Sep 2018 21:30:57 +0200 Subject: [PATCH 12/12] fix RLC UM issue when dropping PDU that is neither start nor end aligned --- lib/src/upper/rlc_um.cc | 78 +++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index c4fa72d2a..5a13b55f6 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -28,8 +28,9 @@ #include "srslte/upper/rlc_um.h" #include #include +#include -#define RX_MOD_BASE(x) (x-vr_uh-cfg.rx_window_size)%cfg.rx_mod +#define RX_MOD_BASE(x) (((x)-vr_uh-cfg.rx_window_size)%cfg.rx_mod) namespace srslte { @@ -95,6 +96,11 @@ bool rlc_um::rlc_um_rx::configure(srslte_rlc_config_t cnfg_, std::string rb_name return false; } + // set reordering timer + if (reordering_timer != NULL) { + reordering_timer->set(this, cfg.t_reordering); + } + rb_name = rb_name_; rx_enabled = true; @@ -464,12 +470,11 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) vt_us = (vt_us + 1)%cfg.tx_mod; // Add header and TX - log->debug("%s packing PDU with length %d\n", get_rb_name(), pdu->N_bytes); rlc_um_write_data_pdu_header(&header, pdu); memcpy(payload, pdu->msg, pdu->N_bytes); uint32_t ret = pdu->N_bytes; - log->debug("%s returning length %d\n", get_rb_name(), pdu->N_bytes); + log->info("%s Transmitting PDU SN=%d (%d B)\n", get_rb_name(), header.sn, pdu->N_bytes); pool->deallocate(pdu); debug_state(); @@ -545,9 +550,7 @@ void rlc_um::rlc_um_rx::reestablish() void rlc_um::rlc_um_rx::stop() { pthread_mutex_lock(&mutex); - if(reordering_timer) { - reordering_timer->stop(); - } + vr_ur = 0; vr_ux = 0; vr_uh = 0; @@ -559,7 +562,8 @@ void rlc_um::rlc_um_rx::stop() rx_sdu = NULL; } - if (mac_timers && reordering_timer) { + if (mac_timers != NULL && reordering_timer != NULL) { + reordering_timer->stop(); mac_timers->timer_release_id(reordering_timer_id); reordering_timer = NULL; } @@ -642,7 +646,7 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) } if(!reordering_timer->is_running()) { if(RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { - reordering_timer->set(this, cfg.t_reordering); + reordering_timer->reset(); reordering_timer->run(); vr_ux = vr_uh; } @@ -714,7 +718,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() // Handle last segment if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { - log->debug("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n", + log->info("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n", vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes); @@ -753,18 +757,36 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() // Now update vr_ur until we reach an SN we haven't yet received while(rx_window.end() != rx_window.find(vr_ur)) { + log->debug("Reassemble loop for vr_ur=%d\n", vr_ur); + if ((vr_ur_in_rx_sdu+1)%cfg.rx_mod != vr_ur) { + log->warning("PDU SN=%d lost, dropping remainder of %d\n", vr_ur_in_rx_sdu+1, vr_ur); + rx_sdu->reset(); + } + // Handle any SDU segments for(uint32_t i=0; iN_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { - log->warning("Dropping PDU %d due to lost start segment\n", vr_ur); + log->warning_hex(rx_window[vr_ur].buf->msg, len, "Dropping first part of SN %d due to lost start segment\n", vr_ur); + // Advance data pointers and continue with next segment rx_window[vr_ur].buf->msg += len; rx_window[vr_ur].buf->N_bytes -= len; rx_sdu->reset(); - break; + + // beginning of next SDU? + if (rx_window[vr_ur].header.fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED) { + len = rx_window[vr_ur].buf->N_bytes; + log->info_hex(rx_window[vr_ur].buf->msg, len, "Copying first %d bytes of new SDU\n", len); + memcpy(rx_sdu->msg, rx_window[vr_ur].buf->msg, len); + rx_sdu->N_bytes = len; + rx_window[vr_ur].buf->msg += len; + rx_window[vr_ur].buf->N_bytes -= len; + log->info("Updating vr_ur_in_rx_sdu. old=%d, new=%d\n", vr_ur_in_rx_sdu, vr_ur); + vr_ur_in_rx_sdu = vr_ur; + goto clean_up_rx_window; + } } // Check available space in SDU @@ -774,7 +796,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() goto clean_up_rx_window; } - log->debug("Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", + log->info_hex(rx_window[vr_ur].buf->msg, len, "Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", len, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur_in_rx_sdu, vr_ur, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod); memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); rx_sdu->N_bytes += len; @@ -811,11 +833,10 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES && rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) { - + log->info_hex(rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes, "Writing last segment in SDU buffer. Updating vr_ur=%d, Buffer size=%d, segment size=%d\n", + vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes); rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes; - log->debug("Writing last segment in SDU buffer. Updating vr_ur=%d, Buffer size=%d, segment size=%d\n", - vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); } else { log->error("Out of bounds while reassembling SDU buffer in UM: sdu_len=%d, window_buffer_len=%d, vr_ur=%d\n", rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur); @@ -842,8 +863,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() pdu_lost = false; } - clean_up_rx_window: - +clean_up_rx_window: // Clean up rx_window pool->deallocate(rx_window[vr_ur].buf); rx_window.erase(vr_ur); @@ -853,16 +873,15 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() } // Only called when lock is hold +// 36.322 Section 5.1.2.2.1 bool rlc_um::rlc_um_rx::inside_reordering_window(uint16_t sn) { - if(cfg.rx_window_size == 0) { + if (cfg.rx_window_size == 0 || rx_window.empty()) { return true; } - if(RX_MOD_BASE(sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && - RX_MOD_BASE(sn) < RX_MOD_BASE(vr_uh)) - { + if (RX_MOD_BASE(vr_uh-cfg.rx_window_size) <= RX_MOD_BASE(sn) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_uh)) { return true; - }else{ + } else { return false; } } @@ -888,8 +907,7 @@ void rlc_um::rlc_um_rx::reset_metrics() void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) { - if(reordering_timer_id == timeout_id) - { + if (reordering_timer_id == timeout_id) { pthread_mutex_lock(&mutex); // 36.322 v10 Section 5.1.2.2.4 @@ -897,19 +915,19 @@ void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) get_rb_name()); log->warning("Lost PDU SN: %d\n", vr_ur); + pdu_lost = true; rx_sdu->reset(); - while(RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) - { + + while(RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) { vr_ur = (vr_ur + 1)%cfg.rx_mod; log->debug("Entering Reassemble from timeout id=%d\n", timeout_id); reassemble_rx_sdus(); log->debug("Finished reassemble from timeout id=%d\n", timeout_id); } reordering_timer->stop(); - if(RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) - { - reordering_timer->set(this, cfg.t_reordering); + if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { + reordering_timer->reset(); reordering_timer->run(); vr_ux = vr_uh; }