diff --git a/CMakeLists.txt b/CMakeLists.txt index 42d8996a7..0c8f5a021 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,8 +333,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) endif(NOT WIN32) if (ENABLE_ASAN) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") endif (ENABLE_ASAN) endif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") @@ -346,6 +346,23 @@ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") message(STATUS "CMAKE_C_FLAGS is ${CMAKE_C_FLAGS}") message(STATUS "CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}") + +######################################################################## +# clang-tidy check +######################################################################## +find_program( + CLANG_TIDY_BIN + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" +) +if(NOT CLANG_TIDY_BIN) + message(STATUS "clang-tidy not found.") +else() + message(STATUS "clang-tidy found: ${CLANG_TIDY_BIN}") + set(DO_CLANG_TIDY "${CLANG_TIDY_BIN}" "-checks=*,-clang-analyzer-alpha.*") +endif() + + ######################################################################## # Create uninstall targets ######################################################################## diff --git a/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index 4c9673a9d..e5101deff 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.cmake @@ -14,7 +14,7 @@ if (ENABLE_SSE) # # Check compiler for SSE4_1 intrinsics # - if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-msse4.1") check_c_source_runs(" #include @@ -38,7 +38,7 @@ if (ENABLE_SSE) # # Check compiler for AVX intrinsics # - if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mavx") check_c_source_runs(" #include @@ -72,7 +72,7 @@ if (ENABLE_SSE) # # Check compiler for AVX intrinsics # - if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mavx2") check_c_source_runs(" #include @@ -106,7 +106,7 @@ if (ENABLE_SSE) # # Check compiler for AVX intrinsics # - if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mfma") check_c_source_runs(" #include @@ -141,7 +141,7 @@ if (ENABLE_SSE) # # Check compiler for AVX intrinsics # - if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mavx512f") check_c_source_runs(" #include diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index ed5c9acc1..549e992bf 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -122,7 +122,9 @@ public: byte_buffer_t():N_bytes(0) { bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); +#ifdef ENABLE_TIMESTAMP timestamp_is_set = false; +#endif msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; next = NULL; #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED @@ -149,7 +151,9 @@ public: { msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; N_bytes = 0; - timestamp_is_set = false; +#ifdef ENABLE_TIMESTAMP + timestamp_is_set = false; +#endif } uint32_t get_headroom() { @@ -183,8 +187,10 @@ public: private: +#ifdef ENABLE_TIMESTAMP struct timeval timestamp[3]; bool timestamp_is_set; +#endif byte_buffer_t *next; }; @@ -199,6 +205,9 @@ struct bit_buffer_t{ bit_buffer_t():N_bits(0) { msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; +#ifdef ENABLE_TIMESTAMP + timestamp_is_set = false; +#endif } bit_buffer_t(const bit_buffer_t& buf){ N_bits = buf.N_bits; @@ -216,7 +225,9 @@ struct bit_buffer_t{ { msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; N_bits = 0; - timestamp_is_set = false; +#ifdef ENABLE_TIMESTAMP + timestamp_is_set = false; +#endif } uint32_t get_headroom() { @@ -241,10 +252,11 @@ struct bit_buffer_t{ #endif } -private: +private: +#ifdef ENABLE_TIMESTAMP struct timeval timestamp[3]; bool timestamp_is_set; - +#endif }; } // namespace srslte diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 55ed29e07..2e02050c3 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -240,6 +240,7 @@ public: virtual void reset() = 0; virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking = true) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; + virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; virtual void config_security(uint32_t lcid, uint8_t *k_enc_, uint8_t *k_int_, @@ -273,10 +274,12 @@ class rlc_interface_rrc public: virtual void reset() = 0; virtual void reestablish() = 0; + virtual void reestablish(uint32_t lcid) = 0; virtual void add_bearer(uint32_t lcid) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0; virtual void add_bearer_mrb(uint32_t lcid) = 0; virtual void del_bearer(uint32_t lcid) = 0; + virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; }; // RLC interface for PDCP diff --git a/lib/include/srslte/phy/fec/turbodecoder_win.h b/lib/include/srslte/phy/fec/turbodecoder_win.h index 347e3ecc2..bd52e6284 100644 --- a/lib/include/srslte/phy/fec/turbodecoder_win.h +++ b/lib/include/srslte/phy/fec/turbodecoder_win.h @@ -65,8 +65,8 @@ #else #ifdef WINIMP_IS_AVX16 - #ifndef LV_HAVE_AVX - #error "Selected AVX window decoder but instruction set not supported" + #ifndef LV_HAVE_AVX2 + #error "Selected AVX2 window decoder but instruction set not supported" #endif #include @@ -139,8 +139,8 @@ #ifdef WINIMP_IS_AVX8 - #ifndef LV_HAVE_AVX - #error "Selected AVX window decoder but instruction set not supported" + #ifndef LV_HAVE_AVX2 + #error "Selected AVX2 window decoder but instruction set not supported" #endif #include diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index e4be9d548..7272f5079 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -61,6 +61,7 @@ public: void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void del_bearer(uint32_t lcid); + void change_lcid(uint32_t old_lcid, uint32_t new_lcid); void config_security(uint32_t lcid, uint8_t *k_enc, uint8_t *k_int, diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index a56f48eff..0bea0394e 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -81,12 +81,14 @@ public: // RRC interface void reestablish(); + void reestablish(uint32_t lcid); void reset(); void empty_queue(); void add_bearer(uint32_t lcid); void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg); void add_bearer_mrb(uint32_t lcid); void del_bearer(uint32_t lcid); + void change_lcid(uint32_t old_lcid, uint32_t new_lcid); private: void reset_metrics(); diff --git a/lib/src/phy/fec/turbodecoder.c b/lib/src/phy/fec/turbodecoder.c index 422175357..a97180745 100644 --- a/lib/src/phy/fec/turbodecoder.c +++ b/lib/src/phy/fec/turbodecoder.c @@ -71,7 +71,7 @@ srslte_tdec_16bit_impl_t sse16_win_impl = { #endif /* AVX window implementation */ -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 #define WINIMP_IS_AVX16 #include "srslte/phy/fec/turbodecoder_win.h" #undef WINIMP_IS_AVX16 @@ -100,7 +100,7 @@ srslte_tdec_8bit_impl_t sse8_win_impl = { #endif /* AVX window implementation */ -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 #define WINIMP_IS_AVX8 #include "srslte/phy/fec/turbodecoder_win.h" #undef WINIMP_IS_AVX8 @@ -178,7 +178,7 @@ int srslte_tdec_init_manual(srslte_tdec_t * h, uint32_t max_long_cb, srslte_tdec h->dec8[0] = &sse8_win_impl; h->current_llr_type = SRSLTE_TDEC_8; break; -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 case SRSLTE_TDEC_AVX_WINDOW: h->dec16[0] = &avx16_win_impl; h->current_llr_type = SRSLTE_TDEC_16; @@ -240,7 +240,7 @@ int srslte_tdec_init_manual(srslte_tdec_t * h, uint32_t max_long_cb, srslte_tdec h->dec16[AUTO_16_SSE] = &sse_impl; h->dec16[AUTO_16_SSEWIN] = &sse16_win_impl; h->dec8[AUTO_8_SSEWIN] = &sse8_win_impl; -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 h->dec16[AUTO_16_AVXWIN] = &avx16_win_impl; h->dec8[AUTO_8_AVXWIN] = &avx8_win_impl; #endif @@ -363,7 +363,7 @@ static void tdec_decision_byte(srslte_tdec_t * h, uint8_t *output) /* Returns number of subblocks in automatic mode for this long_cb */ uint32_t srslte_tdec_autoimp_get_subblocks(uint32_t long_cb) { -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 if (!(long_cb%16) && long_cb > 800) { return 16; } else @@ -391,7 +391,7 @@ static int tdec_sb_idx(uint32_t long_cb) { uint32_t srslte_tdec_autoimp_get_subblocks_8bit(uint32_t long_cb) { -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 if (!(long_cb%32) && long_cb > 2048) { return 32; } else diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index ec2855d0c..a203d459d 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -41,6 +41,10 @@ #include "srslte/phy/utils/vector.h" +#ifdef LV_HAVE_SSE +#include +#endif /* LV_HAVE_SSE */ + #define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12) @@ -699,13 +703,71 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t } int8_t *e_b = e; int16_t *e_s = e; - for (int i = 0; i < nbits->nof_bits / qm; i++) { - const float csi = q->csi[codeword_idx][i] / csi_max; - if (q->llr_is_8bit) { + float *csi_v = q->csi[codeword_idx]; + if (q->llr_is_8bit) { + for (int i = 0; i < nbits->nof_bits / qm; i++) { + const float csi = *(csi_v++) / csi_max; for (int k = 0; k < qm; k++) { - e_b[qm * i + k] = (int8_t) ((float) e_b[qm * i + k] * csi); + *e_b = (int8_t) ((float) *e_b * csi); + e_b++; } - } else { + } + } else { + int i = 0; + +#ifdef LV_HAVE_SSE + __m128 _csi_scale = _mm_set1_ps(INT16_MAX / csi_max); + __m64 *_e = (__m64 *) e; + + switch(cfg->grant.mcs[tb_idx].mod) { + case SRSLTE_MOD_QPSK: + for (; i < nbits->nof_bits - 3; i += 4) { + __m128 _csi1 = _mm_set1_ps(*(csi_v++)); + __m128 _csi2 = _mm_set1_ps(*(csi_v++)); + _csi1 = _mm_blend_ps(_csi1, _csi2, 3); + + _csi1 = _mm_mul_ps(_csi1, _csi_scale); + + _e[0] = _mm_mulhi_pi16(_e[0], _mm_cvtps_pi16(_csi1)); + _e += 1; + } + break; + case SRSLTE_MOD_16QAM: + for (; i < nbits->nof_bits - 3; i += 4) { + __m128 _csi = _mm_set1_ps(*(csi_v++)); + + _csi = _mm_mul_ps(_csi, _csi_scale); + + _e[0] = _mm_mulhi_pi16(_e[0], _mm_cvtps_pi16(_csi)); + _e += 1; + } + break; + case SRSLTE_MOD_64QAM: + for (; i < nbits->nof_bits - 11; i += 12) { + __m128 _csi1 = _mm_set1_ps(*(csi_v++)); + __m128 _csi3 = _mm_set1_ps(*(csi_v++)); + + _csi1 = _mm_mul_ps(_csi1, _csi_scale); + _csi3 = _mm_mul_ps(_csi3, _csi_scale); + __m128 _csi2 = _mm_blend_ps(_csi1, _csi3, 3); + + _e[0] = _mm_mulhi_pi16(_e[0], _mm_cvtps_pi16(_csi1)); + _e[1] = _mm_mulhi_pi16(_e[1], _mm_cvtps_pi16(_csi2)); + _e[2] = _mm_mulhi_pi16(_e[2], _mm_cvtps_pi16(_csi3)); + _e += 3; + } + break; + case SRSLTE_MOD_BPSK: + case SRSLTE_MOD_LAST: + /* Do nothing */ + break; + } + + i /= qm; +#endif /* LV_HAVE_SSE */ + + for (; i < nbits->nof_bits / qm; i++) { + const float csi = q->csi[codeword_idx][i] / csi_max; for (int k = 0; k < qm; k++) { e_s[qm * i + k] = (int16_t) ((float) e_s[qm * i + k] * csi); } diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index c8391518b..93ac0cf15 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -187,6 +187,28 @@ void pdcp::del_bearer(uint32_t lcid) pthread_rwlock_unlock(&rwlock); } +void pdcp::change_lcid(uint32_t old_lcid, uint32_t new_lcid) +{ + pthread_rwlock_wrlock(&rwlock); + + // make sure old LCID exists and new LCID is still free + if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { + // insert old PDCP entity into new LCID + pdcp_map_t::iterator it = pdcp_array.find(old_lcid); + pdcp_entity_interface *pdcp_entity = it->second; + if (not pdcp_array.insert(pdcp_map_pair_t(new_lcid, pdcp_entity)).second) { + pdcp_log->error("Error inserting PDCP entity into array\n."); + goto exit; + } + // erase from old position + pdcp_array.erase(it); + pdcp_log->warning("Changed LCID of PDCP bearer from %d to %d\n", old_lcid, new_lcid); + } else { + pdcp_log->error("Can't change PDCP of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied.\n", rrc->get_rb_name(old_lcid).c_str(), old_lcid, new_lcid); + } +exit: + pthread_rwlock_unlock(&rwlock); +} void pdcp::config_security(uint32_t lcid, uint8_t *k_enc, diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 65bb07fae..9d0300820 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -218,7 +218,7 @@ void pdcp_entity::write_pdu(byte_buffer_t *pdu) rx_count, pdu->N_bytes - 4, &(pdu->msg[pdu->N_bytes - 4]))) { - log->error_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); + log->error_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d (Dropping PDU)", rrc->get_rb_name(lcid).c_str(), sn); goto exit; } } diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 67002fd37..413da1364 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -144,7 +144,7 @@ void rlc::get_metrics(rlc_metrics_t &m) pthread_rwlock_unlock(&rwlock); } -// A call to reestablish stops all lcids but does not delete the instances. The mapping lcid to rlc mode can not change +// Reestablish all RLC bearer void rlc::reestablish() { pthread_rwlock_rdlock(&rwlock); @@ -160,6 +160,18 @@ void rlc::reestablish() pthread_rwlock_unlock(&rwlock); } +// Reestablish a specific RLC bearer +void rlc::reestablish(uint32_t lcid) +{ + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + rlc_array.at(lcid)->reestablish(); + } else { + rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid); + } + pthread_rwlock_unlock(&rwlock); +} + // Resetting the RLC layer returns the object to the state after the call to init(): // All LCIDs are removed, except SRB0 void rlc::reset() @@ -505,13 +517,37 @@ void rlc::del_bearer(uint32_t lcid) rlc_array.erase(it); rlc_log->warning("Deleted RLC bearer %s\n", rrc->get_rb_name(lcid).c_str()); } else { - rlc_log->warning("Can't delete bearer %s. Bearer doesn't exist.\n", rrc->get_rb_name(lcid).c_str()); + rlc_log->error("Can't delete bearer %s. Bearer doesn't exist.\n", rrc->get_rb_name(lcid).c_str()); } pthread_rwlock_unlock(&rwlock); } +void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid) +{ + pthread_rwlock_wrlock(&rwlock); + + // make sure old LCID exists and new LCID is still free + if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { + // insert old rlc entity into new LCID + rlc_map_t::iterator it = rlc_array.find(old_lcid); + rlc_common *rlc_entity = it->second; + if (not rlc_array.insert(rlc_map_pair_t(new_lcid, rlc_entity)).second) { + rlc_log->error("Error inserting RLC entity into array\n."); + goto exit; + } + // erase from old position + rlc_array.erase(it); + rlc_log->warning("Changed LCID of RLC bearer from %d to %d\n", old_lcid, new_lcid); + } else { + rlc_log->error("Can't change LCID of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied.\n", rrc->get_rb_name(old_lcid).c_str(), old_lcid, new_lcid); + } +exit: + pthread_rwlock_unlock(&rwlock); +} + + /******************************************************************************* Helpers (Lock must be hold when calling those) *******************************************************************************/