diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 3fd71422b..41a89fb36 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -96,35 +96,6 @@ static const char error_text[ERROR_N_ITEMS][20] = { "None", "Can't start", "Already started"}; -// Radio bearers -typedef enum{ - RB_ID_SRB0 = 0, - RB_ID_SRB1, - RB_ID_SRB2, - RB_ID_DRB1, - RB_ID_DRB2, - RB_ID_DRB3, - RB_ID_DRB4, - RB_ID_DRB5, - RB_ID_DRB6, - RB_ID_DRB7, - RB_ID_DRB8, - RB_ID_MAX -} rb_id_t; - -static const char rb_id_str[RB_ID_MAX][8] = {"SRB0", "SRB1", "SRB2", - "DRB1", "DRB2", "DRB3", - "DRB4", "DRB5", "DRB6", - "DRB7", "DRB8"}; - -inline const char* get_rb_name(uint32_t lcid) { - if (lcid < RB_ID_MAX) { - return rb_id_str[lcid]; - } else { - return "INVALID_RB"; - } -} - /****************************************************************************** * Byte and Bit buffers * diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 71f47d197..93f7657cb 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -70,6 +70,7 @@ public: level = LOG_LEVEL_NONE; hex_limit = 0; show_layer_en = true; + level_text_short = true; } log(std::string service_name_) { @@ -78,6 +79,7 @@ public: level = LOG_LEVEL_NONE; hex_limit = 0; show_layer_en = true; + level_text_short = true; } // This function shall be called at the start of every tti for printing tti diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index e8a33c207..3e6bfe6f1 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -174,6 +174,7 @@ public: virtual void enable_capabilities() = 0; virtual void plmn_search() = 0; virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for PDCP @@ -184,6 +185,7 @@ public: virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_pcch(srslte::byte_buffer_t *pdu) = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for RLC @@ -191,6 +193,7 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted() = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // PDCP interface for GW diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 0bd6e9afe..c1f5579a1 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -79,6 +79,7 @@ typedef struct { srslte_interp_linsrslte_vec_t srslte_interp_linvec; srslte_interp_lin_t srslte_interp_lin; + srslte_interp_lin_t srslte_interp_lin_3; srslte_interp_lin_t srslte_interp_lin_mbsfn; float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; diff --git a/lib/include/srslte/phy/fec/viterbi.h b/lib/include/srslte/phy/fec/viterbi.h index d69750fb3..689b636e9 100644 --- a/lib/include/srslte/phy/fec/viterbi.h +++ b/lib/include/srslte/phy/fec/viterbi.h @@ -57,10 +57,13 @@ typedef struct SRSLTE_API{ float gain_quant; int16_t gain_quant_s; int (*decode) (void*, uint8_t*, uint8_t*, uint32_t); + int (*decode_s) (void*, uint16_t*, uint8_t*, uint32_t); int (*decode_f) (void*, float*, uint8_t*, uint32_t); void (*free) (void*); uint8_t *tmp; + uint16_t *tmp_s; uint8_t *symbols_uc; + uint16_t *symbols_us; }srslte_viterbi_t; SRSLTE_API int srslte_viterbi_init(srslte_viterbi_t *q, @@ -87,6 +90,8 @@ SRSLTE_API int srslte_viterbi_decode_s(srslte_viterbi_t *q, uint8_t *data, uint32_t frame_length); +SRSLTE_API int srslte_viterbi_decode_us(srslte_viterbi_t *q, uint16_t *symbols, uint8_t *data, uint32_t frame_length); + SRSLTE_API int srslte_viterbi_decode_uc(srslte_viterbi_t *q, uint8_t *symbols, uint8_t *data, diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index a4028e495..4ec95639a 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -141,8 +141,9 @@ SRSLTE_API uint32_t srslte_vec_max_abs_ci(const cf_t *x, const uint32_t len); /* quantify vector of floats or int16 and convert to uint8_t */ SRSLTE_API void srslte_vec_quant_fuc(const float *in, uint8_t *out, const float gain, const float offset, const float clip, const uint32_t len); +SRSLTE_API void srslte_vec_quant_fus(float *in, uint16_t *out, float gain, float offset, float clip, uint32_t len); SRSLTE_API void srslte_vec_quant_suc(const int16_t *in, uint8_t *out, const float gain, const int16_t offset, const int16_t clip, const uint32_t len); - +SRSLTE_API void srslte_vec_quant_sus(const int16_t *in, uint16_t *out, const float gain, const int16_t offset, const uint32_t len); /* magnitude of each vector element */ SRSLTE_API void srslte_vec_abs_cf(const cf_t *x, float *abs, const uint32_t len); SRSLTE_API void srslte_vec_abs_square_cf(const cf_t *x, float *abs_square, const uint32_t len); @@ -150,6 +151,10 @@ SRSLTE_API void srslte_vec_abs_square_cf(const cf_t *x, float *abs_square, const /* Copy 256 bit aligned vector */ SRSLTE_API void srs_vec_cf_cpy(const cf_t *src, cf_t *dst, const int len); +SRSLTE_API void srslte_vec_interleave(const cf_t *x, const cf_t *y, cf_t *z, const int len); + +SRSLTE_API void srslte_vec_interleave_add(const cf_t *x, const cf_t *y, cf_t *z, const int len); + #ifdef __cplusplus } #endif diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 54ac55f98..31725edb3 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -122,6 +122,9 @@ SRSLTE_API void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const flo SRSLTE_API void srslte_vec_cp_simd(const cf_t *src, cf_t *dst, int len); +SRSLTE_API void srslte_vec_interleave_simd(const cf_t *x, const cf_t *y, cf_t *z, const int len); + +SRSLTE_API void srslte_vec_interleave_add_simd(const cf_t *x, const cf_t *y, cf_t *z, const int len); /* SIMD Find Max functions */ SRSLTE_API uint32_t srslte_vec_max_fi_simd(const float *x, const int len); diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index 5879f49a8..6720c21ad 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -44,11 +44,17 @@ log_filter::log_filter() log_filter::log_filter(std::string layer) { + do_tti = false; + time_src = NULL; + time_format = TIME; init(layer, &def_logger_stdout, tti); } log_filter::log_filter(std::string layer, logger *logger_, bool tti) { + do_tti = false; + time_src = NULL; + time_format = TIME; init(layer, logger_, tti); } diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 113870cc9..d63933ced 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -141,6 +141,11 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) goto clean_exit; } + if (srslte_interp_linear_init(&q->srslte_interp_lin_3, 4*max_prb, SRSLTE_NRE/4)) { + fprintf(stderr, "Error initializing interpolator\n"); + goto clean_exit; + } + if (srslte_interp_linear_init(&q->srslte_interp_lin_mbsfn, 6*max_prb, SRSLTE_NRE/6)) { fprintf(stderr, "Error initializing interpolator\n"); goto clean_exit; @@ -185,6 +190,7 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q) } srslte_interp_linear_vector_free(&q->srslte_interp_linvec); srslte_interp_linear_free(&q->srslte_interp_lin); + srslte_interp_linear_free(&q->srslte_interp_lin_3); srslte_interp_linear_free(&q->srslte_interp_lin_mbsfn); if (q->pilot_estimates) { free(q->pilot_estimates); @@ -238,6 +244,11 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) return SRSLTE_ERROR; } + if (srslte_interp_linear_resize(&q->srslte_interp_lin_3, 4 * q->cell.nof_prb, SRSLTE_NRE / 4)) { + fprintf(stderr, "Error initializing interpolator\n"); + return SRSLTE_ERROR; + } + } ret = SRSLTE_SUCCESS; } @@ -245,12 +256,16 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) } /* Uses the difference between the averaged and non-averaged pilot estimates */ -static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id) +static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslte_sf_t ch_mode) { int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); if (q->average_subframe) { - nref /= 4; + if (ch_mode == SRSLTE_SF_MBSFN) { + nref /= 4; + } else { + nref /= 2; + } } /* Substract noisy pilot estimates */ @@ -337,10 +352,18 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t fidx_offset, SRSLTE_NRE/6-fidx_offset); } } else { - fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0); - srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l], - &ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE], - fidx_offset, SRSLTE_NRE/2-fidx_offset); + if (q->average_subframe) { + fidx_offset = SRSLTE_MIN(srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0), + srslte_refsignal_cs_fidx(q->cell, 1, port_id, 0)); + srslte_interp_linear_offset(&q->srslte_interp_lin_3, &pilot_estimates[q->cell.nof_prb * l], + &ce[srslte_refsignal_cs_nsymbol(l, q->cell.cp, port_id) * q->cell.nof_prb + * SRSLTE_NRE], fidx_offset, SRSLTE_NRE / 4 - fidx_offset); + } else { + fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0); + srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2 * q->cell.nof_prb * l], + &ce[srslte_refsignal_cs_nsymbol(l, q->cell.cp, port_id) * q->cell.nof_prb + * SRSLTE_NRE], fidx_offset, SRSLTE_NRE / 2 - fidx_offset); + } } } @@ -417,11 +440,31 @@ static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint // Average in the time domain if enabled if (q->average_subframe) { - for (int l=1;lcell, 0, port_id, 0) < 3) { + srslte_vec_interleave(input, &input[nref], temp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], temp, nref); + } + } else { + srslte_vec_interleave(&input[nref], input, temp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[(l + 1) * nref], &input[l * nref], temp, nref); + } + } + nref *= 2; + srslte_vec_sc_prod_cfc(temp, 2.0f / (float) nsymbols, input, nref); + + nsymbols = 1; } - srslte_vec_sc_prod_cfc(input, 1.0/((float) nsymbols), input, nref); - nsymbols = 1; } // Average in the frequency domain @@ -482,7 +525,7 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui /* Estimate noise power */ if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) { - q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id); + q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); } else if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce); diff --git a/lib/src/phy/fec/test/viterbi_test.c b/lib/src/phy/fec/test/viterbi_test.c index f619b50b9..6ca97a084 100644 --- a/lib/src/phy/fec/test/viterbi_test.c +++ b/lib/src/phy/fec/test/viterbi_test.c @@ -36,8 +36,13 @@ #include "viterbi_test.h" +#define VITERBI_16 -int frame_length = 1000, nof_frames = 128; +#ifndef LV_HAVE_AVX2 +#undef VITERBI_16 +#endif + +int frame_length = 1000, nof_frames = 256; float ebno_db = 100.0; uint32_t seed = 0; bool tail_biting = false; @@ -84,6 +89,7 @@ void parse_args(int argc, char **argv) { int main(int argc, char **argv) { int frame_cnt; float *llr; + uint16_t *llr_s; uint8_t *llr_c; uint8_t *data_tx, *data_rx, *data_rx2, *symbols; int i, j; @@ -154,6 +160,11 @@ int main(int argc, char **argv) { perror("malloc"); exit(-1); } + llr_s = malloc(2 * coded_length * sizeof(uint16_t)); + if (!llr_s) { + perror("malloc"); + exit(-1); + } llr_c = malloc(2 * coded_length * sizeof(uint8_t)); if (!llr_c) { perror("malloc"); @@ -177,7 +188,7 @@ int main(int argc, char **argv) { snr_points = 1; } - float Gain = 32; + float Gain = 2500; for (i = 0; i < snr_points; i++) { frame_cnt = 0; @@ -206,17 +217,22 @@ int main(int argc, char **argv) { } srslte_ch_awgn_f(llr, llr, var[i], coded_length); + //srslte_vec_fprint_f(stdout, llr, 100); + + srslte_vec_quant_fuc(llr, llr_c, 32, 127.5, 255, coded_length); + srslte_vec_quant_fus(llr, llr_s, 8192, 32767.5, 65535, coded_length); - srslte_vec_quant_fuc(llr, llr_c, Gain, 127.5, 255, coded_length); - struct timeval t[3]; gettimeofday(&t[1], NULL); int M = 1; - - //srslte_vec_fprint_b(stdout, data_tx, frame_length); + for (int i=0;iptr, q->tmp, TB_ITER*frame_length, &best_state); chainback_viterbi37_port(q->ptr, q->tmp, TB_ITER*frame_length, best_state); - memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t)); + memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); } else { update_viterbi37_blk_port(q->ptr, symbols, frame_length + q->K - 1, NULL); chainback_viterbi37_port(q->ptr, data, frame_length, 0); @@ -98,7 +105,7 @@ int decode37_sse(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_length } update_viterbi37_blk_sse(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); chainback_viterbi37_sse(q->ptr, q->tmp, TB_ITER*frame_length, best_state); - memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t)); + memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); } else { update_viterbi37_blk_sse(q->ptr, symbols, frame_length+q->K-1, NULL); chainback_viterbi37_sse(q->ptr, data, frame_length, 0); @@ -123,7 +130,7 @@ void free37_sse(void *o) { #ifdef LV_HAVE_AVX2 -int decode37_avx2(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_length) { +int decode37_avx2_16bit(void *o, uint16_t *symbols, uint8_t *data, uint32_t frame_length) { srslte_viterbi_t *q = o; uint32_t best_state; @@ -133,10 +140,51 @@ int decode37_avx2(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_lengt q->framebits); return -1; } + + /* Initialize Viterbi decoder */ + init_viterbi37_avx2_16bit(q->ptr, q->tail_biting?-1:0); + + /* Decode block */ + if (q->tail_biting) { + for (int i=0;itmp_s[i*3*frame_length], symbols, 3*frame_length*sizeof(uint16_t)); + } + update_viterbi37_blk_avx2_16bit(q->ptr, q->tmp_s, TB_ITER*frame_length, &best_state); + chainback_viterbi37_avx2_16bit(q->ptr, q->tmp, TB_ITER*frame_length, best_state); + memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); + } else { + update_viterbi37_blk_avx2_16bit(q->ptr, symbols, frame_length+q->K-1, NULL); + chainback_viterbi37_avx2_16bit(q->ptr, data, frame_length, 0); + } + + return q->framebits; +} +void free37_avx2_16bit(void *o) { + srslte_viterbi_t *q = o; + + if (q->symbols_uc) { + free(q->symbols_uc); + } + if (q->tmp) { + free(q->tmp); + } + delete_viterbi37_avx2_16bit(q->ptr); +} + + +int decode37_avx2(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_length) { + srslte_viterbi_t *q = o; + + uint32_t best_state; + + if (frame_length > q->framebits) { + fprintf(stderr, "Initialized decoder for max frame length %d bits\n", + q->framebits); + return -1; + } /* Initialize Viterbi decoder */ init_viterbi37_avx2(q->ptr, q->tail_biting?-1:0); - /* Decode block */ if (q->tail_biting) { for (int i=0;iptr, q->tmp, TB_ITER*frame_length, &best_state); chainback_viterbi37_avx2(q->ptr, q->tmp, TB_ITER*frame_length, best_state); - memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t)); + memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); } else { update_viterbi37_blk_avx2(q->ptr, symbols, frame_length+q->K-1, NULL); chainback_viterbi37_avx2(q->ptr, data, frame_length, 0); @@ -164,6 +212,7 @@ void free37_avx2(void *o) { delete_viterbi37_avx2(q->ptr); } + #endif #ifdef HAVE_NEON @@ -188,7 +237,7 @@ int decode37_neon(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_lengt } update_viterbi37_blk_neon(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); chainback_viterbi37_neon(q->ptr, q->tmp, TB_ITER*frame_length, best_state); - memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t)); + memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); } else { update_viterbi37_blk_neon(q->ptr, symbols, frame_length+q->K-1, NULL); chainback_viterbi37_neon(q->ptr, data, frame_length, 0); @@ -368,6 +417,44 @@ int init37_avx2(srslte_viterbi_t *q, int poly[3], uint32_t framebits, bool tail_ return 0; } } + +int init37_avx2_16bit(srslte_viterbi_t *q, int poly[3], uint32_t framebits, bool tail_biting) { + q->K = 7; + q->R = 3; + q->framebits = framebits; + q->gain_quant_s = 4; + q->gain_quant = DEFAULT_GAIN; + q->tail_biting = tail_biting; + q->decode_s = decode37_avx2_16bit; + q->free = free37_avx2_16bit; + q->decode_f = NULL; + q->symbols_uc = srslte_vec_malloc(3 * (q->framebits + q->K - 1) * sizeof(uint8_t)); + q->symbols_us = srslte_vec_malloc(3 * (q->framebits + q->K - 1) * sizeof(uint16_t)); + if (!q->symbols_uc || !q->symbols_us) { + perror("malloc"); + return -1; + } + if (q->tail_biting) { + q->tmp = srslte_vec_malloc(TB_ITER*3*(q->framebits + q->K - 1) * sizeof(uint8_t)); + q->tmp_s = srslte_vec_malloc(TB_ITER*3*(q->framebits + q->K - 1) * sizeof(uint16_t)); + if (!q->tmp) { + perror("malloc"); + free37(q); + return -1; + } + } else { + q->tmp = NULL; + } + //printf("pt0\n"); + if ((q->ptr = create_viterbi37_avx2_16bit(poly, TB_ITER*framebits)) == NULL) { + fprintf(stderr, "create_viterbi37 failed\n"); + free37(q); + return -1; + } else { + return 0; + } +} + #endif void srslte_viterbi_set_gain_quant(srslte_viterbi_t *q, float gain_quant) { @@ -383,8 +470,13 @@ int srslte_viterbi_init(srslte_viterbi_t *q, srslte_viterbi_type_t type, int pol switch (type) { case SRSLTE_VITERBI_37: #ifdef LV_HAVE_SSE + #ifdef LV_HAVE_AVX2 + #ifdef VITERBI_16 + return init37_avx2_16bit(q, poly, max_frame_length, tail_bitting); + #else return init37_avx2(q, poly, max_frame_length, tail_bitting); + #endif #else return init37_sse(q, poly, max_frame_length, tail_bitting); #endif @@ -444,8 +536,13 @@ int srslte_viterbi_decode_f(srslte_viterbi_t *q, float *symbols, uint8_t *data, max = fabs(symbols[i]); } } - srslte_vec_quant_fuc(symbols, q->symbols_uc, q->gain_quant/max, 127.5, 255, len); - return srslte_viterbi_decode_uc(q, q->symbols_uc, data, frame_length); +#ifdef VITERBI_16 + srslte_vec_quant_fus(symbols, q->symbols_us, DEFAULT_GAIN_16/max, 32767.5, 65535, len); + return srslte_viterbi_decode_us(q, q->symbols_us, data, frame_length); +#else + srslte_vec_quant_fuc(symbols, q->symbols_uc, q->gain_quant/max, 127.5, 255, len); + return srslte_viterbi_decode_uc(q, q->symbols_uc, data, frame_length); +#endif } else { return q->decode_f(q, symbols, data, frame_length); } @@ -472,8 +569,20 @@ int srslte_viterbi_decode_s(srslte_viterbi_t *q, int16_t *symbols, uint8_t *data max = abs(symbols[i]); } } - srslte_vec_quant_suc(symbols, q->symbols_uc, (float) q->gain_quant/max, 127, 255, len); - return srslte_viterbi_decode_uc(q, q->symbols_uc, data, frame_length); +#ifdef VITERBI_16 + srslte_vec_quant_sus(symbols, q->symbols_us, 1, 32767, len); + return srslte_viterbi_decode_us(q, q->symbols_us, data, frame_length); +#else + srslte_vec_quant_suc(symbols, q->symbols_uc, (float) q->gain_quant/max, 127, 255, len); + return srslte_viterbi_decode_uc(q, q->symbols_uc, data, frame_length); +#endif + + +} + +int srslte_viterbi_decode_us(srslte_viterbi_t *q, uint16_t *symbols, uint8_t *data, uint32_t frame_length) +{ + return q->decode_s(q, symbols, data, frame_length); } diff --git a/lib/src/phy/fec/viterbi37.h b/lib/src/phy/fec/viterbi37.h index 574f4fd87..a77145592 100644 --- a/lib/src/phy/fec/viterbi37.h +++ b/lib/src/phy/fec/viterbi37.h @@ -110,3 +110,23 @@ int update_viterbi37_blk_avx2(void *p, uint32_t *best_state); +void *create_viterbi37_avx2_16bit(int polys[3], + uint32_t len); + +int init_viterbi37_avx2_16bit(void *p, + int starting_state); + + +void reset_blk_avx2_16bit(void *p, int nbits); + +int chainback_viterbi37_avx2_16bit(void *p, + uint8_t *data, + uint32_t nbits, + uint32_t endstate); + +void delete_viterbi37_avx2_16bit(void *p); + +int update_viterbi37_blk_avx2_16bit(void *p, + uint16_t *syms, + uint32_t nbits, + uint32_t *best_state); \ No newline at end of file diff --git a/lib/src/phy/fec/viterbi37_avx2.c b/lib/src/phy/fec/viterbi37_avx2.c index a00bb494b..8735bf7ea 100644 --- a/lib/src/phy/fec/viterbi37_avx2.c +++ b/lib/src/phy/fec/viterbi37_avx2.c @@ -76,14 +76,16 @@ int init_viterbi37_avx2(void *p, int starting_state) { struct v37 *vp = p; uint32_t i; firstGo = 1; + for(i=0;i<64;i++) vp->metrics1.c[i] = 63; - + clear_v37_avx2(vp); vp->old_metrics = &vp->metrics1; vp->new_metrics = &vp->metrics2; vp->dp = vp->decisions; + if (starting_state != -1) { vp->old_metrics->c[starting_state & 63] = 0; /* Bias known start state */ } @@ -259,7 +261,7 @@ void update_viterbi37_blk_avx2(void *p,unsigned char *syms,int nbits, uint32_t * d->s[0] = (short) y; d->s[1] = (short) x; d->s[2] = (short) (y >>16); - d->s[3] = (short)(x>> 16); + d->s[3] = (short) (x >>16); __m256i unpack; diff --git a/lib/src/phy/fec/viterbi37_avx2_16bit.c b/lib/src/phy/fec/viterbi37_avx2_16bit.c new file mode 100644 index 000000000..cda292017 --- /dev/null +++ b/lib/src/phy/fec/viterbi37_avx2_16bit.c @@ -0,0 +1,363 @@ +/* Adapted Phil Karn's r=1/3 k=9 viterbi decoder to r=1/3 k=7 + * + * K=15 r=1/6 Viterbi decoder for x86 SSE2 + * Copyright Mar 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "parity.h" + +//#define DEBUG + +#ifdef LV_HAVE_AVX2 + + +#include +#include +#include +#include + +typedef union { + //unsigned char c[64]; + //__m128i v[4]; + unsigned short c[64]; + __m256i v[4]; +} metric_t; + +typedef union { + unsigned int w[2]; + unsigned char c[8]; + unsigned short s[4]; + __m64 v[1]; +} decision_t; + +union branchtab27 { + + //unsigned char c[32]; + //__m128i v[2]; + unsigned short c[32]; + __m256i v[2]; + +} Branchtab37_sse2[3]; + +int firstGo; +/* State info for instance of Viterbi decoder */ +struct v37 { + metric_t metrics1; /* path metric buffer 1 */ + metric_t metrics2; /* path metric buffer 2 */ + decision_t *dp; /* Pointer to current decision */ + metric_t *old_metrics,*new_metrics; /* Pointers to path metrics, swapped on every bit */ + decision_t *decisions; /* Beginning of decisions for block */ + uint32_t len; +}; + +void set_viterbi37_polynomial_avx2_16bit(int polys[3]) { + int state; + for(state=0;state < 32;state++){ + Branchtab37_sse2[0].c[state] = (polys[0] < 0) ^ parity((2*state) & polys[0]) ? 65535:0; + Branchtab37_sse2[1].c[state] = (polys[1] < 0) ^ parity((2*state) & polys[1]) ? 65535:0; + Branchtab37_sse2[2].c[state] = (polys[2] < 0) ^ parity((2*state) & polys[2]) ? 65535:0; + } +} + +void clear_v37_avx2_16bit(struct v37 *vp) { + bzero(vp->decisions, sizeof(decision_t)*vp->len); + vp->dp = NULL; + bzero(&vp->metrics1, sizeof(metric_t)); + bzero(&vp->metrics2, sizeof(metric_t)); + vp->old_metrics = NULL; + vp->new_metrics = NULL; +} + + +/* Initialize Viterbi decoder for start of new frame */ +int init_viterbi37_avx2_16bit(void *p, int starting_state) { + + struct v37 *vp = p; + uint32_t i; + + for(i=0;i<64;i++) + vp->metrics1.c[i] = 63; + + clear_v37_avx2_16bit(vp); +firstGo = 1; + vp->old_metrics = &vp->metrics1; + vp->new_metrics = &vp->metrics2; + vp->dp = vp->decisions; + if (starting_state != -1) { + vp->old_metrics->c[starting_state & 63] = 0; /* Bias known start state */ + } + return 0; +} + +/* Create a new instance of a Viterbi decoder */ +void *create_viterbi37_avx2_16bit(int polys[3], uint32_t len) { + void *p; + struct v37 *vp; + + set_viterbi37_polynomial_avx2_16bit(polys); + + /* Ordinary malloc() only returns 8-byte alignment, we need 16 */ + if(posix_memalign(&p, sizeof(__m256i),sizeof(struct v37))) + return NULL; + + vp = (struct v37 *)p; + if(posix_memalign(&p, sizeof(__m256i),(len+6)*sizeof(decision_t))) { + free(vp); + return NULL; + } + vp->decisions = (decision_t *)p; + vp->len = len+6; + return vp; +} + + +/* Viterbi chainback */ +int chainback_viterbi37_avx2_16bit( + void *p, + uint8_t *data, /* Decoded output data */ + uint32_t nbits, /* Number of data bits */ + uint32_t endstate) { /* Terminal encoder state */ + struct v37 *vp = p; + + if (p == NULL) + return -1; + + decision_t *d = (decision_t *)vp->decisions; + + /* Make room beyond the end of the encoder register so we can + * accumulate a full byte of decoded data + */ + endstate %= 64; + endstate <<= 2; + + /* The store into data[] only needs to be done every 8 bits. + * But this avoids a conditional branch, and the writes will + * combine in the cache anyway + */ + d += 6; /* Look past tail */ + while(nbits--) { + int k; + + k = (d[nbits].c[(endstate>>2)/8] >> ((endstate>>2)%8)) & 1; + endstate = (endstate >> 1) | (k << 7); + data[nbits] = k; + //printf("nbits=%d, endstate=%3d, k=%d, w[0]=%d, w[1]=%d, c=%d\n", nbits, endstate, k, d[nbits].s[1]&1, d[nbits].s[2]&1, d[nbits].c[(endstate>>2)/8]&1); + } + return 0; +} + +/* Delete instance of a Viterbi decoder */ +void delete_viterbi37_avx2_16bit(void *p){ + struct v37 *vp = p; + + if(vp != NULL){ + free(vp->decisions); + free(vp); + } +} + +void print_256i(char *s, __m256i val) { + + printf("%s: ", s); + + uint16_t *x = (uint16_t*) &val; + for (int i=0;i<16;i++) { + printf("%.5f, ", (float)x[i]/65535); + } + printf("\n"); +} +void print_256i_char(char *s, __m256i val) { + + printf("%s: ", s); + + uint8_t *x = (uint8_t*) &val; + for (int i=0;i<32;i++) { + printf("%d, ",x[31-i]); + } + printf("\n"); +} + + +inline unsigned short my_mm256_movemask_epi16(__m256i x) { + uint32_t x1 = _mm256_movemask_epi8(x); + uint16_t tmp = 0; + for(int i = 0; i<16;i++){ + tmp |= ((x1 >> ((i*2)+1)) & 0x01) << i; + } + + return (tmp); + } + + +void update_viterbi37_blk_avx2_16bit(void *p, unsigned short *syms, int nbits, uint32_t *best_state) { + struct v37 *vp = p; + decision_t *d; + + if(p == NULL) + return; + +#ifdef DEBUG + printf("["); +#endif + + d = (decision_t *) vp->dp; + + for (int s=0;sold_metrics->v[i],metric); + m3 = _mm256_add_epi16(vp->old_metrics->v[2+i],metric); + m1 = _mm256_add_epi16(vp->old_metrics->v[2+i],m_metric); + m2 = _mm256_add_epi16(vp->old_metrics->v[i],m_metric); + + + /* Compare and select, using modulo arithmetic */ + + decision0 = _mm256_cmpgt_epi16(_mm256_sub_epi16(m0,m1),_mm256_setzero_si256()); + decision1 = _mm256_cmpgt_epi16(_mm256_sub_epi16(m2,m3),_mm256_setzero_si256()); + survivor0 = _mm256_or_si256(_mm256_and_si256(decision0,m1),_mm256_andnot_si256(decision0,m0)); + survivor1 = _mm256_or_si256(_mm256_and_si256(decision1,m3),_mm256_andnot_si256(decision1,m2)); + + + + /* Pack each set of decisions into 16 bits */ + + decision0 = _mm256_permute4x64_epi64(decision0,216); + decision1 = _mm256_permute4x64_epi64(decision1,216); + + __m256i packed = _mm256_packus_epi16( _mm256_srli_epi16(_mm256_unpacklo_epi16(decision0,decision1),8),_mm256_srli_epi16(_mm256_unpackhi_epi16(decision0,decision1),8)); + + d->w[i] = _mm256_movemask_epi8(packed); + + unsigned char temp_char1 = d->c[4*i + 1]; + unsigned char temp_char2 = d->c[4*i + 2]; + + d->c[4*i+1] = temp_char2; + d->c[4*i+2] = temp_char1; + + /* Store surviving metrics */ + survivor0 = _mm256_permute4x64_epi64(survivor0,216); + survivor1 = _mm256_permute4x64_epi64(survivor1,216); + + vp->new_metrics->v[2*i] = _mm256_unpacklo_epi16(survivor0,survivor1); + vp->new_metrics->v[2*i+1] = _mm256_unpackhi_epi16(survivor0,survivor1); + + } + + // See if we need to normalize + if (vp->new_metrics->c[0] > 25600) { + int i; + + uint16_t adjust; + __m256i adjustv; + union { __m256i v; signed short w[8]; } t; + + adjustv = vp->new_metrics->v[0]; + for(i=1;i<4;i++) { + adjustv = _mm256_min_epu16(adjustv,vp->new_metrics->v[i]); + } + + adjustv = _mm256_min_epu16(adjustv,_mm256_srli_si256(adjustv,16)); + adjustv = _mm256_min_epu16(adjustv,_mm256_srli_si256(adjustv,8)); + adjustv = _mm256_min_epu16(adjustv,_mm256_srli_si256(adjustv,4)); + + + t.v = adjustv; + adjust = t.w[0]; + adjustv = _mm256_set1_epi16(adjust); + + /* We cannot use a saturated subtract, because we often have to adjust by more than SHRT_MAX + * This is okay since it can't overflow anyway + */ + for(i=0;i<4;i++) + vp->new_metrics->v[i] = _mm256_sub_epi16(vp->new_metrics->v[i],adjustv); + } + + + d++; + /* Swap pointers to old and new metrics */ + tmp = vp->old_metrics; + vp->old_metrics = vp->new_metrics; + vp->new_metrics = tmp; + } + + if (best_state) { + uint32_t i, bst=0; + + uint16_t minmetric= UINT16_MAX; + for (i=0;i<64;i++) { + if (vp->old_metrics->c[i] <= minmetric) { + bst = i; + minmetric = vp->old_metrics->c[i]; + } + } + *best_state = bst; + } + + #ifdef DEBUG + printf("];\n===========================================\n"); +#endif + + vp->dp = d; +} + +#endif + + + diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index 809d4c392..f4e97fad6 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -98,14 +98,14 @@ void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, uint8_t *input, uin w_offset_p=8-w_offset; } - uint32_t i = st * 8; + int i = st * 8; byte_idx += i - w_offset_p; bit_mask += i - w_offset_p; output_ptr += st; #ifdef LV_HAVE_SSE - for(; i < q->nof_bits - 15; i += 16) { + for(; i < (int) q->nof_bits - 15; i += 16) { __m128i in128; in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x7); in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x6); @@ -137,7 +137,7 @@ void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, uint8_t *input, uin #endif /* LV_HAVE_SSE */ - for(; i < q->nof_bits; i += 8) { + for(; i < (int) q->nof_bits - 7; i += 8) { uint8_t out0 = (input[*(byte_idx++)] & *(bit_mask++))?mask[0]:(uint8_t)0; uint8_t out1 = (input[*(byte_idx++)] & *(bit_mask++))?mask[1]:(uint8_t)0; uint8_t out2 = (input[*(byte_idx++)] & *(bit_mask++))?mask[2]:(uint8_t)0; diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 35457fcb5..abedfd5a5 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -363,6 +363,20 @@ uint32_t srslte_vec_max_abs_ci(const cf_t *x, const uint32_t len) { return srslte_vec_max_ci_simd(x, len); } +void srslte_vec_quant_fus(float *in, uint16_t *out, float gain, float offset, float clip, uint32_t len) { + int i; + long tmp; + + for (i=0;i clip) + tmp = clip; + out[i] = (uint16_t) tmp; + } +} + void srslte_vec_quant_fuc(const float *in, uint8_t *out, const float gain, const float offset, const float clip, const uint32_t len) { int i; int tmp; @@ -391,6 +405,26 @@ void srslte_vec_quant_suc(const int16_t *in, uint8_t *out, const float gain, con } } +void srslte_vec_quant_sus(const int16_t *in, uint16_t *out, const float gain, const int16_t offset, const uint32_t len) { + int i; + int16_t tmp; + + for (i=0;iinfo("Added bearer %s\n", get_rb_name(lcid)); + pdcp_log->info("Added bearer %s\n", rrc->get_rb_name(lcid).c_str()); } else { - pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid)); + pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); } } diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 27425a698..088515096 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -64,7 +64,7 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_, start(PDCP_THREAD_PRIO); - log->debug("Init %s\n", get_rb_name(lcid)); + log->debug("Init %s\n", rrc->get_rb_name(lcid).c_str()); } void pdcp_entity::stop() @@ -94,7 +94,7 @@ void pdcp_entity::reset() { active = false; if(log) - log->debug("Reset %s\n", get_rb_name(lcid)); + log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); } bool pdcp_entity::is_active() @@ -107,7 +107,7 @@ void pdcp_entity::write_sdu(byte_buffer_t *sdu) { log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", - get_rb_name(lcid), tx_count, + rrc->get_rb_name(lcid).c_str(), tx_count, (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); if (cfg.is_control) { @@ -131,7 +131,7 @@ void pdcp_entity::write_sdu(byte_buffer_t *sdu) cipher_encrypt(&sdu->msg[sn_len_bytes], sdu->N_bytes-sn_len_bytes, &sdu->msg[sn_len_bytes]); - log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", get_rb_name(lcid)); + log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str()); } tx_count++; @@ -340,49 +340,17 @@ void pdcp_entity::run_thread() while(running) { rx_pdu_queue.read(&pdu); log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU, do_integrity = %s, do_encryption = %s", - get_rb_name(lcid), (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); - - // Handle SRB messages - switch(lcid) - { - case RB_ID_SRB0: - // Simply pass on to RRC - rrc->write_pdu(RB_ID_SRB0, pdu); - break; - case RB_ID_SRB1: // Intentional fall-through - case RB_ID_SRB2: - uint32_t sn; - if (do_encryption) { - cipher_decrypt(&(pdu->msg[sn_len_bytes]), - rx_count, - pdu->N_bytes - sn_len_bytes, - &(pdu->msg[sn_len_bytes])); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid)); - } - - if (do_integrity) { - integrity_verify(pdu->msg, - rx_count, - pdu->N_bytes - 4, - &(pdu->msg[pdu->N_bytes - 4])); - } - - pdcp_unpack_control_pdu(pdu, &sn); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn); - rrc->write_pdu(lcid, pdu); - break; - } + rrc->get_rb_name(lcid).c_str(), (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); // Handle DRB messages - if(lcid >= RB_ID_DRB1) - { + if (cfg.is_data) { uint32_t sn; if (do_encryption) { cipher_decrypt(&(pdu->msg[sn_len_bytes]), rx_count, pdu->N_bytes - sn_len_bytes, &(pdu->msg[sn_len_bytes])); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid)); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); } if(12 == cfg.sn_len) { @@ -390,16 +358,40 @@ void pdcp_entity::run_thread() } else { pdcp_unpack_data_pdu_short_sn(pdu, &sn); } - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); gw->write_pdu(lcid, pdu); + } else { + // Handle SRB messages + if (cfg.is_control) { + uint32_t sn; + if (do_encryption) { + cipher_decrypt(&(pdu->msg[sn_len_bytes]), + rx_count, + pdu->N_bytes - sn_len_bytes, + &(pdu->msg[sn_len_bytes])); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); + } + + if (do_integrity) { + integrity_verify(pdu->msg, + rx_count, + pdu->N_bytes - 4, + &(pdu->msg[pdu->N_bytes - 4])); + } + + pdcp_unpack_control_pdu(pdu, &sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); + } + // pass to RRC + rrc->write_pdu(lcid, pdu); } - rx_count++; } } uint8_t pdcp_entity::get_bearer_id(uint8_t lcid) { + #define RB_ID_SRB2 2 if(lcid <= RB_ID_SRB2) { return lcid - 1; } else { diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 16319c268..7a7180e45 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -224,10 +224,10 @@ void rlc::add_bearer(uint32_t lcid) cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; add_bearer(lcid, srslte_rlc_config_t(&cnfg)); } else { - rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid)); + rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); } }else{ - rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", get_rb_name(lcid)); + rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", rrc->get_rb_name(lcid).c_str()); } } @@ -240,7 +240,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) if (!rlc_array[lcid].active()) { rlc_log->info("Adding radio bearer %s with mode %s\n", - get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); switch(cnfg.rlc_mode) { case LIBLTE_RRC_RLC_MODE_AM: @@ -260,7 +260,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) return; } } else { - rlc_log->warning("Bearer %s already created.\n", get_rb_name(lcid)); + rlc_log->warning("Bearer %s already created.\n", rrc->get_rb_name(lcid).c_str()); } rlc_array[lcid].configure(cnfg); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index c048133d6..c6c69c12b 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -79,7 +79,7 @@ void rlc_am::configure(srslte_rlc_config_t cfg_) cfg = cfg_.am; log->info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, " "t_reordering=%d, t_status_prohibit=%d\n", - get_rb_name(lcid), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh, + rrc->get_rb_name(lcid).c_str(), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh, cfg.t_reordering, cfg.t_status_prohibit); } @@ -175,7 +175,7 @@ uint32_t rlc_am::get_bearer() void rlc_am::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); tx_sdu_queue.write(sdu); } @@ -229,7 +229,7 @@ uint32_t rlc_am::get_total_buffer_state() // Room needed for fixed header? if(n_bytes > 0) { - n_bytes += 2; + n_bytes += 3; log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes); } @@ -285,7 +285,7 @@ uint32_t rlc_am::get_buffer_state() // Room needed for fixed header? if(n_bytes > 0) { - n_bytes += 2; + n_bytes += 3; log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes); } @@ -359,7 +359,7 @@ void rlc_am::check_reordering_timeout() if(reordering_timeout.is_running() && reordering_timeout.expired()) { reordering_timeout.reset(); - log->debug("%s reordering timeout expiry - updating vr_ms\n", get_rb_name(lcid)); + log->debug("%s reordering timeout expiry - updating vr_ms\n", rrc->get_rb_name(lcid).c_str()); // 36.322 v10 Section 5.1.3.2.4 vr_ms = vr_x; @@ -433,7 +433,7 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_len > 0 && nof_bytes >= (uint32_t)pdu_len) { log->info("%s Tx status PDU - %s\n", - get_rb_name(lcid), rlc_am_to_string(&status).c_str()); + rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); do_status = false; poll_received = false; @@ -444,7 +444,7 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) return rlc_am_write_status_pdu(&status, payload); }else{ log->warning("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", - get_rb_name(lcid), nof_bytes, pdu_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); return 0; } } @@ -478,7 +478,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) return -1; } if(retx.is_segment || req_size > (int)nof_bytes) { - log->debug("%s build_retx_pdu - resegmentation required\n", get_rb_name(lcid)); + log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str()); return build_segment(payload, nof_bytes, retx); } @@ -503,7 +503,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) rrc->max_retx_attempted(); log->info("%s Retx PDU scheduled for tx. SN: %d, retx count: %d\n", - get_rb_name(lcid), retx.sn, tx_window[retx.sn].retx_count); + rrc->get_rb_name(lcid).c_str(), retx.sn, tx_window[retx.sn].retx_count); debug_state(); return (ptr-payload) + tx_window[retx.sn].buf->N_bytes; @@ -540,7 +540,7 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r if(nof_bytes <= head_len) { log->warning("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n", - get_rb_name(lcid), nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; } pdu_space = nof_bytes-head_len; @@ -606,15 +606,15 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r memcpy(ptr, data, len); log->info("%s Retx PDU segment scheduled for tx. SN: %d, SO: %d\n", - get_rb_name(lcid), retx.sn, retx.so_start); + rrc->get_rb_name(lcid).c_str(), retx.sn, retx.so_start); debug_state(); int pdu_len = (ptr-payload) + len; if(pdu_len > (int)nof_bytes) { log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n", - get_rb_name(lcid), nof_bytes, pdu_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); log->debug("%s Retx PDU segment length error. Header len: %d, Payload len: %d, N_li: %d\n", - get_rb_name(lcid), (ptr-payload), len, new_header.N_li); + rrc->get_rb_name(lcid).c_str(), (ptr-payload), len, new_header.N_li); } return pdu_len; @@ -662,13 +662,13 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_space <= head_len + 1) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", - get_rb_name(lcid), nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); pool->deallocate(pdu); return 0; } log->debug("%s Building PDU - pdu_space: %d, head_len: %d \n", - get_rb_name(lcid), pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), pdu_space, head_len); // Check for SDU segment if(tx_sdu) @@ -683,7 +683,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - get_rb_name(lcid), tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -694,7 +694,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - get_rb_name(lcid), to_move, pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); } // Pull SDUs from queue @@ -718,7 +718,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - get_rb_name(lcid), tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -728,7 +728,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_space = 0; log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - get_rb_name(lcid), to_move, pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); } if(tx_sdu) @@ -737,11 +737,11 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set Poll bit pdu_without_poll++; byte_without_poll += (pdu->N_bytes + head_len); - log->debug("%s pdu_without_poll: %d\n", get_rb_name(lcid), pdu_without_poll); - log->debug("%s byte_without_poll: %d\n", get_rb_name(lcid), byte_without_poll); + log->debug("%s pdu_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), pdu_without_poll); + log->debug("%s byte_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), byte_without_poll); if(poll_required()) { - log->debug("%s setting poll bit to request status\n", get_rb_name(lcid)); + log->debug("%s setting poll bit to request status\n", rrc->get_rb_name(lcid).c_str()); header.p = 1; poll_sn = vt_s; pdu_without_poll = 0; @@ -752,7 +752,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set SN header.sn = vt_s; vt_s = (vt_s + 1)%MOD; - log->info("%s PDU scheduled for tx. SN: %d\n", get_rb_name(lcid), header.sn); + log->info("%s PDU scheduled for tx. SN: %d\n", rrc->get_rb_name(lcid).c_str(), header.sn); // Place PDU in tx_window, write header and TX tx_window[header.sn].buf = pdu; @@ -773,26 +773,26 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d", - get_rb_name(lcid), header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - get_rb_name(lcid), header.sn, vr_r, vr_mr); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s Discarding duplicate SN: %d\n", - get_rb_name(lcid), header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); return; } @@ -825,7 +825,7 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -870,16 +870,16 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU segment. SN: %d, SO: %d", - get_rb_name(lcid), header.sn, header.so); + rrc->get_rb_name(lcid).c_str(), header.sn, header.so); // Check inside rx window if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - get_rb_name(lcid), header.sn, vr_r, vr_mr); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); return; } @@ -898,7 +898,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a if(rx_segments.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } @@ -928,7 +928,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -946,12 +946,12 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) { - log->info_hex(payload, nof_bytes, "%s Rx control PDU", get_rb_name(lcid)); + log->info_hex(payload, nof_bytes, "%s Rx control PDU", rrc->get_rb_name(lcid).c_str()); rlc_status_pdu_t status; rlc_am_read_status_pdu(payload, nof_bytes, &status); - log->info("%s Rx Status PDU: %s\n", get_rb_name(lcid), rlc_am_to_string(&status).c_str()); + log->info("%s Rx Status PDU: %s\n", rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); poll_retx_timeout.reset(); @@ -989,7 +989,7 @@ void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) } } else { log->warning("%s invalid segment NACK received for SN %d. so_start: %d, so_end: %d, N_bytes: %d\n", - get_rb_name(lcid), i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); + rrc->get_rb_name(lcid).c_str(), i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); } } @@ -1043,7 +1043,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += len; rx_window[vr_r].buf->msg += len; rx_window[vr_r].buf->N_bytes -= len; - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", get_rb_name(lcid)); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1059,7 +1059,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += rx_window[vr_r].buf->N_bytes; if(rlc_am_end_aligned(rx_window[vr_r].header.fi)) { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", get_rb_name(lcid)); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1103,7 +1103,7 @@ void rlc_am::debug_state() { log->debug("%s vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d " "vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d\n", - get_rb_name(lcid), vt_a, vt_ms, vt_s, poll_sn, + rrc->get_rb_name(lcid).c_str(), vt_a, vt_ms, vt_s, poll_sn, vr_r, vr_mr, vr_x, vr_ms, vr_h); } diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 4559dd07b..627752494 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -84,7 +84,7 @@ uint32_t rlc_tm::get_bearer() // PDCP interface void rlc_tm::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); ul_queue.write(sdu); } @@ -104,7 +104,7 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t pdu_size = ul_queue.size_tail_bytes(); if(pdu_size > nof_bytes) { - log->error("TX %s PDU size larger than MAC opportunity\n", get_rb_name(lcid)); + log->error("TX %s PDU size larger than MAC opportunity\n", rrc->get_rb_name(lcid).c_str()); return 0; } byte_buffer_t *buf; @@ -112,9 +112,9 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_size = buf->N_bytes; memcpy(payload, buf->msg, buf->N_bytes); log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - get_rb_name(lcid), buf->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); pool->deallocate(buf); - log->info_hex(payload, pdu_size, "TX %s, %s PDU", get_rb_name(lcid), rlc_mode_text[RLC_MODE_TM]); + log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); return pdu_size; } diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 5b395228f..4756e2f7c 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -75,18 +75,18 @@ void rlc_um::configure(srslte_rlc_config_t cnfg_) case LIBLTE_RRC_RLC_MODE_UM_BI: log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: log->info("%s configured in %s mode: tx_sn_field_length=%u bits\n", - get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits\n", - get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; default: @@ -153,7 +153,7 @@ uint32_t rlc_um::get_bearer() void rlc_um::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); tx_sdu_queue.write(sdu); } @@ -216,7 +216,7 @@ void rlc_um::timer_expired(uint32_t timeout_id) // 36.322 v10 Section 5.1.2.2.4 log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", - get_rb_name(lcid)); + rrc->get_rb_name(lcid).c_str()); log->warning("Lost PDU SN: %d\n", vr_ur); pdu_lost = true; @@ -281,7 +281,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) { pool->deallocate(pdu); log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", - get_rb_name(lcid), nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; } @@ -291,7 +291,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding remainder of SDU segment - %d bytes of %d remaining\n", - get_rb_name(lcid), to_move, tx_sdu->N_bytes); + rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -301,7 +301,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - get_rb_name(lcid), tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -320,7 +320,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding new SDU segment - %d bytes of %d remaining\n", - get_rb_name(lcid), to_move, tx_sdu->N_bytes); + rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -330,7 +330,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - get_rb_name(lcid), tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -345,11 +345,11 @@ int rlc_um::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(lcid), pdu->N_bytes); + log->debug("%s packing PDU with length %d\n", rrc->get_rb_name(lcid).c_str(), 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(lcid), pdu->N_bytes); + log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); pool->deallocate(pdu); debug_state(); @@ -363,20 +363,20 @@ void rlc_um::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.rx_sn_field_length, &header); log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d", - get_rb_name(lcid), header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) { log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - get_rb_name(lcid), header.sn, vr_ur, vr_uh); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_ur, vr_uh); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { log->info("%s Discarding duplicate SN: %d\n", - get_rb_name(lcid), header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); return; } @@ -451,7 +451,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", get_rb_name(lcid), vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -471,7 +471,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (lower edge last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", get_rb_name(lcid), vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -505,7 +505,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (update vr_ur middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", get_rb_name(lcid), vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -534,7 +534,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (update vr_ur last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", get_rb_name(lcid), vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -564,7 +564,7 @@ bool rlc_um::inside_reordering_window(uint16_t sn) void rlc_um::debug_state() { log->debug("%s vt_us = %d, vr_ur = %d, vr_ux = %d, vr_uh = %d \n", - get_rb_name(lcid), vt_us, vr_ur, vr_ux, vr_uh); + rrc->get_rb_name(lcid).c_str(), vt_us, vr_ur, vr_ux, vr_uh); } diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index b5df0900a..68f3d1344 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -49,13 +49,6 @@ typedef struct { using srslte::byte_buffer_t; - -static std::string rb_id_str[] = {"SRB0", "SRB1", "SRB2", - "DRB1","DRB2","DRB3", - "DRB4","DRB5","DRB6", - "DRB7","DRB8"}; - - namespace srsue { class rrc @@ -195,6 +188,33 @@ private: uint32_t n311_cnt, N311; uint32_t t301, t310, t311, t304; + // Radio bearers + typedef enum{ + RB_ID_SRB0 = 0, + RB_ID_SRB1, + RB_ID_SRB2, + RB_ID_DRB1, + RB_ID_DRB2, + RB_ID_DRB3, + RB_ID_DRB4, + RB_ID_DRB5, + RB_ID_DRB6, + RB_ID_DRB7, + RB_ID_DRB8, + RB_ID_MAX + } rb_id_t; + + static const std::string rb_id_str[]; + + std::string get_rb_name(uint32_t lcid) + { + if (lcid < RB_ID_MAX) { + return rb_id_str[lcid]; + } else { + return "INVALID_RB"; + } + } + typedef struct { uint32_t earfcn; srslte_cell_t phy_cell; @@ -405,7 +425,6 @@ private: void set_phy_default(); void set_mac_default(); void set_rrc_default(); - void set_bearers(); }; } // namespace srsue diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 1fb26c177..9a9015af7 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -198,7 +198,7 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { uint8 sec_hdr_type; bool mac_valid = false; - nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", get_rb_name(lcid)); + nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rrc->get_rb_name(lcid).c_str()); // Parse the message security header liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)pdu, &pd, &sec_hdr_type); @@ -228,7 +228,7 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { // Parse the message header liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) pdu, &pd, &msg_type); - nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s Decrypted PDU", get_rb_name(lcid)); + nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s Decrypted PDU", rrc->get_rb_name(lcid).c_str()); // TODO: Check if message type requieres specical security header type and if it isvalid switch (msg_type) { @@ -770,7 +770,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) &sdu->msg[1]); nas_log->info("Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s\n", ctxt.tx_count, - get_rb_name(lcid)); + rrc->get_rb_name(lcid).c_str()); rrc->write_sdu(lcid, sdu); ctxt.tx_count++; pool->deallocate(pdu); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 2ea1b877d..39846f425 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1447,7 +1447,7 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid)); + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); switch (state) { case RRC_STATE_CONNECTING: send_con_setup_complete(sdu); @@ -1462,7 +1462,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { } void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid).c_str()); switch (lcid) { case RB_ID_SRB0: @@ -1524,7 +1524,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dl_dcch_msg); rrc_log->info("%s - Received %s\n", - get_rb_name(lcid), + get_rb_name(lcid).c_str(), liblte_rrc_dl_dcch_msg_type_text[dl_dcch_msg.msg_type]); // Reset and reuse pdu buffer if possible @@ -2098,7 +2098,7 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) { } srbs[srb_cnfg->srb_id] = *srb_cnfg; - rrc_log->info("Added radio bearer %s\n", get_rb_name(srb_cnfg->srb_id)); + rrc_log->info("Added radio bearer %s\n", get_rb_name(srb_cnfg->srb_id).c_str()); } void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) { @@ -2157,7 +2157,7 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) { drbs[lcid] = *drb_cnfg; drb_up = true; - rrc_log->info("Added radio bearer %s\n", get_rb_name(lcid)); + rrc_log->info("Added radio bearer %s\n", get_rb_name(lcid).c_str()); } void rrc::release_drb(uint8_t lcid) { @@ -2807,13 +2807,9 @@ float rrc::rrc_meas::range_to_value(quantity_t quant, uint8_t range) { return val; } - - - - - - - - +const std::string rrc::rb_id_str[] = {"SRB0", "SRB1", "SRB2", + "DRB1", "DRB2", "DRB3", + "DRB4", "DRB5", "DRB6", + "DRB7", "DRB8"}; } // namespace srsue diff --git a/srsue/test/upper/CMakeLists.txt b/srsue/test/upper/CMakeLists.txt index cbffe1cc8..00fb54576 100644 --- a/srsue/test/upper/CMakeLists.txt +++ b/srsue/test/upper/CMakeLists.txt @@ -26,7 +26,10 @@ add_executable(rrc_reconfig_test rrc_reconfig_test.cc) target_link_libraries(rrc_reconfig_test srsue_upper srslte_upper srslte_phy) add_test(rrc_reconfig_test rrc_reconfig_test) - +add_executable(nas_test nas_test.cc) +target_link_libraries(nas_test srsue_upper srslte_upper srslte_phy) +add_test(nas_test nas_test) + ######################################################################## # Option to run command after build (useful for remote builds) ######################################################################## diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 6aa9f29e5..f328d77df 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -25,35 +25,37 @@ */ #include +#include #include "upper/usim.h" #include "upper/nas.h" #include "srslte/upper/rlc.h" #include "upper/rrc.h" #include "mac/mac.h" +#include "srslte/common/log_filter.h" #include "srslte/upper/pdcp_entity.h" #include "srslte/upper/pdcp.h" -#include "srslte/common/log_stdout.h" #include "srslte/interfaces/ue_interfaces.h" +#include "srslte/common/bcd_helpers.h" -using namespace srsue; +using namespace srsue; +#define LCID 1 -uint8_t pdu1[] = { -0x03, 0x22, 0x16, 0x15, 0xe8 , 0x00 , 0x00 , 0x03 , 0x13 , 0xb0 , 0x00 , 0x02 , 0x90 , 0x08, -0x79, 0xf0, 0x00, 0x00, 0x40 , 0xb5 , 0x01 , 0x25 , 0x40 , 0xcc , 0x1d , 0x08 , 0x04 , 0x3c , 0x18 , 0x00, -0x4c, 0x02, 0x20, 0x0f, 0xa8 , 0x00 , 0x65 , 0x48 , 0x07 , 0x04 , 0x04 , 0x24 , 0x1c , 0x19 , 0x05 , 0x41, -0x39, 0x39, 0x4d, 0x38, 0x14 , 0x04 , 0x28 , 0xd1 , 0x5e , 0x6d , 0x78 , 0x13 , 0xfb , 0xf9 , 0x01 , 0xb1, -0x40, 0x2f, 0xd8, 0x4c, 0x02 , 0x20 , 0x00 , 0x5b , 0x78 , 0x00 , 0x07 , 0xa1 , 0x25 , 0xa9 , 0xc1 , 0x3f, -0xd9, 0x40, 0x41, 0xf5, 0x1b , 0x58 , 0x2f , 0x27 , 0x28 , 0xa0 , 0xed , 0xde , 0x54 , 0x43 , 0x48 , 0xc0, -0x56, 0xcc, 0x00, 0x02, 0x84 , 0x00 , 0x42 , 0x0a , 0xf1 , 0x63 }; +uint8_t auth_request_pdu[] = { 0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0xe6, 0xa4, + 0xce, 0xd9, 0x86, 0xfb, 0xe5, 0xce, 0x9b, 0x62, 0x5e, 0x10, + 0x67, 0x57, 0xb3, 0xc2, 0xb9, 0x70, 0x90, 0x01, 0x0c, 0x72, + 0x8a, 0x67, 0x57, 0x92, 0x52, 0xb8 }; -uint32_t PDU1_LEN = 104; +uint8_t sec_mode_command_pdu[] = { 0x37, 0x37, 0xc7, 0x67, 0xae, 0x00, 0x07, 0x5d, 0x02, 0x01, + 0x02, 0xe0, 0x60, 0xc1 }; +uint16 mcc = 61441; +uint16 mnc = 65281; -#define LCID 3 +using namespace srslte; -namespace srsue { +namespace srslte { // fake classes class pdcp_dummy : public rrc_interface_pdcp @@ -63,121 +65,154 @@ public: void write_pdu_bcch_bch(byte_buffer_t *pdu) {} void write_pdu_bcch_dlsch(byte_buffer_t *pdu) {} void write_pdu_pcch(byte_buffer_t *pdu) {} + std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } }; - - class rrc_dummy : public rrc_interface_nas { public: void write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - + printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + last_sdu_len = sdu->N_bytes; + srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); } + std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } + uint32_t get_last_sdu_len() { return last_sdu_len; } - uint16_t get_mcc() { return 0x11; } - uint16_t get_mnc() { return 0xff; } - void enable_capabilities() { + void plmn_search() {}; + void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {}; - } + uint16_t get_mcc() { return mcc; } + uint16_t get_mnc() { return mnc; } + void enable_capabilities() {} + +private: + uint32_t last_sdu_len; }; class gw_dummy : public gw_interface_nas, public gw_interface_pdcp { - error_t setup_if_addr(uint32_t ip_addr, char *err_str) {} + error_t setup_if_addr(uint32_t ip_addr, char *err_str) { return ERROR_NONE; } void write_pdu(uint32_t lcid, byte_buffer_t *pdu) {} }; } -class usim_dummy : public usim_interface_nas -{ - void get_imsi_vec(uint8_t* imsi_, uint32_t n){ - - } - void get_imei_vec(uint8_t* imei_, uint32_t n){ - - } - void generate_authentication_response(uint8_t *rand, - uint8_t *autn_enb, - uint16_t mcc, - uint16_t mnc, - bool *net_valid, - uint8_t *res){ - - } - - - void generate_nas_keys(uint8_t *k_nas_enc, - uint8_t *k_nas_int, - CIPHERING_ALGORITHM_ID_ENUM cipher_algo, - INTEGRITY_ALGORITHM_ID_ENUM integ_algo){ - - } -}; - - - - -int main(int argc, char **argv) +int security_command_test() { - srslte::log_stdout nas_log("NAS"); - srslte::log_stdout pdcp_entity_log("PDCP"); - srslte::log_stdout rrc_log("RRC"); - srslte::log_stdout mac_log("MAC"); - + int ret = SRSLTE_ERROR; + srslte::log_filter nas_log("NAS"); + srslte::log_filter rrc_log("RRC"); + srslte::log_filter mac_log("MAC"); + srslte::log_filter usim_log("USIM"); nas_log.set_level(srslte::LOG_LEVEL_DEBUG); - pdcp_entity_log.set_level(srslte::LOG_LEVEL_DEBUG); rrc_log.set_level(srslte::LOG_LEVEL_DEBUG); - nas_log.set_hex_limit(100000); rrc_log.set_hex_limit(100000); - usim_dummy usim; rrc_dummy rrc_dummy; gw_dummy gw; - pdcp_dummy pdcp_dummy; - + usim_args_t args; + args.algo = "xor"; + args.amf = "9001"; + args.imei = "353490069873319"; + args.imsi = "001010123456789"; + args.k = "00112233445566778899aabbccddeeff"; + args.op = "63BFA50EE6523365FF14C1F45F88737D"; + // init USIM + srsue::usim usim; + bool net_valid; + uint8_t res[16]; + usim.init(&args, &usim_log); - buffer_pool *pool; - pool = buffer_pool::get_instance(); + srslte::byte_buffer_pool *pool; + pool = byte_buffer_pool::get_instance(); srsue::nas nas; - nas.init(&usim, &rrc_dummy, &gw, &nas_log); + srslte_nas_config_t cfg; + nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg); + // push auth request PDU to NAS to generate security context + byte_buffer_t* tmp = pool->allocate(); + memcpy(tmp->msg, auth_request_pdu, sizeof(auth_request_pdu)); + tmp->N_bytes = sizeof(auth_request_pdu); + nas.write_pdu(LCID, tmp); + // TODO: add check for authentication response + // reuse buffer for security mode command + memcpy(tmp->msg, sec_mode_command_pdu, sizeof(sec_mode_command_pdu)); + tmp->N_bytes = sizeof(sec_mode_command_pdu); + nas.write_pdu(LCID, tmp); - byte_buffer_t* tmp = pool_allocate; - memcpy(tmp->msg, &pdu1[0], PDU1_LEN); - tmp->N_bytes = PDU1_LEN; + // check length of generated NAS SDU + if (rrc_dummy.get_last_sdu_len() > 3) { + ret = SRSLTE_SUCCESS; + } - //byte_buffer_t tmp2; - //memcpy(tmp2.msg, &pdu1[0], PDU1_LEN); - //tmp2.N_bytes = PDU1_LEN; + pool->cleanup(); - //srsue::mac mac; - //mac.init(NULL, NULL, NULL, &mac_log); + return ret; +} - srsue::rrc rrc; - rrc.init(NULL, NULL, NULL, NULL, &nas, NULL, NULL, &rrc_log); - //rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); +int mme_attach_request_test() +{ + int ret = SRSLTE_ERROR; + srslte::log_filter nas_log("NAS"); + srslte::log_filter rrc_log("RRC"); + srslte::log_filter mac_log("MAC"); + srslte::log_filter usim_log("USIM"); - srsue::pdcp_entity pdcp_entity; - pdcp_entity.init(NULL, &rrc, &gw, &pdcp_entity_log, RB_ID_SRB1, NULL); + nas_log.set_level(srslte::LOG_LEVEL_DEBUG); + rrc_log.set_level(srslte::LOG_LEVEL_DEBUG); + nas_log.set_hex_limit(100000); + rrc_log.set_hex_limit(100000); - pdcp_entity.write_pdu(tmp); + rrc_dummy rrc_dummy; + gw_dummy gw; + srsue::usim usim; + usim_args_t args; + args.algo = "xor"; + args.amf = "9001"; + args.imei = "353490069873319"; + args.imsi = "001010123456789"; + args.k = "00112233445566778899aabbccddeeff"; + args.op = "63BFA50EE6523365FF14C1F45F88737D"; + usim.init(&args, &usim_log); + + srslte_nas_config_t nas_cfg; + srsue::nas nas; + nas.init(&usim, &rrc_dummy, &gw, &nas_log, nas_cfg); + + nas.attach_request(); + nas.notify_connection_setup(); - //rrc.write_sdu(RB_ID_SRB2, tmp); + // check length of generated NAS SDU + if (rrc_dummy.get_last_sdu_len() > 3) { + ret = SRSLTE_SUCCESS; + } + return ret; +} - //nas.write_pdu(LCID, tmp); - pool->cleanup(); +int main(int argc, char **argv) +{ + if (security_command_test()) { + printf("Security command test failed.\n"); + return -1; + } + + if (mme_attach_request_test()) { + printf("Attach request test failed.\n"); + return -1; + } + return 0; }