From 5d149a4b78b7ecefaba951eeb7c2b67a93071bd6 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 16 Aug 2021 09:08:30 +0200 Subject: [PATCH 01/56] Moved NR time/frequency allocation SLIV to new component --- lib/include/srsran/phy/common/sliv.h | 23 +++++++++ lib/src/phy/common/CMakeLists.txt | 2 +- lib/src/phy/common/sliv.c | 34 ++++++++++++ lib/src/phy/common/test/CMakeLists.txt | 11 ++++ lib/src/phy/common/test/sliv_test.c | 71 ++++++++++++++++++++++++++ lib/src/phy/phch/ra_dl_nr.c | 4 +- lib/src/phy/phch/ra_helper.h | 24 +-------- lib/src/phy/phch/ra_ul_nr.c | 2 +- 8 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 lib/include/srsran/phy/common/sliv.h create mode 100644 lib/src/phy/common/sliv.c create mode 100644 lib/src/phy/common/test/sliv_test.c diff --git a/lib/include/srsran/phy/common/sliv.h b/lib/include/srsran/phy/common/sliv.h new file mode 100644 index 000000000..b4f8cb98d --- /dev/null +++ b/lib/include/srsran/phy/common/sliv.h @@ -0,0 +1,23 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SLIV_H +#define SRSRAN_SLIV_H + +#include "srsran/config.h" +#include + +SRSRAN_API void srsran_sliv_to_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L); + +SRSRAN_API uint32_t srsran_sliv_from_s_and_l(uint32_t N, uint32_t S, uint32_t L); + +#endif // SRSRAN_SLIV_H diff --git a/lib/src/phy/common/CMakeLists.txt b/lib/src/phy/common/CMakeLists.txt index 9493d6836..c3a000d62 100644 --- a/lib/src/phy/common/CMakeLists.txt +++ b/lib/src/phy/common/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -set(SOURCES phy_common.c phy_common_sl.c phy_common_nr.c sequence.c timestamp.c zc_sequence.c) +set(SOURCES phy_common.c phy_common_sl.c phy_common_nr.c sequence.c timestamp.c zc_sequence.c sliv.c) add_library(srsran_phy_common OBJECT ${SOURCES}) add_subdirectory(test) \ No newline at end of file diff --git a/lib/src/phy/common/sliv.c b/lib/src/phy/common/sliv.c new file mode 100644 index 000000000..01635b67d --- /dev/null +++ b/lib/src/phy/common/sliv.c @@ -0,0 +1,34 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/phy/common/sliv.h" + +void srsran_sliv_to_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L) +{ + uint32_t low = v % N; + uint32_t high = v / N; + if (high + 1 + low <= N) { + *S = low; + *L = high + 1; + } else { + *S = N - 1 - low; + *L = N - high + 1; + } +} + +uint32_t srsran_sliv_from_s_and_l(uint32_t N, uint32_t S, uint32_t L) +{ + if ((L - 1) <= N / 2) { + return N * (L - 1) + S; + } + return N * (N - L + 1) + (N - 1 - S); +} \ No newline at end of file diff --git a/lib/src/phy/common/test/CMakeLists.txt b/lib/src/phy/common/test/CMakeLists.txt index c933a3c23..ae08699a5 100644 --- a/lib/src/phy/common/test/CMakeLists.txt +++ b/lib/src/phy/common/test/CMakeLists.txt @@ -14,3 +14,14 @@ add_executable(sequence_test sequence_test.c) target_link_libraries(sequence_test srsran_phy) add_test(sequence_test sequence_test) + +######################################################################## +# SLIV TEST +######################################################################## + +add_executable(sliv_test sliv_test.c) +target_link_libraries(sliv_test srsran_phy) + +add_test(sliv_test_14 sliv_test 14) +add_test(sliv_test_52 sliv_test 48) +add_test(sliv_test_52 sliv_test 52) diff --git a/lib/src/phy/common/test/sliv_test.c b/lib/src/phy/common/test/sliv_test.c new file mode 100644 index 000000000..6a42dadac --- /dev/null +++ b/lib/src/phy/common/test/sliv_test.c @@ -0,0 +1,71 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#include "srsran/common/test_common.h" +#include "srsran/phy/common/sliv.h" +#include +#include +#include + +static uint32_t N = 48; + +static int test() +{ + for (uint32_t s = 0; s < N; s++) { + for (uint32_t l = 1; l < N - s; l++) { + uint32_t sliv = srsran_sliv_from_s_and_l(N, s, l); + + uint32_t S = 0; + uint32_t L = 0; + srsran_sliv_to_s_and_l(N, sliv, &S, &L); + + if (s != S || l != L) { + printf("s=%d; l=%d; SLIV=%d; Start: %d; Length: %d;\n", s, l, sliv, S, L); + return SRSRAN_ERROR; + } + } + } + return SRSRAN_SUCCESS; +} + +int main(int argc, char** argv) +{ + // Parse N + if (argc >= 2) { + N = (uint32_t)strtol(argv[1], NULL, 10); + } + + // If two arguments, run brute force test + if (argc == 2) { + return test(); + } + + // if three arguments, calculate start and length from sliv + if (argc == 3) { + uint32_t sliv = (uint32_t)strtol(argv[2], NULL, 10); + uint32_t S = 0; + uint32_t L = 0; + srsran_sliv_to_s_and_l(N, sliv, &S, &L); + + printf("SLIV=%d; Start: %d; Length: %d;\n", sliv, S, L); + return SRSRAN_SUCCESS; + } + + // if four arguments, calculate sliv from start and length + if (argc == 4) { + uint32_t s = (uint32_t)strtol(argv[2], NULL, 10); + uint32_t l = (uint32_t)strtol(argv[3], NULL, 10); + uint32_t sliv = srsran_sliv_from_s_and_l(N, s, l); + + printf("SLIV=%d; Start: %d; Length: %d;\n", sliv, s, l); + return SRSRAN_SUCCESS; + } +} \ No newline at end of file diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index caa8adb83..e8712324b 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -115,7 +115,7 @@ int srsran_ra_dl_nr_time_default_A(uint32_t m, srsran_dmrs_sch_typeA_pos_t dmrs_ static void ra_dl_nr_time_hl(const srsran_sch_time_ra_t* hl_ra_cfg, srsran_sch_grant_nr_t* grant) { // Compute S and L from SLIV from higher layers - ra_helper_compute_s_and_l(SRSRAN_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L); + srsran_sliv_to_s_and_l(SRSRAN_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L); grant->k = hl_ra_cfg->k; grant->mapping = hl_ra_cfg->mapping_type; @@ -322,5 +322,5 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier, uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t length_rb) { - return ra_helper_from_s_and_l(N_prb, start_rb, length_rb); + return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb); } \ No newline at end of file diff --git a/lib/src/phy/phch/ra_helper.h b/lib/src/phy/phch/ra_helper.h index 004bf6075..2c25563a5 100644 --- a/lib/src/phy/phch/ra_helper.h +++ b/lib/src/phy/phch/ra_helper.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_RA_HELPER_H #define SRSRAN_RA_HELPER_H +#include "srsran/phy/common/sliv.h" #include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/vector.h" #include @@ -60,32 +61,11 @@ static int ra_helper_freq_type0(const srsran_carrier_nr_t* carrier, return 0; } -static inline void ra_helper_compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L) -{ - uint32_t low = v % N; - uint32_t high = v / N; - if (high + 1 + low <= N) { - *S = low; - *L = high + 1; - } else { - *S = N - 1 - low; - *L = N - high + 1; - } -} - -static inline uint32_t ra_helper_from_s_and_l(uint32_t N, uint32_t S, uint32_t L) -{ - if ((L - 1) <= N / 2) { - return N * (L - 1) + S; - } - return N * (N - L + 1) + (N - 1 - S); -} - static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srsran_sch_grant_nr_t* grant) { uint32_t start = 0; uint32_t len = 0; - ra_helper_compute_s_and_l(N_bwp_size, riv, &start, &len); + srsran_sliv_to_s_and_l(N_bwp_size, riv, &start, &len); if (start + len > N_bwp_size) { ERROR("RIV 0x%x for BWP size %d resulted in freq=%d:%d", riv, N_bwp_size, start, len); diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index d8159b87d..b2e15ffd2 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -73,7 +73,7 @@ int srsran_ra_ul_nr_pusch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, static void ra_ul_nr_time_hl(const srsran_sch_time_ra_t* hl_ra_cfg, srsran_sch_grant_nr_t* grant) { // Compute S and L from SLIV from higher layers - ra_helper_compute_s_and_l(SRSRAN_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L); + srsran_sliv_to_s_and_l(SRSRAN_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L); grant->k = hl_ra_cfg->k; grant->mapping = hl_ra_cfg->mapping_type; From 62ba7d386db45f97b47c24b41b75b821e797ef5d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 16 Aug 2021 10:49:05 +0200 Subject: [PATCH 02/56] Initial CORESET Zero constructor --- lib/include/srsran/phy/common/phy_common_nr.h | 24 +++- lib/src/phy/common/phy_common_nr.c | 124 ++++++++++++++++++ 2 files changed, 146 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 9334b6ad1..af4a083c5 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -410,7 +410,11 @@ typedef struct SRSRAN_API { uint32_t duration; bool freq_resources[SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE]; srsran_coreset_bundle_size_t interleaver_size; - + uint32_t offset_rb; ///< Defined by TS 36.213 section 13 UE procedure for monitoring Type0-PDCCH CSS sets: + ///< Offset respect to the SCS of the CORESET for Type0-PDCCH CSS set, provided by + ///< subCarrierSpacingCommon, from the smallest RB index of the CORESET for Type0-PDCCH CSS set + ///< to the smallest RB index of the common RB overlapping with the first RB of the + ///< corresponding SS/PBCH block. bool dmrs_scrambling_id_present; uint32_t dmrs_scrambling_id; srsran_coreset_precoder_granularity_t precoder_granularity; @@ -607,7 +611,23 @@ SRSRAN_API srsran_subcarrier_spacing_t srsran_subcarrier_spacing_from_str(const * @param[in] b CSI-RS measurement * @param[out] dst Destination of the combined */ -SRSRAN_API void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measurements_t *a, const srsran_csi_trs_measurements_t *b, srsran_csi_trs_measurements_t *dst); +SRSRAN_API void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measurements_t* a, + const srsran_csi_trs_measurements_t* b, + srsran_csi_trs_measurements_t* dst); + +/** + * @brief Setup CORESET Zero from a configuration index + * @remark Defined by TS 38.213 tables 13-1, 13-2, 13-3, 13-4, 13-5, 13-6, 13-7, 13-8, 13-9, 13-10 + * @param ssb_scs SS/PBCH block subcarrier spacing + * @param pdcch_scs PDCCH subcarrier spacing + * @param idx CORESET Zero configuration index + * @param[out] coreset Points to the resultant CORESET + * @return SRSLTE_SUCCESS if the given inputs lead to a valid CORESET configuration, otherise SRSLTE_ERROR code + */ +SRSRAN_API int srsran_coreset_zero(srsran_subcarrier_spacing_t ssb_scs, + srsran_subcarrier_spacing_t pdcch_scs, + uint32_t idx, + srsran_coreset_t* coreset); #ifdef __cplusplus } diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 8f1223beb..23c4fe1e6 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -11,6 +11,7 @@ */ #include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/vector.h" #include #include @@ -389,3 +390,126 @@ void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measurements_t* a, dst->delay_us = SRSRAN_VEC_PMA(a->delay_us, a->nof_re, b->delay_us, b->nof_re); dst->nof_re = nof_re_sum; } + +typedef struct { + uint32_t mux_pattern; + uint32_t nof_prb; + uint32_t nof_symb; + uint32_t offset_rb; +} coreset_zero_entry_t; + +static const coreset_zero_entry_t coreset_zero_15_15[16] = { + {1, 24, 2, 0}, + {1, 24, 2, 2}, + {1, 24, 2, 4}, + {1, 24, 3, 0}, + {1, 24, 3, 2}, + {1, 24, 3, 4}, + {1, 48, 1, 12}, + {1, 48, 1, 16}, + {1, 48, 2, 12}, + {1, 48, 2, 16}, + {1, 48, 3, 12}, + {1, 48, 3, 16}, + {1, 96, 1, 38}, + {1, 96, 2, 38}, + {1, 96, 3, 38}, + {}, +}; + +static const coreset_zero_entry_t coreset_zero_15_30[16] = { + {1, 24, 2, 5}, + {1, 24, 2, 6}, + {1, 24, 2, 7}, + {1, 24, 2, 8}, + {1, 24, 3, 5}, + {1, 24, 3, 6}, + {1, 24, 3, 7}, + {1, 24, 3, 8}, + {1, 48, 1, 18}, + {1, 48, 1, 20}, + {1, 48, 2, 18}, + {1, 48, 2, 20}, + {1, 48, 3, 18}, + {1, 48, 3, 20}, + {}, + {}, +}; + +static const coreset_zero_entry_t coreset_zero_30_15[16] = { + {1, 48, 1, 2}, + {1, 48, 1, 6}, + {1, 48, 2, 2}, + {1, 48, 2, 6}, + {1, 48, 3, 2}, + {1, 48, 3, 6}, + {1, 96, 1, 28}, + {1, 96, 2, 28}, + {1, 96, 3, 28}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, +}; + +int srsran_coreset_zero(srsran_subcarrier_spacing_t ssb_scs, + srsran_subcarrier_spacing_t pdcch_scs, + uint32_t idx, + srsran_coreset_t* coreset) +{ + // Verify inputs + if (coreset == NULL || idx >= 16) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Default entry to NULL + const coreset_zero_entry_t* entry = NULL; + + // Table 13-1: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {15, 15} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_15kHz && pdcch_scs == srsran_subcarrier_spacing_15kHz) { + entry = &coreset_zero_15_15[idx]; + } + // Table 13-2: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {15, 30} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_15kHz && pdcch_scs == srsran_subcarrier_spacing_30kHz) { + entry = &coreset_zero_15_30[idx]; + } + + // Table 13-3: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {30, 15} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_30kHz && pdcch_scs == srsran_subcarrier_spacing_15kHz) { + entry = &coreset_zero_30_15[idx]; + } + + // Check a valid entry has been selected + if (entry == NULL) { + ERROR("Unhandled case ssb_scs=%d, pdcch_scs=%d", (int)ssb_scs, (int)pdcch_scs); + return SRSRAN_ERROR; + } + + if (entry->nof_prb == 0) { + ERROR("Reserved case ssb_scs=%d, pdcch_scs=%d, idx=%d", (int)ssb_scs, (int)pdcch_scs, idx); + return SRSRAN_ERROR; + } + + // Set CORESET fields + coreset->id = 0; + coreset->dmrs_scrambling_id_present = false; + coreset->mapping_type = srsran_coreset_mapping_type_non_interleaved; + coreset->duration = entry->nof_symb; + coreset->offset_rb = entry->offset_rb; + + // Set CORESET frequency resource mask + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { + coreset->freq_resources[i] = (i < (entry->nof_prb / 6)); + } + + return SRSRAN_SUCCESS; +} From 737749641744a9238d9b1f2f860f9853e0ffc721 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 17 Aug 2021 13:34:38 +0200 Subject: [PATCH 03/56] Added SCS to string and corrected coreset0 --- lib/include/srsran/phy/common/phy_common_nr.h | 18 ++++--- lib/src/phy/common/phy_common_nr.c | 53 +++++++++++++++++-- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index af4a083c5..40719b89c 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -410,11 +410,8 @@ typedef struct SRSRAN_API { uint32_t duration; bool freq_resources[SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE]; srsran_coreset_bundle_size_t interleaver_size; - uint32_t offset_rb; ///< Defined by TS 36.213 section 13 UE procedure for monitoring Type0-PDCCH CSS sets: - ///< Offset respect to the SCS of the CORESET for Type0-PDCCH CSS set, provided by - ///< subCarrierSpacingCommon, from the smallest RB index of the CORESET for Type0-PDCCH CSS set - ///< to the smallest RB index of the common RB overlapping with the first RB of the - ///< corresponding SS/PBCH block. + uint32_t offset_rb; ///< Integer offset in resource blocks from the pointA (lowest subcarrier of resource grid) to the + ///< lowest resource block of the CORESET region (used by CORESET Zero only) bool dmrs_scrambling_id_present; uint32_t dmrs_scrambling_id; srsran_coreset_precoder_granularity_t precoder_granularity; @@ -605,6 +602,13 @@ SRSRAN_API uint32_t srsran_csi_meas_info(const srsran_csi_trs_measurements_t* me */ SRSRAN_API srsran_subcarrier_spacing_t srsran_subcarrier_spacing_from_str(const char* str); +/** + * @brief Converts a given subcarrier spacing to string + * @param scs Subcarrier spacing + * @return A constant string pointer + */ +SRSRAN_API const char* srsran_subcarrier_spacing_to_str(srsran_subcarrier_spacing_t scs); + /** * @brief Combine Channel State Information from Tracking Reference Signals (CSI-TRS) * @param[in] a CSI-RS measurement @@ -618,13 +622,15 @@ SRSRAN_API void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measure /** * @brief Setup CORESET Zero from a configuration index * @remark Defined by TS 38.213 tables 13-1, 13-2, 13-3, 13-4, 13-5, 13-6, 13-7, 13-8, 13-9, 13-10 + * @param ssb_pointA_freq_offset_Hz Integer frequency offset in Hz between the SS/PBCH block center and pointA * @param ssb_scs SS/PBCH block subcarrier spacing * @param pdcch_scs PDCCH subcarrier spacing * @param idx CORESET Zero configuration index * @param[out] coreset Points to the resultant CORESET * @return SRSLTE_SUCCESS if the given inputs lead to a valid CORESET configuration, otherise SRSLTE_ERROR code */ -SRSRAN_API int srsran_coreset_zero(srsran_subcarrier_spacing_t ssb_scs, +SRSRAN_API int srsran_coreset_zero(uint32_t ssb_pointA_freq_offset_Hz, + srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs, uint32_t idx, srsran_coreset_t* coreset); diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 23c4fe1e6..7b2a00975 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -361,6 +361,25 @@ srsran_subcarrier_spacing_t srsran_subcarrier_spacing_from_str(const char* str) return srsran_subcarrier_spacing_invalid; } +const char* srsran_subcarrier_spacing_to_str(srsran_subcarrier_spacing_t scs) +{ + switch (scs) { + case srsran_subcarrier_spacing_15kHz: + return "15kHz"; + case srsran_subcarrier_spacing_30kHz: + return "30kHz"; + case srsran_subcarrier_spacing_60kHz: + return "60kHz"; + case srsran_subcarrier_spacing_120kHz: + return "120kHz"; + case srsran_subcarrier_spacing_240kHz: + return "240kHz"; + case srsran_subcarrier_spacing_invalid: + default: + return "invalid"; + } +} + void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measurements_t* a, const srsran_csi_trs_measurements_t* b, srsran_csi_trs_measurements_t* dst) @@ -395,7 +414,11 @@ typedef struct { uint32_t mux_pattern; uint32_t nof_prb; uint32_t nof_symb; - uint32_t offset_rb; + uint32_t offset_rb; ///< Defined by TS 36.213 section 13 UE procedure for monitoring Type0-PDCCH CSS sets: + ///< Offset respect to the SCS of the CORESET for Type0-PDCCH CSS set, provided by + ///< subCarrierSpacingCommon, from the smallest RB index of the CORESET for Type0-PDCCH CSS set + ///< to the smallest RB index of the common RB overlapping with the first RB of the + ///< corresponding SS/PBCH block. } coreset_zero_entry_t; static const coreset_zero_entry_t coreset_zero_15_15[16] = { @@ -455,13 +478,15 @@ static const coreset_zero_entry_t coreset_zero_30_15[16] = { {}, }; -int srsran_coreset_zero(srsran_subcarrier_spacing_t ssb_scs, +int srsran_coreset_zero(uint32_t ssb_pointA_freq_offset_Hz, + srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs, uint32_t idx, srsran_coreset_t* coreset) { // Verify inputs if (coreset == NULL || idx >= 16) { + ERROR("Invalid CORESET Zero inputs. coreset=%p, idx=%d", coreset, idx); return SRSRAN_ERROR_INVALID_INPUTS; } @@ -490,21 +515,39 @@ int srsran_coreset_zero(srsran_subcarrier_spacing_t ssb_scs, // Check a valid entry has been selected if (entry == NULL) { - ERROR("Unhandled case ssb_scs=%d, pdcch_scs=%d", (int)ssb_scs, (int)pdcch_scs); + ERROR("Unhandled case ssb_scs=%s, pdcch_scs=%s", + srsran_subcarrier_spacing_to_str(ssb_scs), + srsran_subcarrier_spacing_to_str(pdcch_scs)); return SRSRAN_ERROR; } if (entry->nof_prb == 0) { - ERROR("Reserved case ssb_scs=%d, pdcch_scs=%d, idx=%d", (int)ssb_scs, (int)pdcch_scs, idx); + ERROR("Reserved case ssb_scs=%s, pdcch_scs=%s, idx=%d", + srsran_subcarrier_spacing_to_str(ssb_scs), + srsran_subcarrier_spacing_to_str(pdcch_scs), + idx); return SRSRAN_ERROR; } + // Calculate CORESET offset in RB + uint32_t ssb_half_bw_Hz = SRSRAN_SUBC_SPACING_NR(ssb_scs) * (SRSRAN_SSB_BW_SUBC / 2U); + if (ssb_pointA_freq_offset_Hz > ssb_half_bw_Hz) { + // Move SSB center to lowest SSB subcarrier + ssb_pointA_freq_offset_Hz -= ssb_half_bw_Hz; + } else { + ssb_pointA_freq_offset_Hz = 0; + } + uint32_t ssb_pointA_freq_offset_rb = + SRSRAN_FLOOR(ssb_pointA_freq_offset_Hz, SRSRAN_NRE * SRSRAN_SUBC_SPACING_NR(pdcch_scs)); + uint32_t offset_rb = + (ssb_pointA_freq_offset_rb > entry->offset_rb) ? (ssb_pointA_freq_offset_rb - entry->offset_rb) : 0; + // Set CORESET fields coreset->id = 0; coreset->dmrs_scrambling_id_present = false; coreset->mapping_type = srsran_coreset_mapping_type_non_interleaved; coreset->duration = entry->nof_symb; - coreset->offset_rb = entry->offset_rb; + coreset->offset_rb = offset_rb; // Set CORESET frequency resource mask for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { From e07263ee2607d247b85b7b58b35a822162421f68 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 17 Aug 2021 13:35:16 +0200 Subject: [PATCH 04/56] Added band helper for getting band from ARFCN --- lib/include/srsran/common/band_helper.h | 7 +++++++ lib/src/common/band_helper.cc | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/include/srsran/common/band_helper.h b/lib/include/srsran/common/band_helper.h index a362a6b29..0ffde42c9 100644 --- a/lib/include/srsran/common/band_helper.h +++ b/lib/include/srsran/common/band_helper.h @@ -52,6 +52,13 @@ public: */ uint16_t get_band_from_dl_freq_Hz(double dl_freq_Hz) const; + /** + * @brief Get the lowest band that includes a given Downlink ARFCN + * @param arfcn Given ARFCN + * @return The band number if the ARFCN is bounded in a band, UINT16_MAX otherwise + */ + uint16_t get_band_from_dl_arfcn(uint32_t arfcn) const; + /** * @brief Selects the SSB pattern case according to the band number and subcarrier spacing * @remark Described by TS 38.101-1 Table 5.4.3.3-1: Applicable SS raster entries per operating band diff --git a/lib/src/common/band_helper.cc b/lib/src/common/band_helper.cc index 76e2821e1..5b760a480 100644 --- a/lib/src/common/band_helper.cc +++ b/lib/src/common/band_helper.cc @@ -67,6 +67,18 @@ uint16_t srsran_band_helper::get_band_from_dl_freq_Hz(double freq) const return UINT16_MAX; } +uint16_t srsran_band_helper::get_band_from_dl_arfcn(uint32_t arfcn) const +{ + for (const nr_band& band : nr_band_table_fr1) { + // Check given ARFCN is between the first and last possible ARFCN and matches step + if (arfcn >= band.dl_nref_first and arfcn <= band.dl_nref_last and + (arfcn - band.dl_nref_first) % band.dl_nref_step == 0) { + return band.band; + } + } + return UINT16_MAX; +} + srsran_ssb_patern_t srsran_band_helper::get_ssb_pattern(uint16_t band, srsran_subcarrier_spacing_t scs) const { // Look for the given band and SCS From d61d6aa59fd8088c7b7b5088521ce14e500b31de Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 17 Aug 2021 13:36:23 +0200 Subject: [PATCH 05/56] Integrated CORESET0 into UE's RRC --- lib/src/phy/ch_estimation/dmrs_pdcch.c | 5 +++- lib/src/phy/phch/pdcch_nr.c | 7 +++-- srsue/src/stack/rrc/rrc_nr.cc | 40 ++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lib/src/phy/ch_estimation/dmrs_pdcch.c b/lib/src/phy/ch_estimation/dmrs_pdcch.c index 914992fdc..9cc1a00bf 100644 --- a/lib/src/phy/ch_estimation/dmrs_pdcch.c +++ b/lib/src/phy/ch_estimation/dmrs_pdcch.c @@ -290,6 +290,9 @@ void srsran_dmrs_pdcch_estimator_free(srsran_dmrs_pdcch_estimator_t* q) static void srsran_dmrs_pdcch_extract(srsran_dmrs_pdcch_estimator_t* q, uint32_t cinit, const cf_t* sf_symbol, cf_t* lse) { + // Get CORESET offset + uint32_t offset_k = q->coreset.offset_rb * SRSRAN_NRE; + // Initialise pseudo-random sequence srsran_sequence_state_t sequence_state = {}; srsran_sequence_state_init(&sequence_state, cinit); @@ -328,7 +331,7 @@ srsran_dmrs_pdcch_extract(srsran_dmrs_pdcch_estimator_t* q, uint32_t cinit, cons uint32_t k = n * SRSRAN_NRE + 4 * k_prime + 1; // Extract symbol - lse[idx] = sf_symbol[k]; + lse[idx] = sf_symbol[k + offset_k]; } } diff --git a/lib/src/phy/phch/pdcch_nr.c b/lib/src/phy/phch/pdcch_nr.c index 055f8bb3a..b5be24d35 100644 --- a/lib/src/phy/phch/pdcch_nr.c +++ b/lib/src/phy/phch/pdcch_nr.c @@ -310,7 +310,8 @@ static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q, cf_t* symbols, bool put) { - uint32_t L = 1U << dci_location->L; + uint32_t offset_k = q->coreset.offset_rb * SRSRAN_NRE; + uint32_t L = 1U << dci_location->L; // Calculate begin and end sub-carrier index for the selected candidate uint32_t k_begin = (dci_location->ncce * SRSRAN_NRE * 6) / q->coreset.duration; @@ -327,9 +328,9 @@ static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q, for (uint32_t i = r * 6 * SRSRAN_NRE; i < (r + 1) * 6 * SRSRAN_NRE; i++, k++) { if (k >= k_begin && k < k_end && k % 4 != 1) { if (put) { - slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i] = symbols[count++]; + slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i + offset_k] = symbols[count++]; } else { - symbols[count++] = slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i]; + symbols[count++] = slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i + offset_k]; } } } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index a5caada5c..f151d859c 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -16,6 +16,7 @@ #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rlc_interfaces.h" #include "srsue/hdr/stack/upper/usim.h" +#include "srsran/common/band_helper.h" #define Error(fmt, ...) rrc_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define Warning(fmt, ...) rrc_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -784,6 +785,45 @@ bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_com if (dl_cfg_common.init_dl_bwp.pdsch_cfg_common.type() == asn1::rrc_nr::setup_release_c::types_opts::setup) { const pdcch_cfg_common_s& pdcch_cfg_common = dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); + + // Load CORESET Zero + if (pdcch_cfg_common.ctrl_res_set_zero_present) { + srsran::srsran_band_helper band_helper; + + // Get band number + uint16_t band = band_helper.get_band_from_dl_arfcn(phy_cfg.carrier.absolute_frequency_point_a); + + // Get pointA and SSB absolute frequencies + double pointA_abs_freq_Hz = band_helper.nr_arfcn_to_freq(phy_cfg.carrier.absolute_frequency_point_a); + double ssb_abs_freq_Hz = band_helper.nr_arfcn_to_freq(phy_cfg.carrier.absolute_frequency_ssb); + + // Calculate integer SSB to pointA frequency offset in Hz + uint32_t ssb_pointA_freq_offset_Hz = + (ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0; + + // TODO: Select subcarrier spacing from SSB (depending on band) + srsran_subcarrier_spacing_t ssb_scs = srsran_subcarrier_spacing_30kHz ; + + // Select PDCCH subcarrrier spacing from PDCCH BWP + srsran_subcarrier_spacing_t pdcch_scs = phy_cfg.carrier.scs; + + // Make CORESET Zero from provided field and given subcarrier spacing + srsran_coreset_t coreset0 = {}; + if (srsran_coreset_zero( + ssb_pointA_freq_offset_Hz, ssb_scs, pdcch_scs, pdcch_cfg_common.ctrl_res_set_zero, &coreset0) < + SRSASN_SUCCESS) { + logger.warning("Not possible to create CORESET Zero (ssb_scs=%s, pdcch_scs=%s, idx=%d)", + srsran_subcarrier_spacing_to_str(ssb_scs), + srsran_subcarrier_spacing_to_str(pdcch_scs), + pdcch_cfg_common.ctrl_res_set_zero); + return false; + } + + // Write CORESET Zero in index 0 + phy_cfg.pdcch.coreset[0] = coreset0; + phy_cfg.pdcch.coreset_present[0] = true; + } + if (pdcch_cfg_common.common_ctrl_res_set_present) { srsran_coreset_t coreset; if (make_phy_coreset_cfg(pdcch_cfg_common.common_ctrl_res_set, &coreset) == true) { From f5f18054eb902a4294243b8df96be652c3000fb9 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 17 Aug 2021 16:52:35 +0200 Subject: [PATCH 06/56] Added PDCCH NR interleaved mapping --- lib/include/srsran/phy/common/phy_common_nr.h | 23 +-- lib/include/srsran/phy/phch/pdcch_nr.h | 11 ++ lib/src/phy/common/phy_common_nr.c | 11 +- lib/src/phy/phch/pdcch_nr.c | 143 ++++++++++++++++-- lib/src/phy/phch/test/CMakeLists.txt | 3 +- lib/src/phy/phch/test/pdcch_nr_test.c | 35 ++++- 6 files changed, 194 insertions(+), 32 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 40719b89c..9941df529 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -405,18 +405,19 @@ typedef struct SRSRAN_API { * @brief CORESET parameters as defined in TS 38.331 V15.10.0 - ControlResourceSet */ typedef struct SRSRAN_API { - uint32_t id; - srsran_coreset_mapping_type_t mapping_type; - uint32_t duration; - bool freq_resources[SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE]; - srsran_coreset_bundle_size_t interleaver_size; - uint32_t offset_rb; ///< Integer offset in resource blocks from the pointA (lowest subcarrier of resource grid) to the - ///< lowest resource block of the CORESET region (used by CORESET Zero only) + uint32_t id; + srsran_coreset_mapping_type_t mapping_type; + uint32_t duration; + bool freq_resources[SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE]; bool dmrs_scrambling_id_present; uint32_t dmrs_scrambling_id; srsran_coreset_precoder_granularity_t precoder_granularity; - srsran_coreset_bundle_size_t reg_bundle_size; + srsran_coreset_bundle_size_t interleaver_size; ///< Referenced in TS 38.211 section 7.3.2.2 as R + srsran_coreset_bundle_size_t reg_bundle_size; ///< Referenced in TS 38.211 section 7.3.2.2 as L uint32_t shift_index; + uint32_t offset_rb; ///< Integer offset in resource blocks from the pointA (lowest subcarrier of resource grid) to the + ///< lowest resource block of the CORESET region (used by CORESET Zero only) + /** Missing TCI parameters */ } srsran_coreset_t; @@ -622,14 +623,16 @@ SRSRAN_API void srsran_combine_csi_trs_measurements(const srsran_csi_trs_measure /** * @brief Setup CORESET Zero from a configuration index * @remark Defined by TS 38.213 tables 13-1, 13-2, 13-3, 13-4, 13-5, 13-6, 13-7, 13-8, 13-9, 13-10 + * @param n_cell_id Physical Cell identifier * @param ssb_pointA_freq_offset_Hz Integer frequency offset in Hz between the SS/PBCH block center and pointA * @param ssb_scs SS/PBCH block subcarrier spacing * @param pdcch_scs PDCCH subcarrier spacing * @param idx CORESET Zero configuration index * @param[out] coreset Points to the resultant CORESET - * @return SRSLTE_SUCCESS if the given inputs lead to a valid CORESET configuration, otherise SRSLTE_ERROR code + * @return SRSRAN_SUCCESS if the given inputs lead to a valid CORESET configuration, otherise SRSRAN_ERROR code */ -SRSRAN_API int srsran_coreset_zero(uint32_t ssb_pointA_freq_offset_Hz, +SRSRAN_API int srsran_coreset_zero(uint32_t n_cell_id, + uint32_t ssb_pointA_freq_offset_Hz, srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs, uint32_t idx, diff --git a/lib/include/srsran/phy/phch/pdcch_nr.h b/lib/include/srsran/phy/phch/pdcch_nr.h index a0b6e9a46..616d4b896 100644 --- a/lib/include/srsran/phy/phch/pdcch_nr.h +++ b/lib/include/srsran/phy/phch/pdcch_nr.h @@ -98,6 +98,17 @@ int srsran_pdcch_nr_locations_coreset(const srsran_coreset_t* coreset, SRSRAN_API int srsran_pdcch_nr_max_candidates_coreset(const srsran_coreset_t* coreset, uint32_t aggregation_level); +/** + * @brief Function for generating a RB mask indicating the CCE-to-REG mapping + * @param coreset A given CORESET + * @param dci_location The DCI location for the PDCCH transmission + * @param[out] rb_mask The resultant mask indicating the locations of PDCCH payload + * @return SRSRAN_SUCCESS if the provided parameters are valid, SRSRAN_ERROR code otherwise + */ +SRSRAN_API int srsran_pdcch_nr_cce_to_reg_mapping(const srsran_coreset_t* coreset, + const srsran_dci_location_t* dci_location, + bool rb_mask[SRSRAN_MAX_PRB_NR]); + SRSRAN_API int srsran_pdcch_nr_init_tx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t* args); SRSRAN_API int srsran_pdcch_nr_init_rx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t* args); diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 7b2a00975..9a78bc310 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -478,7 +478,8 @@ static const coreset_zero_entry_t coreset_zero_30_15[16] = { {}, }; -int srsran_coreset_zero(uint32_t ssb_pointA_freq_offset_Hz, +int srsran_coreset_zero(uint32_t n_cell_id, + uint32_t ssb_pointA_freq_offset_Hz, srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs, uint32_t idx, @@ -545,10 +546,16 @@ int srsran_coreset_zero(uint32_t ssb_pointA_freq_offset_Hz, // Set CORESET fields coreset->id = 0; coreset->dmrs_scrambling_id_present = false; - coreset->mapping_type = srsran_coreset_mapping_type_non_interleaved; coreset->duration = entry->nof_symb; coreset->offset_rb = offset_rb; + // Set CCE-to-REG mapping according to TS 38.211 section 7.3.2.2 + coreset->mapping_type = srsran_coreset_mapping_type_interleaved; + coreset->reg_bundle_size = srsran_coreset_bundle_size_n6; + coreset->interleaver_size = srsran_coreset_bundle_size_n2; + coreset->precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + coreset->shift_index = n_cell_id; + // Set CORESET frequency resource mask for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { coreset->freq_resources[i] = (i < (entry->nof_prb / 6)); diff --git a/lib/src/phy/phch/pdcch_nr.c b/lib/src/phy/phch/pdcch_nr.c index b5be24d35..1d3f348cc 100644 --- a/lib/src/phy/phch/pdcch_nr.c +++ b/lib/src/phy/phch/pdcch_nr.c @@ -304,6 +304,106 @@ int srsran_pdcch_nr_set_carrier(srsran_pdcch_nr_t* q, return SRSRAN_SUCCESS; } +static uint32_t pdcch_nr_bundle_size(srsran_coreset_bundle_size_t x) +{ + switch (x) { + case srsran_coreset_bundle_size_n2: + return 2; + case srsran_coreset_bundle_size_n3: + return 3; + case srsran_coreset_bundle_size_n6: + return 6; + } + return 0; +} + +static int pdcch_nr_cce_to_reg_mapping_non_interleaved(const srsran_coreset_t* coreset, + const srsran_dci_location_t* dci_location, + bool rb_mask[SRSRAN_MAX_PRB_NR]) +{ + uint32_t nof_cce = 1U << dci_location->L; + uint32_t L = 6; + uint32_t nof_reg_bundle = 6 / L; + + // For each CCE j in the PDCCH transmission + for (uint32_t j = dci_location->ncce; j < dci_location->ncce + nof_cce; j++) { + // For each REG bundle i in the CCE j + for (uint32_t reg_bundle = 0; reg_bundle < nof_reg_bundle; reg_bundle++) { + // Calculate x variable + uint32_t x = (6 * j) / L + reg_bundle; + + // For non interleaved f(x) = x + uint32_t i = x; + + // For each REG in the REG bundle + for (uint32_t reg = 0; reg < L; reg++) { + rb_mask[(i * L + reg) / coreset->duration] = true; + } + } + } + + return SRSRAN_SUCCESS; +} + +static int pdcch_nr_cce_to_reg_mapping_interleaved(const srsran_coreset_t* coreset, + const srsran_dci_location_t* dci_location, + bool rb_mask[SRSRAN_MAX_PRB_NR]) +{ + // Calculate CORESET constants + uint32_t N_CORESET_REG = coreset->duration * srsran_coreset_get_bw(coreset); + uint32_t L = pdcch_nr_bundle_size(coreset->reg_bundle_size); + uint32_t R = pdcch_nr_bundle_size(coreset->interleaver_size); + uint32_t C = N_CORESET_REG / (L * R); + uint32_t n_shift = coreset->shift_index; + + // Validate + if (N_CORESET_REG == 0 || N_CORESET_REG % (L * R) != 0 || L % coreset->duration != 0) { + ERROR("Invalid CORESET configuration N=%d; L=%d; R=%d;", N_CORESET_REG, L, R); + return 0; + } + + uint32_t nof_cce = 1U << dci_location->L; + uint32_t nof_reg_bundle = 6 / L; + + // For each CCE j in the PDCCH transmission + for (uint32_t j = dci_location->ncce; j < dci_location->ncce + nof_cce; j++) { + // For each REG bundle i in the CCE j + for (uint32_t reg_bundle = 0; reg_bundle < nof_reg_bundle; reg_bundle++) { + // Calculate x variable + uint32_t x = (6 * j) / L + reg_bundle; + + // For non interleaved f(x) = x + uint32_t r = x % R; + uint32_t c = x / R; + uint32_t i = (r * C + c + n_shift) % (N_CORESET_REG / L); + + // For each REG in the REG bundle i + for (uint32_t reg = 0; reg < L; reg++) { + rb_mask[(i * L + reg) / coreset->duration] = true; + } + } + } + + return SRSRAN_SUCCESS; +} + +int srsran_pdcch_nr_cce_to_reg_mapping(const srsran_coreset_t* coreset, + const srsran_dci_location_t* dci_location, + bool rb_mask[SRSRAN_MAX_PRB_NR]) +{ + if (coreset == NULL || dci_location == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Non-interleaved case + if (coreset->mapping_type == srsran_coreset_mapping_type_non_interleaved) { + return pdcch_nr_cce_to_reg_mapping_non_interleaved(coreset, dci_location, rb_mask); + } + + // Interleaved case + return pdcch_nr_cce_to_reg_mapping_interleaved(coreset, dci_location, rb_mask); +} + static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q, const srsran_dci_location_t* dci_location, cf_t* slot_grid, @@ -311,27 +411,44 @@ static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q, bool put) { uint32_t offset_k = q->coreset.offset_rb * SRSRAN_NRE; - uint32_t L = 1U << dci_location->L; - // Calculate begin and end sub-carrier index for the selected candidate - uint32_t k_begin = (dci_location->ncce * SRSRAN_NRE * 6) / q->coreset.duration; - uint32_t k_end = k_begin + (L * 6 * SRSRAN_NRE) / q->coreset.duration; + // Compute REG list + bool rb_mask[SRSRAN_MAX_PRB_NR] = {}; + if (srsran_pdcch_nr_cce_to_reg_mapping(&q->coreset, dci_location, rb_mask) < SRSRAN_SUCCESS) { + return 0; + } uint32_t count = 0; // Iterate over symbols for (uint32_t l = 0; l < q->coreset.duration; l++) { // Iterate over frequency resource groups - uint32_t k = 0; + uint32_t rb = 0; for (uint32_t r = 0; r < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; r++) { - if (q->coreset.freq_resources[r]) { - for (uint32_t i = r * 6 * SRSRAN_NRE; i < (r + 1) * 6 * SRSRAN_NRE; i++, k++) { - if (k >= k_begin && k < k_end && k % 4 != 1) { - if (put) { - slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i + offset_k] = symbols[count++]; - } else { - symbols[count++] = slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i + offset_k]; - } + // Skip frequency resource if not set + if (!q->coreset.freq_resources[r]) { + continue; + } + + // For each RB in the frequency resource + for (uint32_t i = r * 6; i < (r + 1) * 6; i++, rb++) { + // Skip if this RB is not marked as mapped + if (!rb_mask[rb]) { + continue; + } + + // For each RE in the RB + for (uint32_t k = i * SRSRAN_NRE; k < (i + 1) * SRSRAN_NRE; k++) { + // Skip if it is a DMRS + if (k % 4 == 1) { + continue; + } + + // Read or write in the grid + if (put) { + slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + k + offset_k] = symbols[count++]; + } else { + symbols[count++] = slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + k + offset_k]; } } } diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 9e78dca80..965651324 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -663,4 +663,5 @@ add_nr_test(pusch_nr_ack20_csi4_test pusch_nr_test -p 50 -m 20 -A 20 -C 4) add_executable(pdcch_nr_test pdcch_nr_test.c) target_link_libraries(pdcch_nr_test srsran_phy) -add_nr_test(pdcch_nr_test pdcch_nr_test) +add_nr_test(pdcch_nr_test_non_interleaved pdcch_nr_test) +add_nr_test(pdcch_nr_test_interleaved pdcch_nr_test -I) diff --git a/lib/src/phy/phch/test/pdcch_nr_test.c b/lib/src/phy/phch/test/pdcch_nr_test.c index 15d880abe..52a799d2f 100644 --- a/lib/src/phy/phch/test/pdcch_nr_test.c +++ b/lib/src/phy/phch/test/pdcch_nr_test.c @@ -26,8 +26,9 @@ static srsran_carrier_nr_t carrier = { 1 // max_mimo_layers }; -static uint16_t rnti = 0x1234; -static bool fast_sweep = true; +static uint16_t rnti = 0x1234; +static bool fast_sweep = true; +static bool interleaved = false; typedef struct { uint64_t time_us; @@ -69,16 +70,17 @@ static int test(srsran_pdcch_nr_t* tx, static void usage(char* prog) { - printf("Usage: %s [pFv] \n", prog); + printf("Usage: %s [pFIv] \n", prog); printf("\t-p Number of carrier PRB [Default %d]\n", carrier.nof_prb); printf("\t-F Fast CORESET frequency resource sweeping [Default %s]\n", fast_sweep ? "Enabled" : "Disabled"); + printf("\t-I Enable interleaved CCE-to-REG [Default %s]\n", interleaved ? "Enabled" : "Disabled"); printf("\t-v [set srsran_verbose to debug, default none]\n"); } static int parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "pFv")) != -1) { + while ((opt = getopt(argc, argv, "pFIv")) != -1) { switch (opt) { case 'p': carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); @@ -86,6 +88,9 @@ static int parse_args(int argc, char** argv) case 'F': fast_sweep ^= true; break; + case 'I': + interleaved ^= true; + break; case 'v': srsran_verbose++; break; @@ -135,16 +140,34 @@ int main(int argc, char** argv) goto clean_exit; } - srsran_coreset_t coreset = {}; - uint32_t nof_frequency_resource = SRSRAN_MIN(SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, carrier.nof_prb / 6); + srsran_coreset_t coreset = {}; + if (interleaved) { + coreset.mapping_type = srsran_coreset_mapping_type_interleaved; + coreset.reg_bundle_size = srsran_coreset_bundle_size_n6; + coreset.interleaver_size = srsran_coreset_bundle_size_n2; + coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + coreset.shift_index = carrier.pci; + + carrier.nof_prb = 52; + carrier.pci = 500; + } + + uint32_t nof_frequency_resource = SRSRAN_MIN(SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, carrier.nof_prb / 6); for (uint32_t frequency_resources = 1; frequency_resources < (1U << nof_frequency_resource); frequency_resources = (fast_sweep) ? ((frequency_resources << 1U) | 1U) : (frequency_resources + 1)) { for (uint32_t i = 0; i < nof_frequency_resource; i++) { uint32_t mask = ((frequency_resources >> i) & 1U); coreset.freq_resources[i] = (mask == 1); } + for (coreset.duration = SRSRAN_CORESET_DURATION_MIN; coreset.duration <= SRSRAN_CORESET_DURATION_MAX; coreset.duration++) { + // Skip case if CORESET bandwidth is not enough + uint32_t N = srsran_coreset_get_bw(&coreset) * coreset.duration; + if (interleaved && N % 12 != 0) { + continue; + } + srsran_search_space_t search_space = {}; search_space.type = srsran_search_space_type_ue; search_space.formats[search_space.nof_formats++] = srsran_dci_format_nr_0_0; From 9c3dd563983598215a613d5818fe17a055bba49c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 18 Aug 2021 09:59:53 +0200 Subject: [PATCH 07/56] Added PDCCH DMRS interleaved mapping --- lib/src/phy/ch_estimation/dmrs_pdcch.c | 185 +++++++++--------- lib/src/phy/ch_estimation/test/CMakeLists.txt | 3 +- .../phy/ch_estimation/test/dmrs_pdcch_test.c | 42 ++-- srsue/src/stack/rrc/rrc_nr.cc | 17 +- 4 files changed, 134 insertions(+), 113 deletions(-) diff --git a/lib/src/phy/ch_estimation/dmrs_pdcch.c b/lib/src/phy/ch_estimation/dmrs_pdcch.c index 9cc1a00bf..0a7ca935c 100644 --- a/lib/src/phy/ch_estimation/dmrs_pdcch.c +++ b/lib/src/phy/ch_estimation/dmrs_pdcch.c @@ -13,15 +13,18 @@ #include "srsran/phy/ch_estimation/dmrs_pdcch.h" #include "srsran/phy/ch_estimation/chest_common.h" #include "srsran/phy/common/sequence.h" +#include "srsran/phy/phch/pdcch_nr.h" #include "srsran/phy/utils/convolution.h" #include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/vector.h" #include #include +#define NOF_PILOTS_X_RB 3 + /// @brief Every frequency resource is 6 Resource blocks, every resource block carries 3 pilots. So 18 possible pilots /// per frequency resource. -#define NOF_PILOTS_X_FREQ_RES 18 +#define NOF_PILOTS_X_FREQ_RES (NOF_PILOTS_X_RB * 6) ///@brief Maximum number of pilots in a PDCCH candidate location #define DMRS_PDCCH_MAX_NOF_PILOTS_CANDIDATE \ @@ -51,13 +54,12 @@ static uint32_t dmrs_pdcch_get_cinit(uint32_t slot_idx, uint32_t symbol_idx, uin 2UL * n_id); } -static void dmrs_pdcch_put_symbol_noninterleaved(const srsran_carrier_nr_t* carrier, - const srsran_coreset_t* coreset, - const srsran_dci_location_t* dci_location, - uint32_t cinit, - cf_t* sf_symbol) +static void dmrs_pdcch_put_symbol(const srsran_carrier_nr_t* carrier, + const srsran_coreset_t* coreset, + const bool rb_mask[SRSRAN_MAX_PRB_NR], + uint32_t cinit, + cf_t* sf_symbol) { - uint32_t L = 1U << dci_location->L; uint32_t nof_freq_res = SRSRAN_MIN(carrier->nof_prb / 6, SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE); // Initialise sequence for this symbol @@ -65,67 +67,45 @@ static void dmrs_pdcch_put_symbol_noninterleaved(const srsran_carrier_nr_t* ca srsran_sequence_state_init(&sequence_state, cinit); uint32_t sequence_skip = 0; // Accumulates pilot locations to skip - // Calculate Resource block indexes range, every CCE is 6 REG, 1 REG is 6 RE in resource blocks - uint32_t rb_coreset_idx_begin = (dci_location->ncce * 6) / coreset->duration; - uint32_t rb_coreset_idx_end = ((dci_location->ncce + L) * 6) / coreset->duration; - // CORESET Resource Block counter uint32_t rb_coreset_idx = 0; - for (uint32_t i = 0; i < nof_freq_res; i++) { - // Skip frequency resource if outside of the CORESET - if (!coreset->freq_resources[i]) { - // Skip possible DMRS locations in this region - sequence_skip += NOF_PILOTS_X_FREQ_RES; - continue; - } - // Skip if the frequency resource highest RB is lower than the first CCE resource block. - if ((rb_coreset_idx + 6) <= rb_coreset_idx_begin) { + // For each frequency resource (6 RB groups) + for (uint32_t res_idx = 0; res_idx < nof_freq_res; res_idx++) { + // Skip frequency resource if outside of the CORESET + if (!coreset->freq_resources[res_idx]) { // Skip possible DMRS locations in this region sequence_skip += NOF_PILOTS_X_FREQ_RES; - - // Since this is part of the CORESET, count the RB as CORESET - rb_coreset_idx += 6; continue; } - // Return if the first RB of the frequency resource is greater than the last CCE resource block - if (rb_coreset_idx > rb_coreset_idx_end) { - return; - } - - // Skip all discarded possible pilot locations - srsran_sequence_state_advance(&sequence_state, 2 * sequence_skip); - sequence_skip = 0; - - // Generate pilots - cf_t rl[NOF_PILOTS_X_FREQ_RES]; - srsran_sequence_state_gen_f(&sequence_state, M_SQRT1_2, (float*)rl, NOF_PILOTS_X_FREQ_RES * 2); - - // For each RB in the frequency resource - for (uint32_t j = 0; j < 6; j++) { - // Calculate absolute RB index - uint32_t n = i * 6 + j; - - // Skip if lower than begin - if (rb_coreset_idx < rb_coreset_idx_begin) { - rb_coreset_idx++; + // For each RB in the enabled frequency resource + for (uint32_t rb = 0; rb < 6; rb++, rb_coreset_idx++) { + // Skip if mask is disabled + if (!rb_mask[rb_coreset_idx]) { + sequence_skip += NOF_PILOTS_X_RB; continue; } - // Return if greater than end - if (rb_coreset_idx >= rb_coreset_idx_end) { - return; - } + // Skip all discarded possible pilot locations + srsran_sequence_state_advance(&sequence_state, 2 * sequence_skip); + sequence_skip = 0; + + // Generate pilots for the given RB + cf_t rl[NOF_PILOTS_X_RB]; + srsran_sequence_state_gen_f(&sequence_state, M_SQRT1_2, (float*)rl, NOF_PILOTS_X_RB * 2); + + // Absolute RB index in the resource grid + uint32_t n = res_idx * 6 + rb; // Write pilots in the symbol - for (uint32_t k_prime = 0; k_prime < 3; k_prime++) { - // Calculate sub-carrier index + for (uint32_t k_prime = 0; k_prime < NOF_PILOTS_X_RB; k_prime++) { + // Calculate absolute sub-carrier index in the resource grid uint32_t k = n * SRSRAN_NRE + 4 * k_prime + 1; - sf_symbol[k] = rl[3 * j + k_prime]; + // Write DMRS + sf_symbol[k] = rl[k_prime]; } - rb_coreset_idx++; } } } @@ -140,11 +120,6 @@ int srsran_dmrs_pdcch_put(const srsran_carrier_nr_t* carrier, return SRSRAN_ERROR_INVALID_INPUTS; } - if (coreset->mapping_type == srsran_coreset_mapping_type_interleaved) { - ERROR("Error interleaved CORESET mapping is not currently implemented"); - return SRSRAN_ERROR; - } - if (coreset->duration < SRSRAN_CORESET_DURATION_MIN || coreset->duration > SRSRAN_CORESET_DURATION_MAX) { ERROR("Error CORESET duration %d is out-of-bounds (%d,%d)", coreset->duration, @@ -153,6 +128,13 @@ int srsran_dmrs_pdcch_put(const srsran_carrier_nr_t* carrier, return SRSRAN_ERROR; } + // Calculate CCE-to-REG mapping mask + bool rb_mask[SRSRAN_MAX_PRB_NR] = {}; + if (srsran_pdcch_nr_cce_to_reg_mapping(coreset, dci_location, rb_mask) < SRSRAN_SUCCESS) { + ERROR("Error in CCE-to-REG mapping"); + return SRSRAN_SUCCESS; + } + // Use cell id if the DMR scrambling id is not provided by higher layers uint32_t n_id = carrier->pci; if (coreset->dmrs_scrambling_id_present) { @@ -169,8 +151,7 @@ int srsran_dmrs_pdcch_put(const srsran_carrier_nr_t* carrier, DMRS_PDCCH_INFO_TX("n=%d; l=%d; cinit=%08x", slot_idx, l, cinit); // Put data - dmrs_pdcch_put_symbol_noninterleaved( - carrier, coreset, dci_location, cinit, &sf_symbols[carrier->nof_prb * SRSRAN_NRE * l]); + dmrs_pdcch_put_symbol(carrier, coreset, rb_mask, cinit, &sf_symbols[carrier->nof_prb * SRSRAN_NRE * l]); } return SRSRAN_SUCCESS; @@ -301,7 +282,7 @@ srsran_dmrs_pdcch_extract(srsran_dmrs_pdcch_estimator_t* q, uint32_t cinit, cons uint32_t sequence_skip = 0; // Counts enabled frequency domain resources - uint32_t rb_coreset_idx = 0; + uint32_t lse_count = 0; // Iterate over all possible frequency resources uint32_t freq_domain_res_size = SRSRAN_MIN(q->carrier.nof_prb / 6, SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE); @@ -321,26 +302,23 @@ srsran_dmrs_pdcch_extract(srsran_dmrs_pdcch_estimator_t* q, uint32_t cinit, cons srsran_sequence_state_gen_f(&sequence_state, M_SQRT1_2, (float*)rl, NOF_PILOTS_X_FREQ_RES * 2); // Iterate all PRBs in the enabled frequency domain resource - for (uint32_t j = 0, idx = rb_coreset_idx * NOF_PILOTS_X_FREQ_RES; j < 6; j++) { + cf_t* lse_ptr = &lse[lse_count]; + for (uint32_t j = 0; j < 6; j++) { // Calculate Grid PRB index (n) uint32_t n = i * 6 + j; // For each pilot in the PRB - for (uint32_t k_prime = 0; k_prime < 3; k_prime++, idx++) { + for (uint32_t k_prime = 0; k_prime < 3; k_prime++) { // Calculate sub-carrier index uint32_t k = n * SRSRAN_NRE + 4 * k_prime + 1; // Extract symbol - lse[idx] = sf_symbol[k + offset_k]; + lse[lse_count++] = sf_symbol[k + offset_k]; } } // Calculate least squared estimates - cf_t* lse_ptr = &lse[rb_coreset_idx * NOF_PILOTS_X_FREQ_RES]; srsran_vec_prod_conj_ccc(lse_ptr, rl, lse_ptr, NOF_PILOTS_X_FREQ_RES); - - // Increment frequency domain resource counter - rb_coreset_idx++; } } @@ -424,21 +402,18 @@ int srsran_dmrs_pdcch_get_measure(const srsran_dmrs_pdcch_estimator_t* q, return SRSRAN_ERROR_INVALID_INPUTS; } - uint32_t L = 1U << dci_location->L; - if (q->coreset.mapping_type == srsran_coreset_mapping_type_interleaved) { - ERROR("Error interleaved mapping not implemented"); - return SRSRAN_ERROR; - } - // Check that CORESET duration is not less than minimum if (q->coreset.duration < SRSRAN_CORESET_DURATION_MIN) { ERROR("Invalid CORESET duration"); return SRSRAN_ERROR; } - // Get base pilot; - uint32_t pilot_idx = (dci_location->ncce * 18) / q->coreset.duration; - uint32_t nof_pilots = (L * 18) / q->coreset.duration; + // Calculate CCE-to-REG mapping mask + bool rb_mask[SRSRAN_MAX_PRB_NR] = {}; + if (srsran_pdcch_nr_cce_to_reg_mapping(&q->coreset, dci_location, rb_mask) < SRSRAN_SUCCESS) { + ERROR("Error in CCE-to-REG mapping"); + return SRSRAN_SUCCESS; + } // Initialise measurements float rsrp = 0.0f; //< Averages linear RSRP @@ -447,24 +422,36 @@ int srsran_dmrs_pdcch_get_measure(const srsran_dmrs_pdcch_estimator_t* q, float sync_err_avg = 0.0f; //< Averages synchronization cf_t corr[SRSRAN_CORESET_DURATION_MAX] = {}; //< Saves correlation for the different symbols - // Iterate the CORESET duration + // For each CORESET symbol for (uint32_t l = 0; l < q->coreset.duration; l++) { + // Temporal least square estimates + cf_t tmp[DMRS_PDCCH_MAX_NOF_PILOTS_CANDIDATE]; + uint32_t nof_pilots = 0; + + // For each RB in the CORESET + for (uint32_t rb = 0; rb < q->coreset_bw; rb++) { + // Skip RB if unused + if (!rb_mask[rb]) { + continue; + } + + // Copy LSE + srsran_vec_cf_copy(&tmp[nof_pilots], &q->lse[l][rb * NOF_PILOTS_X_RB], NOF_PILOTS_X_RB); + nof_pilots += NOF_PILOTS_X_RB; + } + if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { DMRS_PDCCH_DEBUG_RX("Measuring PDCCH l=%d; lse=", l); - srsran_vec_fprint_c(stdout, &q->lse[l][pilot_idx], nof_pilots); + srsran_vec_fprint_c(stdout, tmp, nof_pilots); } // Measure synchronization error and accumulate for average - float tmp_sync_err = srsran_vec_estimate_frequency(&q->lse[l][pilot_idx], nof_pilots); + float tmp_sync_err = srsran_vec_estimate_frequency(tmp, nof_pilots); sync_err_avg += tmp_sync_err; #if DMRS_PDCCH_SYNC_PRECOMPENSATE_MEAS - cf_t tmp[DMRS_PDCCH_MAX_NOF_PILOTS_CANDIDATE]; - // Pre-compensate synchronization error - srsran_vec_apply_cfo(&q->lse[l][pilot_idx], tmp_sync_err, tmp, nof_pilots); -#else // DMRS_PDCCH_SYNC_PRECOMPENSATE_MEAS - const cf_t* tmp = &q->lse[l][pilot_idx]; + srsran_vec_apply_cfo(tmp, tmp_sync_err, tmp, nof_pilots); #endif // DMRS_PDCCH_SYNC_PRECOMPENSATE_MEAS // Correlate DMRS @@ -530,10 +517,6 @@ int srsran_dmrs_pdcch_get_ce(const srsran_dmrs_pdcch_estimator_t* q, } uint32_t L = 1U << dci_location->L; - if (q->coreset.mapping_type == srsran_coreset_mapping_type_interleaved) { - ERROR("Error interleaved mapping not implemented"); - return SRSRAN_ERROR; - } // Check that CORESET duration is not less than minimum if (q->coreset.duration < SRSRAN_CORESET_DURATION_MIN) { @@ -541,16 +524,30 @@ int srsran_dmrs_pdcch_get_ce(const srsran_dmrs_pdcch_estimator_t* q, return SRSRAN_ERROR; } - // Calculate begin and end sub-carrier index for the selected candidate - uint32_t k_begin = (dci_location->ncce * SRSRAN_NRE * 6) / q->coreset.duration; - uint32_t k_end = k_begin + (L * 6 * SRSRAN_NRE) / q->coreset.duration; + // Calculate CCE-to-REG mapping mask + bool rb_mask[SRSRAN_MAX_PRB_NR] = {}; + if (srsran_pdcch_nr_cce_to_reg_mapping(&q->coreset, dci_location, rb_mask) < SRSRAN_SUCCESS) { + ERROR("Error in CCE-to-REG mapping"); + return SRSRAN_SUCCESS; + } // Extract CE for PDCCH uint32_t count = 0; + + // For each PDCCH symbol for (uint32_t l = 0; l < q->coreset.duration; l++) { - for (uint32_t k = k_begin; k < k_end; k++) { - if (k % 4 != 1) { - ce->ce[count++] = q->ce[q->coreset_bw * SRSRAN_NRE * l + k]; + // For each CORESET RB + for (uint32_t rb = 0; rb < q->coreset_bw; rb++) { + // Skip RB if unused + if (!rb_mask[rb]) { + continue; + } + + // Copy RB, skipping DMRS + for (uint32_t k = rb * SRSRAN_NRE; k < (rb + 1) * SRSRAN_NRE; k++) { + if (k % 4 != 1) { + ce->ce[count++] = q->ce[q->coreset_bw * SRSRAN_NRE * l + k]; + } } } } diff --git a/lib/src/phy/ch_estimation/test/CMakeLists.txt b/lib/src/phy/ch_estimation/test/CMakeLists.txt index a272e84b5..d56f1536a 100644 --- a/lib/src/phy/ch_estimation/test/CMakeLists.txt +++ b/lib/src/phy/ch_estimation/test/CMakeLists.txt @@ -87,7 +87,8 @@ add_nr_test(dmrs_pdsch_test dmrs_pdsch_test) add_executable(dmrs_pdcch_test dmrs_pdcch_test.c) target_link_libraries(dmrs_pdcch_test srsran_phy) -add_nr_test(dmrs_pdcch_test dmrs_pdcch_test) +add_nr_test(dmrs_pdcch_test_non_interleaved dmrs_pdcch_test) +add_nr_test(dmrs_pdcch_test_interleaved dmrs_pdcch_test -I) ######################################################################## diff --git a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c index 03e8b7818..58bbb4509 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c @@ -19,26 +19,25 @@ #include #include -static srsran_carrier_nr_t carrier = {}; -static srsran_dmrs_pdcch_ce_t pdcch_ce = {}; -static uint16_t rnti = 0x1234; +static srsran_carrier_nr_t carrier = {}; +static srsran_dmrs_pdcch_ce_t pdcch_ce = {}; +static uint16_t rnti = 0x1234; +static bool interleaved = false; void usage(char* prog) { - printf("Usage: %s [recov]\n", prog); - + printf("Usage: %s [recoIv]\n", prog); printf("\t-r nof_prb [Default %d]\n", carrier.nof_prb); printf("\t-e extended cyclic prefix [Default normal]\n"); - printf("\t-c cell_id [Default %d]\n", carrier.pci); - + printf("\t-I Enable interleaved CCE-to-REG [Default %s]\n", interleaved ? "Enabled" : "Disabled"); printf("\t-v increase verbosity\n"); } static void parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "recov")) != -1) { + while ((opt = getopt(argc, argv, "recoIv")) != -1) { switch (opt) { case 'r': carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); @@ -46,6 +45,9 @@ static void parse_args(int argc, char** argv) case 'c': carrier.pci = (uint32_t)strtol(argv[optind], NULL, 10); break; + case 'I': + interleaved ^= true; + break; case 'v': srsran_verbose++; break; @@ -120,7 +122,18 @@ int main(int argc, char** argv) parse_args(argc, argv); - srsran_coreset_t coreset = {}; + srsran_coreset_t coreset = {}; + if (interleaved) { + coreset.mapping_type = srsran_coreset_mapping_type_interleaved; + coreset.reg_bundle_size = srsran_coreset_bundle_size_n6; + coreset.interleaver_size = srsran_coreset_bundle_size_n2; + coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + coreset.shift_index = carrier.pci; + + carrier.nof_prb = 52; + carrier.pci = 500; + } + srsran_search_space_t search_space = {}; srsran_dmrs_pdcch_estimator_t estimator = {}; @@ -130,8 +143,6 @@ int main(int argc, char** argv) uint32_t test_counter = 0; uint32_t test_passed = 0; - coreset.mapping_type = srsran_coreset_mapping_type_non_interleaved; - uint32_t nof_frequency_resource = SRSRAN_MIN(SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, carrier.nof_prb / 6); for (uint32_t frequency_resources = 1; frequency_resources < (1U << nof_frequency_resource); frequency_resources++) { uint32_t nof_freq_resources = 0; @@ -141,7 +152,14 @@ int main(int argc, char** argv) nof_freq_resources += mask; } - for (coreset.duration = 1; coreset.duration <= 3; coreset.duration++) { + for (coreset.duration = SRSRAN_CORESET_DURATION_MIN; coreset.duration <= SRSRAN_CORESET_DURATION_MAX; + coreset.duration++) { + // Skip case if CORESET bandwidth is not enough + uint32_t N = srsran_coreset_get_bw(&coreset) * coreset.duration; + if (interleaved && N % 12 != 0) { + continue; + } + for (search_space.type = srsran_search_space_type_common_0; search_space.type <= srsran_search_space_type_ue; search_space.type++) { for (uint32_t i = 0; i < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; i++) { diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index f151d859c..ab2f95577 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -11,12 +11,12 @@ */ #include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srsran/common/band_helper.h" #include "srsran/common/security.h" #include "srsran/common/standard_streams.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rlc_interfaces.h" #include "srsue/hdr/stack/upper/usim.h" -#include "srsran/common/band_helper.h" #define Error(fmt, ...) rrc_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define Warning(fmt, ...) rrc_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -31,7 +31,9 @@ namespace srsue { const char* rrc_nr::rrc_nr_state_text[] = {"IDLE", "CONNECTED", "CONNECTED-INACTIVE"}; rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : - logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_), conn_recfg_proc(this) + logger(srslog::fetch_basic_logger("RRC-NR")), + task_sched(task_sched_), + conn_recfg_proc(this) {} rrc_nr::~rrc_nr() = default; @@ -802,16 +804,19 @@ bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_com (ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0; // TODO: Select subcarrier spacing from SSB (depending on band) - srsran_subcarrier_spacing_t ssb_scs = srsran_subcarrier_spacing_30kHz ; + srsran_subcarrier_spacing_t ssb_scs = srsran_subcarrier_spacing_30kHz; // Select PDCCH subcarrrier spacing from PDCCH BWP srsran_subcarrier_spacing_t pdcch_scs = phy_cfg.carrier.scs; // Make CORESET Zero from provided field and given subcarrier spacing srsran_coreset_t coreset0 = {}; - if (srsran_coreset_zero( - ssb_pointA_freq_offset_Hz, ssb_scs, pdcch_scs, pdcch_cfg_common.ctrl_res_set_zero, &coreset0) < - SRSASN_SUCCESS) { + if (srsran_coreset_zero(phy_cfg.carrier.pci, + ssb_pointA_freq_offset_Hz, + ssb_scs, + pdcch_scs, + pdcch_cfg_common.ctrl_res_set_zero, + &coreset0) < SRSASN_SUCCESS) { logger.warning("Not possible to create CORESET Zero (ssb_scs=%s, pdcch_scs=%s, idx=%d)", srsran_subcarrier_spacing_to_str(ssb_scs), srsran_subcarrier_spacing_to_str(pdcch_scs), From ae0d8f83f04c72c2f2fa0382d8ddd36956aa4e9b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 18 Aug 2021 10:00:39 +0200 Subject: [PATCH 08/56] Add PDCCH interleaved mapping in phy_dl_nr_test and iterate all possible 15kHz SCS bandwidths --- lib/test/phy/CMakeLists.txt | 28 ++++++++++++++++++------ lib/test/phy/phy_dl_nr_test.c | 41 +++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/lib/test/phy/CMakeLists.txt b/lib/test/phy/CMakeLists.txt index fdaee2cb6..a2b79455c 100644 --- a/lib/test/phy/CMakeLists.txt +++ b/lib/test/phy/CMakeLists.txt @@ -54,11 +54,25 @@ add_lte_test(pucch_ca_test pucch_ca_test) add_executable(phy_dl_nr_test phy_dl_nr_test.c) target_link_libraries(phy_dl_nr_test srsran_phy srsran_common srsran_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -add_nr_test(phy_dl_nr_test phy_dl_nr_test -p 100 -m 28 ) -add_nr_test(phy_dl_nr_test_rvd phy_dl_nr_test -P 52 -p 52 -m 0 - -R 0 52 1 010010010010 00000000010000 - -R 0 52 1 100100100100 00000010000000) -add_nr_test(phy_dl_nr_test_cfo_delay phy_dl_nr_test -P 52 -p 52 -m 27 -C 100.0 -D 4 -n 10) -add_nr_test(phy_dl_nr_test_52prb phy_dl_nr_test -P 52 -p 52 -m 27 -T 256qam -d 1 1 -n 10) -add_nr_test(phy_dl_nr_test_270prb phy_dl_nr_test -P 270 -p 270 -m 27 -T 256qam -d 1 1 -n 10) +# Create a test case for each possible bandwidth described in TS 38.104 Table 5.3.2-1: Transmission bandwidth +# configuration N RB for FR1 +foreach(rb 25 52 79 106 133 160 216 270) + # Basic test with 25 RB grant, maximum MCS, 64QAM + add_nr_test(phy_dl_nr_test_${rb}prb phy_dl_nr_test -P ${rb} -p 25 -m 28) + + # Full BW grant, minimum MCS, with reserved RE + add_nr_test(phy_dl_nr_test_${rb}prb_rvd phy_dl_nr_test -P ${rb} -p ${rb} -m 0 + -R 0 ${rb} 1 010010010010 00000000010000 + -R 0 ${rb} 1 100100100100 00000010000000) + + # 25 RB grant with interleaved PDCCH + add_nr_test(phy_dl_nr_test_${rb}prb_interleaved phy_dl_nr_test -P ${rb} -p 25 -m 10 -I) + + # Maximum throughput with 256QAM + add_nr_test(phy_dl_nr_test_${rb}prb_256qam phy_dl_nr_test -P ${rb} -p ${rb} -m 27 -T 256qam -v -d 1 1 -n 10) + + # Maximum throughput with 64QAM and CFO+Delay impairments + add_nr_test(phy_dl_nr_test_${rb}prb_cfo_delay phy_dl_nr_test -P ${rb} -p ${rb} -m 27 -C 100.0 -D 4 -n 10) + +endforeach() diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 163975925..2b477f160 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -30,19 +30,20 @@ static srsran_carrier_nr_t carrier = { 1 // max_mimo_layers }; -static uint32_t n_prb = 0; // Set to 0 for steering -static uint32_t mcs = 30; // Set to 30 for steering -static srsran_sch_cfg_nr_t pdsch_cfg = {}; -static uint32_t nof_slots = 10; -static uint32_t rv_idx = 0; -static uint32_t delay_n = 0; // Integer delay -static float cfo_hz = 0.0f; // CFO Hz -static srsran_dmrs_sch_type_t dmrs_type = srsran_dmrs_sch_type_1; -static srsran_dmrs_sch_add_pos_t dmrs_add_pos = srsran_dmrs_sch_add_pos_2; +static uint32_t n_prb = 0; // Set to 0 for steering +static uint32_t mcs = 30; // Set to 30 for steering +static srsran_sch_cfg_nr_t pdsch_cfg = {}; +static uint32_t nof_slots = 10; +static uint32_t rv_idx = 0; +static uint32_t delay_n = 0; // Integer delay +static float cfo_hz = 0.0f; // CFO Hz +static srsran_dmrs_sch_type_t dmrs_type = srsran_dmrs_sch_type_1; +static srsran_dmrs_sch_add_pos_t dmrs_add_pos = srsran_dmrs_sch_add_pos_2; +static bool interleaved_pdcch = false; static void usage(char* prog) { - printf("Usage: %s [rRPdpmnTLDCv] \n", prog); + printf("Usage: %s [rRPdpmnTILDCv] \n", prog); printf("\t-P Number of BWP (Carrier) PRB [Default %d]\n", carrier.nof_prb); printf("\t-p Number of grant PRB, set to 0 for steering [Default %d]\n", n_prb); printf("\t-n Number of slots to simulate [Default %d]\n", nof_slots); @@ -52,6 +53,7 @@ static void usage(char* prog) printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n", srsran_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table)); printf("\t-R Reserve RE: [rb_begin] [rb_end] [rb_stride] [sc_mask] [symbol_mask]\n"); + printf("\t-I Enable interleaved CCE-to-REG [Default %s]\n", interleaved_pdcch ? "Enabled" : "Disabled"); printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers); printf("\t-D Delay signal an integer number of samples [Default %d samples]\n", delay_n); printf("\t-C Frequency shift (CFO) signal in Hz [Default %+.0f Hz]\n", cfo_hz); @@ -61,7 +63,7 @@ static void usage(char* prog) static int parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "rRPdpmnTLDCv")) != -1) { + while ((opt = getopt(argc, argv, "rRIPdpmnTLDCv")) != -1) { switch (opt) { case 'P': carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); @@ -123,6 +125,9 @@ static int parse_args(int argc, char** argv) return SRSRAN_ERROR; } } break; + case 'I': + interleaved_pdcch ^= true; + break; case 'L': carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10); break; @@ -263,8 +268,20 @@ int main(int argc, char** argv) srsran_coreset_t* coreset = &pdcch_cfg.coreset[1]; pdcch_cfg.coreset_present[1] = true; coreset->duration = 1; + + uint32_t coreset_bw_rb = carrier.nof_prb; + + if (interleaved_pdcch) { + coreset->mapping_type = srsran_coreset_mapping_type_interleaved; + coreset->reg_bundle_size = srsran_coreset_bundle_size_n6; + coreset->interleaver_size = srsran_coreset_bundle_size_n2; + coreset->precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + coreset->shift_index = carrier.pci; + coreset_bw_rb = SRSRAN_FLOOR(carrier.nof_prb, 12) * 12; + } + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { - coreset->freq_resources[i] = i < carrier.nof_prb / 6; + coreset->freq_resources[i] = i < coreset_bw_rb / 6; } // Configure Search Space From 89ef3b64b4f8fcacf63839b8632c9b272bb17f56 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 18 Aug 2021 13:21:28 +0200 Subject: [PATCH 09/56] Optimization NR PDCCH mapping minor optimization --- lib/src/phy/phch/pdcch_nr.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/src/phy/phch/pdcch_nr.c b/lib/src/phy/phch/pdcch_nr.c index 1d3f348cc..3f0dabd1e 100644 --- a/lib/src/phy/phch/pdcch_nr.c +++ b/lib/src/phy/phch/pdcch_nr.c @@ -336,8 +336,10 @@ static int pdcch_nr_cce_to_reg_mapping_non_interleaved(const srsran_coreset_t* uint32_t i = x; // For each REG in the REG bundle - for (uint32_t reg = 0; reg < L; reg++) { - rb_mask[(i * L + reg) / coreset->duration] = true; + uint32_t rb_start = (i * L) / coreset->duration; + uint32_t rb_end = ((i + 1) * L) / coreset->duration; + for (uint32_t rb = rb_start; rb < rb_end; rb++) { + rb_mask[rb] = true; } } } @@ -377,9 +379,11 @@ static int pdcch_nr_cce_to_reg_mapping_interleaved(const srsran_coreset_t* uint32_t c = x / R; uint32_t i = (r * C + c + n_shift) % (N_CORESET_REG / L); - // For each REG in the REG bundle i - for (uint32_t reg = 0; reg < L; reg++) { - rb_mask[(i * L + reg) / coreset->duration] = true; + // For each REG in the REG bundle + uint32_t rb_start = (i * L) / coreset->duration; + uint32_t rb_end = ((i + 1) * L) / coreset->duration; + for (uint32_t rb = rb_start; rb < rb_end; rb++) { + rb_mask[rb] = true; } } } From 36207db615cf79b1d4bf9b31456c4653538e33cf Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 19 Aug 2021 15:50:03 +0200 Subject: [PATCH 10/56] Added CORESET start_rb helper function --- lib/include/srsran/phy/common/phy_common_nr.h | 12 +++++++++++ lib/src/phy/common/phy_common_nr.c | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 9941df529..bf8270082 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -518,6 +518,18 @@ SRSRAN_API uint32_t srsran_coreset_get_bw(const srsran_coreset_t* coreset); */ SRSRAN_API uint32_t srsran_coreset_get_sz(const srsran_coreset_t* coreset); +/** + * @brief Calculates the starting resource block index in the resource grid + * + * @remark Intended to be used for common search space as specifies the lat clause in TS 38.214 section 5.1.2.2 Resource + * allocation in frequency domain + * + * @param coreset provides the given CORESET configuration + * @return The index of the lowest resource block in the resource grid used by the given CORESET if the CORESET + * configuration is valid; Otherwise, 0. + */ +SRSRAN_API uint32_t srsran_coreset_start_rb(const srsran_coreset_t* coreset); + /** * @brief Get the NR PDSCH mapping type in string * @param mapping_type Mapping type diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 9a78bc310..c46dfd222 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -115,6 +115,26 @@ uint32_t srsran_coreset_get_sz(const srsran_coreset_t* coreset) return srsran_coreset_get_bw(coreset) * SRSRAN_NRE * coreset->duration; } +uint32_t srsran_coreset_start_rb(const srsran_coreset_t* coreset) +{ + // Protect CORESET access + if (coreset == NULL) { + return 0; + } + + // Iterates all the possible frequency resources trying to find the first enabled + for (uint32_t res = 0; res < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; res++) { + // If the frequency resource is enabled... + if (coreset->freq_resources[res]) { + // ... return the lowest resource block index + return 6 * res + coreset->offset_rb; + } + } + + // Returns the start resource index + return 0; +} + const char* srsran_sch_mapping_type_to_str(srsran_sch_mapping_type_t mapping_type) { switch (mapping_type) { From cfe2b305a13a03d23d68a050efdebf3e9960a9f5 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 19 Aug 2021 16:04:29 +0200 Subject: [PATCH 11/56] Fix CORESET0 related PDSCH resource allocation procedure --- lib/include/srsran/phy/phch/dci_nr.h | 16 +++++++----- lib/src/common/phy_cfg_nr.cc | 26 ++++++++++--------- lib/src/phy/phch/dci_nr.c | 3 ++- lib/src/phy/phch/ra_dl_nr.c | 20 ++++++++++++-- lib/src/phy/phch/ra_helper.h | 5 +++- lib/src/phy/phch/ra_ul_nr.c | 6 ++--- lib/src/phy/ue/ue_dl_nr.c | 1 + lib/test/phy/phy_dl_nr_test.c | 1 + .../stack/mac/nr/sched_nr_grant_allocator.cc | 2 +- 9 files changed, 54 insertions(+), 26 deletions(-) diff --git a/lib/include/srsran/phy/phch/dci_nr.h b/lib/include/srsran/phy/phch/dci_nr.h index 8a5de1a32..d12e931dd 100644 --- a/lib/include/srsran/phy/phch/dci_nr.h +++ b/lib/include/srsran/phy/phch/dci_nr.h @@ -111,12 +111,13 @@ typedef struct SRSRAN_API { * @brief Describes the NR DCI search context */ typedef struct SRSRAN_API { - srsran_dci_location_t location; ///< DCI location - srsran_search_space_type_t ss_type; ///< Search space type - uint32_t coreset_id; ///< CORESET identifier - srsran_rnti_type_t rnti_type; ///< RNTI type - srsran_dci_format_nr_t format; ///< DCI format - uint16_t rnti; ///< UE temporal RNTI + srsran_dci_location_t location; ///< DCI location + srsran_search_space_type_t ss_type; ///< Search space type + uint32_t coreset_id; ///< CORESET identifier + uint32_t coreset_start_rb; ///< CORESET lowest RB index in the resource grid + srsran_rnti_type_t rnti_type; ///< RNTI type + srsran_dci_format_nr_t format; ///< DCI format + uint16_t rnti; ///< UE temporal RNTI } srsran_dci_ctx_t; /** @@ -182,6 +183,9 @@ typedef struct SRSRAN_API { uint32_t cbg_flush; ///< CBG flushing out information (CBGFI) uint32_t dmrs_id; ///< DMRS sequence initialization + // DL context from unpacking. Required for resource allocation + uint32_t coreset0_bw; ///< CORESET0 size used for frequency resource allocation + } srsran_dci_dl_nr_t; /** diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 907beaacd..47251b440 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -223,12 +223,13 @@ bool phy_cfg_nr_t::get_dci_ctx_pdsch_rnti_c(uint32_t ss_id, const srsran_search_space_t& ss = pdcch.search_space[ss_id]; // Fill context - ctx.location = location; - ctx.ss_type = ss.type; - ctx.coreset_id = ss.coreset_id; - ctx.rnti_type = srsran_rnti_type_c; - ctx.format = format; - ctx.rnti = rnti; + ctx.location = location; + ctx.ss_type = ss.type; + ctx.coreset_id = ss.coreset_id; + ctx.coreset_start_rb = srsran_coreset_start_rb(&pdcch.coreset[ss.coreset_id]); + ctx.rnti_type = srsran_rnti_type_c; + ctx.format = format; + ctx.rnti = rnti; return true; } @@ -248,12 +249,13 @@ bool phy_cfg_nr_t::get_dci_ctx_pusch_rnti_c(uint32_t ss_id, const srsran_search_space_t& ss = pdcch.search_space[ss_id]; // Fill context - ctx.location = location; - ctx.ss_type = ss.type; - ctx.coreset_id = ss.coreset_id; - ctx.rnti_type = srsran_rnti_type_c; - ctx.format = format; - ctx.rnti = rnti; + ctx.location = location; + ctx.ss_type = ss.type; + ctx.coreset_id = ss.coreset_id; + ctx.coreset_start_rb = srsran_coreset_start_rb(&pdcch.coreset[ss.coreset_id]); + ctx.rnti_type = srsran_rnti_type_c; + ctx.format = format; + ctx.rnti = rnti; return true; } diff --git a/lib/src/phy/phch/dci_nr.c b/lib/src/phy/phch/dci_nr.c index 2998a58cd..a37c06a4a 100644 --- a/lib/src/phy/phch/dci_nr.c +++ b/lib/src/phy/phch/dci_nr.c @@ -1990,7 +1990,8 @@ int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, } // Copy DCI MSG fields - dci->ctx = msg->ctx; + dci->ctx = msg->ctx; + dci->coreset0_bw = q->cfg.coreset0_bw; // Pack DCI switch (msg->ctx.format) { diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index e8712324b..7665370e6 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -292,10 +292,26 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier, return SRSRAN_ERROR_INVALID_INPUTS; } + // For a PDSCH scheduled with a DCI format 1_0 in any type of PDCCH common search space, regardless of which + // bandwidth part is the active bandwidth part, RB numbering starts from the lowest RB of the CORESET in which the + // DCI was received; otherwise RB numbering starts from the lowest RB in the determined downlink bandwidth part. + uint32_t start_rb = 0; + if (dci_dl->ctx.format == srsran_dci_format_nr_1_0 && SRSRAN_SEARCH_SPACE_IS_COMMON(dci_dl->ctx.ss_type)) { + start_rb = dci_dl->ctx.coreset_start_rb; + } + + // when DCI format 1_0 is decoded in any common search space in which case the size of CORESET 0 shall be used if + // CORESET 0 is configured for the cell and the size of initial DL bandwidth part shall be used if CORESET 0 is not + // configured for the cell. + uint32_t type1_bwp_sz = carrier->nof_prb; + if (SRSRAN_SEARCH_SPACE_IS_COMMON(dci_dl->ctx.ss_type) && dci_dl->coreset0_bw != 0) { + type1_bwp_sz = dci_dl->coreset0_bw; + } + // The UE shall assume that when the scheduling grant is received with DCI format 1_0 , then downlink resource // allocation type 1 is used. if (dci_dl->ctx.format == srsran_dci_format_nr_1_0) { - return ra_helper_freq_type1(carrier->nof_prb, dci_dl->freq_domain_assigment, grant); + return ra_helper_freq_type1(type1_bwp_sz, start_rb, dci_dl->freq_domain_assigment, grant); } // If the scheduling DCI is configured to indicate the downlink resource allocation type as part of the Frequency @@ -309,7 +325,7 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier, // Otherwise the UE shall use the downlink frequency resource allocation type as defined by the higher layer parameter // resourceAllocation. if (cfg->alloc == srsran_resource_alloc_type1) { - return ra_helper_freq_type1(carrier->nof_prb, dci_dl->freq_domain_assigment, grant); + return ra_helper_freq_type1(type1_bwp_sz, start_rb, dci_dl->freq_domain_assigment, grant); } if (cfg->alloc == srsran_resource_alloc_type0) { diff --git a/lib/src/phy/phch/ra_helper.h b/lib/src/phy/phch/ra_helper.h index 2c25563a5..2f40c64b9 100644 --- a/lib/src/phy/phch/ra_helper.h +++ b/lib/src/phy/phch/ra_helper.h @@ -61,7 +61,7 @@ static int ra_helper_freq_type0(const srsran_carrier_nr_t* carrier, return 0; } -static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srsran_sch_grant_nr_t* grant) +static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t start_rb, uint32_t riv, srsran_sch_grant_nr_t* grant) { uint32_t start = 0; uint32_t len = 0; @@ -72,6 +72,9 @@ static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srsran_sch_gr return SRSRAN_ERROR; } + // Apply numbering start + start += start_rb; + for (uint32_t i = 0; i < start; i++) { grant->prb_idx[i] = false; } diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index b2e15ffd2..b750f1ea4 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -440,13 +440,13 @@ int srsran_ra_ul_nr_freq(const srsran_carrier_nr_t* carrier, // TS 38.213 PUSCH scheduled by RAR UL grant if (dci_ul->ctx.format == srsran_dci_format_nr_rar) { - return ra_helper_freq_type1(carrier->nof_prb, dci_ul->freq_domain_assigment, grant); + return ra_helper_freq_type1(carrier->nof_prb, 0, dci_ul->freq_domain_assigment, grant); } // The UE shall assume that when the scheduling PDCCH is received with DCI format 0_0, then uplink resource // allocation type 1 is used. if (dci_ul->ctx.format == srsran_dci_format_nr_0_0) { - return ra_helper_freq_type1(carrier->nof_prb, dci_ul->freq_domain_assigment, grant); + return ra_helper_freq_type1(carrier->nof_prb, 0, dci_ul->freq_domain_assigment, grant); } // If the scheduling DCI is configured to indicate the uplink resource allocation type as part of the Frequency domain @@ -459,7 +459,7 @@ int srsran_ra_ul_nr_freq(const srsran_carrier_nr_t* carrier, // Otherwise the UE shall use the uplink frequency resource allocation type as defined by the higher layer parameter // resourceAllocation. if (cfg->alloc == srsran_resource_alloc_type1) { - return ra_helper_freq_type1(carrier->nof_prb, dci_ul->freq_domain_assigment, grant); + return ra_helper_freq_type1(carrier->nof_prb, 0, dci_ul->freq_domain_assigment, grant); } if (cfg->alloc == srsran_resource_alloc_type0) { diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 74777cf0e..a5283a620 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -387,6 +387,7 @@ static int ue_dl_nr_find_dci_ss(srsran_ue_dl_nr_t* q, ctx.location.ncce = candidates[ncce_idx]; ctx.ss_type = search_space->type; ctx.coreset_id = search_space->coreset_id; + ctx.coreset_start_rb = srsran_coreset_start_rb(&q->cfg.coreset[search_space->coreset_id]); ctx.rnti_type = rnti_type; ctx.rnti = rnti; ctx.format = dci_format; diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 2b477f160..528721d95 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -168,6 +168,7 @@ static int work_gnb_dl(srsran_gnb_dl_t* gnb_dl, dci_dl.ctx.location = *dci_location; dci_dl.ctx.ss_type = search_space->type; dci_dl.ctx.coreset_id = 1; + dci_dl.ctx.coreset_start_rb = 0; dci_dl.freq_domain_assigment = 0; dci_dl.time_domain_assigment = 0; dci_dl.vrb_to_prb_mapping = 0; diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index d7bb85c80..daffd30b3 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -343,4 +343,4 @@ alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, b } } // namespace sched_nr_impl -} // namespace srsenb \ No newline at end of file +} // namespace srsenb From 7da2d20447a2e8f14ad38b4c201ebdbc2ab83c3a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Aug 2021 10:00:36 +0200 Subject: [PATCH 12/56] Added UE UL NR frequency offset option --- lib/include/srsran/phy/ue/ue_ul_nr.h | 4 ++++ lib/src/phy/ue/ue_ul_nr.c | 30 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/include/srsran/phy/ue/ue_ul_nr.h b/lib/include/srsran/phy/ue/ue_ul_nr.h index 904bdb749..70c17fb13 100644 --- a/lib/include/srsran/phy/ue/ue_ul_nr.h +++ b/lib/include/srsran/phy/ue/ue_ul_nr.h @@ -48,12 +48,16 @@ typedef struct SRSRAN_API { srsran_pusch_nr_t pusch; srsran_pucch_nr_t pucch; srsran_dmrs_sch_t dmrs; + + float freq_offset_hz; } srsran_ue_ul_nr_t; SRSRAN_API int srsran_ue_ul_nr_init(srsran_ue_ul_nr_t* q, cf_t* output, const srsran_ue_ul_nr_args_t* args); SRSRAN_API int srsran_ue_ul_nr_set_carrier(srsran_ue_ul_nr_t* q, const srsran_carrier_nr_t* carrier); +SRSRAN_API void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz); + SRSRAN_API int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_sch_cfg_nr_t* pusch_cfg, diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 3b0073985..38e8b0fb8 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -95,6 +95,15 @@ int srsran_ue_ul_nr_set_carrier(srsran_ue_ul_nr_t* q, const srsran_carrier_nr_t* return SRSRAN_SUCCESS; } +void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz) +{ + if (q == NULL) { + return; + } + + q->freq_offset_hz = freq_offset_hz; +} + int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_sch_cfg_nr_t* pusch_cfg, @@ -130,6 +139,12 @@ int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, srsran_vec_sc_prod_cfc(q->ifft.cfg.out_buffer, 0.99f / max_peak, q->ifft.cfg.out_buffer, q->ifft.sf_sz); } + // Apply frequency offset + if (isnormal(q->freq_offset_hz)) { + srsran_vec_apply_cfo( + q->ifft.cfg.out_buffer, -q->freq_offset_hz / (1000.0f * q->ifft.sf_sz), q->ifft.cfg.out_buffer, q->ifft.sf_sz); + } + return SRSRAN_SUCCESS; } @@ -219,6 +234,19 @@ int srsran_ue_ul_nr_encode_pucch(srsran_ue_ul_nr_t* q, // Generate signal srsran_ofdm_tx_sf(&q->ifft); + // Normalise to peak + uint32_t max_idx = srsran_vec_max_abs_ci(q->ifft.cfg.out_buffer, q->ifft.sf_sz); + float max_peak = cabsf(q->ifft.cfg.out_buffer[max_idx]); + if (isnormal(max_peak)) { + srsran_vec_sc_prod_cfc(q->ifft.cfg.out_buffer, 0.99f / max_peak, q->ifft.cfg.out_buffer, q->ifft.sf_sz); + } + + // Apply frequency offset + if (isnormal(q->freq_offset_hz)) { + srsran_vec_apply_cfo( + q->ifft.cfg.out_buffer, -q->freq_offset_hz / (1000.0f * q->ifft.sf_sz), q->ifft.cfg.out_buffer, q->ifft.sf_sz); + } + return SRSRAN_SUCCESS; } @@ -249,6 +277,8 @@ int srsran_ue_ul_nr_pusch_info(const srsran_ue_ul_nr_t* q, // Append PDSCH info len += srsran_pusch_nr_tx_info(&q->pusch, cfg, &cfg->grant, uci_value, &str[len], str_len - len); + len = srsran_print_check(str, str_len, len, " cfo=%.0f", q->freq_offset_hz); + return len; } From 5aa2279990dc2a3b70a8cee7b29224a1a28f9631 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Aug 2021 10:01:08 +0200 Subject: [PATCH 13/56] Fix NZP-CSI-RS CFO sign --- lib/src/phy/ch_estimation/csi_rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index 4d0af1879..cfe490705 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -696,7 +696,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier, float cfo_max = 0.0f; for (uint32_t i = 1; i < count; i++) { float time_diff = srsran_symbol_distance_s(measurements[i - 1].l0, measurements[i].l0, carrier->scs); - float phase_diff = cargf(measurements[i].corr * conjf(measurements[i - 1].corr)); + float phase_diff = cargf(measurements[i - 1].corr * conjf(measurements[i].corr)); float cfo_max_temp = 0.0f; // Avoid zero division From 83b9b2d1ff44992576e0a91542a7245529438df1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Aug 2021 10:02:24 +0200 Subject: [PATCH 14/56] Implemented UE open loop CFO compensation for NR --- .../srsran/interfaces/ue_nr_interfaces.h | 26 +++--- lib/src/phy/common/phy_common_nr.c | 3 +- srsue/hdr/phy/nr/sf_worker.h | 1 + srsue/hdr/phy/nr/state.h | 65 +++++++++++++++ srsue/hdr/phy/nr/worker_pool.h | 6 ++ srsue/hdr/phy/phy_metrics.h | 4 +- srsue/src/phy/nr/cc_worker.cc | 83 ++++++++----------- srsue/src/phy/nr/worker_pool.cc | 2 +- srsue/src/phy/sync.cc | 4 + 9 files changed, 132 insertions(+), 62 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 367b08b6a..04fc73ee5 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -166,17 +166,21 @@ public: }; struct phy_args_nr_t { - uint32_t rf_channel_offset = 0; ///< Specifies the RF channel the NR carrier shall fill - uint32_t nof_carriers = 1; - uint32_t max_nof_prb = 106; - uint32_t nof_phy_threads = 3; - uint32_t worker_cpu_mask = 0; - srsran::phy_log_args_t log = {}; - srsran_ue_dl_nr_args_t dl = {}; - srsran_ue_ul_nr_args_t ul = {}; - std::set fixed_sr = {1}; - uint32_t fix_wideband_cqi = 15; // Set to a non-zero value for fixing the wide-band CQI report - bool store_pdsch_ko = false; + uint32_t rf_channel_offset = 0; ///< Specifies the RF channel the NR carrier shall fill + uint32_t nof_carriers = 1; + uint32_t max_nof_prb = 106; + uint32_t nof_phy_threads = 3; + uint32_t worker_cpu_mask = 0; + srsran::phy_log_args_t log = {}; + srsran_ue_dl_nr_args_t dl = {}; + srsran_ue_ul_nr_args_t ul = {}; + std::set fixed_sr = {1}; + uint32_t fix_wideband_cqi = 15; // Set to a non-zero value for fixing the wide-band CQI report + bool store_pdsch_ko = false; + float trs_epre_ema_alpha = 0.1f; ///< EPRE measurement exponential average alpha + float trs_rsrp_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha + float trs_cfo_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha + bool enable_worker_cfo = true; ///< Enable/Disable open loop CFO correction at the workers phy_args_nr_t() { diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index c46dfd222..3dbc974e7 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -343,12 +343,13 @@ uint32_t srsran_csi_meas_info(const srsran_csi_trs_measurements_t* meas, char* s return srsran_print_check(str, str_len, 0, - "rsrp=%+.1f epre=%+.1f n0=%+.1f snr=%+.1f cfo=%+.1f delay=%+.1f", + "rsrp=%+.1f epre=%+.1f n0=%+.1f snr=%+.1f cfo=%+.1f cfo_max=%.0f delay=%+.1f", meas->rsrp_dB, meas->epre_dB, meas->n0_dB, meas->snr_dB, meas->cfo_hz, + meas->cfo_hz_max, meas->delay_us); } diff --git a/srsue/hdr/phy/nr/sf_worker.h b/srsue/hdr/phy/nr/sf_worker.h index 7b69c079e..9f8927644 100644 --- a/srsue/hdr/phy/nr/sf_worker.h +++ b/srsue/hdr/phy/nr/sf_worker.h @@ -59,6 +59,7 @@ private: cf_t* prach_ptr = nullptr; float prach_power = 0; srsran::phy_common_interface::worker_context_t context = {}; + float ul_ext_cfo = 0.0f; ///< UL CFO external offset in Hz }; } // namespace nr diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 5c7d09f36..6ff0afbfb 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -60,6 +60,13 @@ private: std::mutex csi_measurements_mutex; std::array csi_measurements = {}; + /// TRS measurements + mutable std::mutex trs_measurements_mutex; + srsran_csi_trs_measurements_t trs_measurements = {}; + + /// Other measurements + std::atomic ul_ext_cfo_hz = {0.0f}; + /** * @brief Resets all metrics (unprotected) */ @@ -453,6 +460,64 @@ public: return; } } + + /** + * @brief Processes a new Tracking Reference Signal (TRS) measurement + * @param new_measure New measurement + * @param resource_set_id NZP-CSI-RS resource set identifier used for the channel measurement if it is configured from + * a NZP-CSI-RS + * @param K_csi_rs Number of NZP-CSI-RS resources used for the measurement, set to 0 if another type of signal is + * measured (i.e. SSB) + */ + void new_csi_trs_measurement(const srsran_csi_trs_measurements_t& new_meas, + uint32_t resource_set_id = 0, + uint32_t K_csi_rs = 0) + { + // Compute channel metrics and push it + ch_metrics_t new_ch_metrics = {}; + new_ch_metrics.sinr = new_meas.snr_dB; + new_ch_metrics.rsrp = new_meas.rsrp_dB; + new_ch_metrics.rsrq = 0.0f; // Not supported + new_ch_metrics.rssi = 0.0f; // Not supported + new_ch_metrics.sync_err = new_meas.delay_us; + set_channel_metrics(new_ch_metrics); + + // Compute synch metrics and report it to the PHY state + sync_metrics_t new_sync_metrics = {}; + new_sync_metrics.cfo = new_meas.cfo_hz; + set_sync_metrics(sync_metrics); + + // Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state + srsran_csi_channel_measurements_t measurements = {}; + measurements.cri = 0; + measurements.wideband_rsrp_dBm = new_meas.rsrp_dB; + measurements.wideband_epre_dBm = new_meas.epre_dB; + measurements.wideband_snr_db = new_meas.snr_dB; + measurements.nof_ports = 1; // Other values are not supported + measurements.K_csi_rs = K_csi_rs; + new_nzp_csi_rs_channel_measurement(measurements, resource_set_id); + + trs_measurements_mutex.lock(); + trs_measurements.rsrp_dB = SRSRAN_VEC_SAFE_EMA(new_meas.rsrp_dB, trs_measurements.rsrp_dB, args.trs_epre_ema_alpha); + trs_measurements.epre_dB = SRSRAN_VEC_SAFE_EMA(new_meas.epre_dB, trs_measurements.epre_dB, args.trs_rsrp_ema_alpha); + trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha); + trs_measurements.nof_re++; + trs_measurements_mutex.unlock(); + } + + float get_dl_cfo() + { + std::lock_guard lock(trs_measurements_mutex); + return trs_measurements.cfo_hz; + } + + float get_ul_cfo() const + { + std::lock_guard lock(trs_measurements_mutex); + return trs_measurements.cfo_hz + ul_ext_cfo_hz; + } + + void set_ul_ext_cfo(float ext_cfo_hz) { ul_ext_cfo_hz = ext_cfo_hz; } }; } // namespace nr } // namespace srsue diff --git a/srsue/hdr/phy/nr/worker_pool.h b/srsue/hdr/phy/nr/worker_pool.h index 81d579ef8..c0d96232e 100644 --- a/srsue/hdr/phy/nr/worker_pool.h +++ b/srsue/hdr/phy/nr/worker_pool.h @@ -49,6 +49,12 @@ public: void clear_pending_grants() override; void get_metrics(phy_metrics_t& m); int tx_request(const tx_request_t& request) override; + + /** + * @brief Sets external CFO to compensate UL signal frequency offset + * @param ext_cfo_hz External CFO in Hz + */ + void set_ul_ext_cfo(float ext_cfo_hz) { phy_state.set_ul_ext_cfo(ext_cfo_hz); } }; } // namespace nr diff --git a/srsue/hdr/phy/phy_metrics.h b/srsue/hdr/phy/phy_metrics.h index c5ba106e9..11233ceb9 100644 --- a/srsue/hdr/phy/phy_metrics.h +++ b/srsue/hdr/phy/phy_metrics.h @@ -27,7 +27,7 @@ struct info_metrics_t { #define PHY_METRICS_SET(PARAM) \ do { \ - PARAM = PARAM + (other.PARAM - PARAM) / count; \ + PARAM = SRSRAN_VEC_SAFE_CMA(other.PARAM, PARAM, count); \ } while (false) struct sync_metrics_t { @@ -41,12 +41,12 @@ struct sync_metrics_t { void set(const sync_metrics_t& other) { - count++; ta_us = other.ta_us; distance_km = other.distance_km; speed_kmph = other.speed_kmph; PHY_METRICS_SET(cfo); PHY_METRICS_SET(sfo); + count++; } void reset() diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index a69faafae..11478547f 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -286,10 +286,11 @@ bool cc_worker::decode_pdsch_dl() srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size()); logger.info(pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, - "PDSCH: cc=%d pid=%d %s\n%s", + "PDSCH: cc=%d pid=%d %s cfo=%.1f\n%s", cc_idx, pid, str.data(), + ue_dl.chest.cfo, str_extra.data()); } else { logger.info(pdsch_res.tb[0].payload, @@ -381,27 +382,13 @@ bool cc_worker::measure_csi() logger.debug("SSB-CSI: %s", str.data()); } - // Compute channel metrics and push it - ch_metrics_t ch_metrics = {}; - ch_metrics.sinr = meas.snr_dB; - ch_metrics.rsrp = meas.rsrp_dB; - ch_metrics.rsrq = 0.0f; // Not supported - ch_metrics.rssi = 0.0f; // Not supported - ch_metrics.sync_err = - meas.delay_us / (float)(ue_dl.fft->fft_plan.size * SRSRAN_SUBC_SPACING_NR(phy.cfg.carrier.scs)); - phy.set_channel_metrics(ch_metrics); - - // Compute synch metrics and report it to the PHY state - sync_metrics_t sync_metrics = {}; - sync_metrics.cfo = meas.cfo_hz; - phy.set_sync_metrics(sync_metrics); - // Report SSB candidate channel measurement to the PHY state - // ... + phy.new_csi_trs_measurement(meas); } } // Iterate all NZP-CSI-RS marked as TRS and perform channel measurements + bool estimate_fft = false; for (uint32_t resource_set_id = 0; resource_set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS; resource_set_id++) { // Select NZP-CSI-RS set const srsran_csi_rs_nzp_set_t& nzp_set = phy.cfg.pdsch.nzp_csi_rs_sets[resource_set_id]; @@ -411,6 +398,12 @@ bool cc_worker::measure_csi() continue; } + // Run FFT if not done before in this slot + if (not estimate_fft) { + srsran_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); + estimate_fft = true; + } + // Perform measurement, n > 0 is any measurement is performed, n = 0 otherwise srsran_csi_trs_measurements_t trs_measurements = {}; int n = srsran_ue_dl_nr_csi_measure_trs(&ue_dl, &dl_slot_cfg, &nzp_set, &trs_measurements); @@ -430,30 +423,7 @@ bool cc_worker::measure_csi() logger.debug("NZP-CSI-RS (TRS): id=%d %s", resource_set_id, str.data()); } - // Compute channel metrics and push it - ch_metrics_t ch_metrics = {}; - ch_metrics.sinr = trs_measurements.snr_dB; - ch_metrics.rsrp = trs_measurements.rsrp_dB; - ch_metrics.rsrq = 0.0f; // Not supported - ch_metrics.rssi = 0.0f; // Not supported - ch_metrics.sync_err = - trs_measurements.delay_us / (float)(ue_dl.fft->fft_plan.size * SRSRAN_SUBC_SPACING_NR(phy.cfg.carrier.scs)); - phy.set_channel_metrics(ch_metrics); - - // Compute synch metrics and report it to the PHY state - sync_metrics_t sync_metrics = {}; - sync_metrics.cfo = trs_measurements.cfo_hz; - phy.set_sync_metrics(sync_metrics); - - // Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state - srsran_csi_channel_measurements_t measurements = {}; - measurements.cri = 0; - measurements.wideband_rsrp_dBm = trs_measurements.rsrp_dB; - measurements.wideband_epre_dBm = trs_measurements.epre_dB; - measurements.wideband_snr_db = trs_measurements.snr_dB; - measurements.nof_ports = 1; // Other values are not supported - measurements.K_csi_rs = (uint32_t)n; - phy.new_nzp_csi_rs_channel_measurement(measurements, resource_set_id); + phy.new_csi_trs_measurement(trs_measurements, resource_set_id, (uint32_t)n); } // Iterate all NZP-CSI-RS not marked as TRS and perform channel measurements @@ -466,6 +436,12 @@ bool cc_worker::measure_csi() continue; } + // Run FFT if not done before in this slot + if (not estimate_fft) { + srsran_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); + estimate_fft = true; + } + // Perform channel measurement, n > 0 is any measurement is performed, n = 0 otherwise srsran_csi_channel_measurements_t measurements = {}; int n = srsran_ue_dl_nr_csi_measure_channel(&ue_dl, &dl_slot_cfg, &nzp_set, &measurements); @@ -504,6 +480,22 @@ bool cc_worker::work_dl() return true; } + // Measure CSI + if (not measure_csi()) { + logger.error("Error measuring, aborting work DL"); + return false; + } + + // Compensate CFO from TRS measurements + if (std::isnormal(phy.args.enable_worker_cfo)) { + float dl_cfo_hz = phy.get_dl_cfo(); + for (cf_t* b : rx_buffer) { + if (b != nullptr and ue_ul.ifft.sf_sz != 0) { + srsran_vec_apply_cfo(b, dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz), b, ue_ul.ifft.sf_sz); + } + } + } + // Run FFT srsran_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); @@ -519,12 +511,6 @@ bool cc_worker::work_dl() return false; } - // Measure CSI - if (not measure_csi()) { - logger.error("Error measuring, aborting work DL"); - return false; - } - return true; } @@ -582,6 +568,9 @@ bool cc_worker::work_ul() // Add CSI reports to UCI data if available phy.get_periodic_csi(ul_slot_cfg.idx, uci_data); + // Setup frequency offset + srsran_ue_ul_nr_set_freq_offset(&ue_ul, phy.get_ul_cfo()); + if (has_pusch_grant) { // Notify MAC about PUSCH found grant mac_interface_phy_nr::tb_action_ul_t ul_action = {}; diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 44e985784..53fa8f13b 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -79,7 +79,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) { uint32_t nof_prach_sf = 0; float prach_target_power = 0.0f; - cf_t* prach_ptr = prach_buffer->generate(0.0f, &nof_prach_sf, &prach_target_power); + cf_t* prach_ptr = prach_buffer->generate(-phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power); worker->set_prach(prach_ptr, prach_target_power); } diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 22b1c3ced..5d7c56608 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -541,6 +541,10 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, nr_worker->set_context(context); + // As UE sync compensates CFO externally based on LTE signal and the NR carrier may estimate the CFO from the LTE + // signal. It is necessary setting an NR external CFO offset to compensate it. + nr_worker_pool->set_ul_ext_cfo(-srsran_ue_sync_get_cfo(&ue_sync)); + // NR worker needs to be launched first, phy_common::worker_end expects first the NR worker and the LTE worker. worker_com->semaphore.push(nr_worker); nr_worker_pool->start_worker(nr_worker); From 4cb633e6e69610648c575b4448a1baaab5591a5b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Aug 2021 13:15:28 +0200 Subject: [PATCH 15/56] UE dicards NR CFO measurement if SNR is negative --- srsue/hdr/phy/nr/state.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 6ff0afbfb..f804b8a6a 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -497,10 +497,16 @@ public: measurements.K_csi_rs = K_csi_rs; new_nzp_csi_rs_channel_measurement(measurements, resource_set_id); + // Update tracking information trs_measurements_mutex.lock(); trs_measurements.rsrp_dB = SRSRAN_VEC_SAFE_EMA(new_meas.rsrp_dB, trs_measurements.rsrp_dB, args.trs_epre_ema_alpha); trs_measurements.epre_dB = SRSRAN_VEC_SAFE_EMA(new_meas.epre_dB, trs_measurements.epre_dB, args.trs_rsrp_ema_alpha); - trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha); + // Consider CFO measurement invalid if the SNR is negative. In this case, set CFO to 0. + if (trs_measurements.snr_dB > 0.0f) { + trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha); + } else { + trs_measurements.cfo_hz = 0.0f; + } trs_measurements.nof_re++; trs_measurements_mutex.unlock(); } From 8aa7ae7d9530a876892d4f72b95eb7eb7c52cc16 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Aug 2021 15:19:21 +0200 Subject: [PATCH 16/56] Remove unused attribute --- srsue/hdr/phy/nr/sf_worker.h | 1 - 1 file changed, 1 deletion(-) diff --git a/srsue/hdr/phy/nr/sf_worker.h b/srsue/hdr/phy/nr/sf_worker.h index 9f8927644..7b69c079e 100644 --- a/srsue/hdr/phy/nr/sf_worker.h +++ b/srsue/hdr/phy/nr/sf_worker.h @@ -59,7 +59,6 @@ private: cf_t* prach_ptr = nullptr; float prach_power = 0; srsran::phy_common_interface::worker_context_t context = {}; - float ul_ext_cfo = 0.0f; ///< UL CFO external offset in Hz }; } // namespace nr From 2b114cb7b9dd8ec00d9d2701d54fbd331bbfc5a4 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 24 Aug 2021 11:17:55 +0200 Subject: [PATCH 17/56] sched,nr: create simple NR scheduler RAR test --- srsenb/src/stack/mac/nr/sched_nr_cell.cc | 1 + srsenb/test/mac/nr/CMakeLists.txt | 3 + srsenb/test/mac/nr/sched_nr_cfg_generators.h | 3 +- srsenb/test/mac/nr/sched_nr_rar_test.cc | 101 +++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 srsenb/test/mac/nr/sched_nr_rar_test.cc diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index fa49c69ac..9eddfc0ed 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -209,6 +209,7 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) for (slot_point t = rar_info.prach_slot + prach_duration; t < rar_info.prach_slot + bwp_cfg->slots.size(); ++t) { if (bwp_cfg->slots[t.slot_idx()].is_dl) { p.rar_win = {t, t + bwp_cfg->cfg.rar_window_size}; + break; } } p.msg3_grant.push_back(rar_info); diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index 528a9e3e2..9af588f18 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -21,3 +21,6 @@ target_link_libraries(sched_nr_prb_test ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_test(sched_nr_prb_test sched_nr_prb_test) + +add_executable(sched_nr_rar_test sched_nr_rar_test.cc) +target_link_libraries(sched_nr_rar_test srsgnb_mac srsran_common) \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 65698c402..498f2a578 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -30,7 +30,8 @@ srsran_coreset_t get_default_coreset0(uint32_t nof_prb) return coreset; } -sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg) +sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ + srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { sched_nr_interface::cell_cfg_t cell_cfg{}; diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc new file mode 100644 index 000000000..cf9b5b431 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -0,0 +1,101 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "sched_nr_cfg_generators.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cell.h" +#include "srsran/common/test_common.h" +#include "srsran/support/srsran_test.h" +#include + +namespace srsenb { + +void test_single_prach() +{ + using namespace sched_nr_impl; + const uint16_t rnti = 0x1234; + static srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC"); + std::random_device r; + std::default_random_engine rgen(r()); + + sched_nr_interface::sched_cfg_t sched_cfg{}; + std::vector cells_cfg = get_default_cells_cfg(1); + sched_params schedparams{sched_cfg}; + schedparams.cells.emplace_back(0, cells_cfg[0], sched_cfg); + bwp_params bwp_cfg(cells_cfg[0], sched_cfg, 0, 0); + slot_ue_map_t slot_ues; + + ra_sched rasched(bwp_cfg); + TESTASSERT(rasched.empty()); + + std::unique_ptr res_grid(new bwp_res_grid{bwp_cfg}); + bwp_slot_allocator alloc(*res_grid); + + // Create UE + sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(1); + ue u(rnti, uecfg, schedparams); + + slot_point pdcch_slot{0, TX_ENB_DELAY}; + slot_point prach_slot{0, std::uniform_int_distribution{TX_ENB_DELAY, 20}(rgen)}; + + const bwp_slot_grid* result = nullptr; + auto run_slot = [&alloc, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* { + mac_logger.set_context(pdcch_slot.to_uint()); + slot_ues.clear(); + slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); + alloc.new_slot(pdcch_slot); + rasched.run_slot(alloc, slot_ues); + ++pdcch_slot; + return &alloc.res_grid()[alloc.get_pdcch_tti()]; + }; + + // Start Run + + for (; pdcch_slot - TX_ENB_DELAY < prach_slot;) { + result = run_slot(); + TESTASSERT(result->dl_pdcchs.empty()); + } + + sched_nr_interface::dl_sched_rar_info_t rainfo{}; + rainfo.preamble_idx = 10; + rainfo.temp_crnti = rnti; + rainfo.prach_slot = prach_slot; + rainfo.msg3_size = 7; + TESTASSERT_SUCCESS(rasched.dl_rach_info(rainfo)); + uint16_t ra_rnti = 1 + rainfo.ofdm_symbol_idx + 14 * rainfo.prach_slot.slot_idx() + 14 * 80 * rainfo.freq_idx; + + while (true) { + result = run_slot(); + if (result->is_dl()) { + TESTASSERT(result->dl_pdcchs.size() == 1); + const auto& pdcch = result->dl_pdcchs[0]; + TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); + TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); + break; + } else { + TESTASSERT(result->dl_pdcchs.empty()); + } + } +} + +} // namespace srsenb + +int main(int argc, char** argv) +{ + auto& test_logger = srslog::fetch_basic_logger("TEST"); + test_logger.set_level(srslog::basic_levels::info); + auto& mac_logger = srslog::fetch_basic_logger("MAC"); + mac_logger.set_level(srslog::basic_levels::info); + + srsran::test_init(argc, argv); + + srsenb::test_single_prach(); +} From 3d810bc88a6cea5cd616fcc2f2110d821b23b82e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 24 Aug 2021 16:53:19 +0200 Subject: [PATCH 18/56] sched,nr: fix RAR DCI values and extended RAR test --- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 4 +-- srsenb/test/mac/nr/CMakeLists.txt | 4 ++- srsenb/test/mac/nr/sched_nr_common_test.cc | 28 +++++++++++++++++++++ srsenb/test/mac/nr/sched_nr_common_test.h | 25 ++++++++++++++++++ srsenb/test/mac/nr/sched_nr_rar_test.cc | 8 +++++- 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 srsenb/test/mac/nr/sched_nr_common_test.cc create mode 100644 srsenb/test/mac/nr/sched_nr_common_test.h diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index f10dc5cdf..02ea342c5 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -49,7 +49,7 @@ bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params& bwp_c { dci.mcs = 5; dci.ctx.format = srsran_dci_format_nr_1_0; - dci.ctx.ss_type = srsran_search_space_type_rar; + dci.ctx.ss_type = srsran_search_space_type_common_1; dci.ctx.rnti_type = srsran_rnti_type_ra; dci.ctx.rnti = ra_rnti; dci.ctx.coreset_id = bwp_cfg.cfg.pdcch.ra_search_space.coreset_id; @@ -111,4 +111,4 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, } } // namespace sched_nr_impl -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index 9af588f18..b322a109e 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_library(sched_nr_test_suite sched_nr_common_test.cc sched_nr_ue_ded_test_suite.cc) + add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc sched_nr_ue_ded_test_suite.cc) target_link_libraries(sched_nr_test srsgnb_mac @@ -23,4 +25,4 @@ target_link_libraries(sched_nr_prb_test add_test(sched_nr_prb_test sched_nr_prb_test) add_executable(sched_nr_rar_test sched_nr_rar_test.cc) -target_link_libraries(sched_nr_rar_test srsgnb_mac srsran_common) \ No newline at end of file +target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_common_test.cc b/srsenb/test/mac/nr/sched_nr_common_test.cc new file mode 100644 index 000000000..07839bae6 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_common_test.cc @@ -0,0 +1,28 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "sched_nr_common_test.h" +#include "srsran/support/srsran_test.h" + +namespace srsenb { + +void test_pdcch_consistency(srsran::const_span dl_pdcchs) +{ + for (const auto& pdcch : dl_pdcchs) { + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { + TESTASSERT_EQ(pdcch.dci.ctx.format, srsran_dci_format_nr_1_0); + TESTASSERT_EQ(pdcch.dci.ctx.ss_type, srsran_search_space_type_common_1); + } + } +} + +} // namespace srsenb diff --git a/srsenb/test/mac/nr/sched_nr_common_test.h b/srsenb/test/mac/nr/sched_nr_common_test.h new file mode 100644 index 000000000..74b768311 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_common_test.h @@ -0,0 +1,25 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_COMMON_TEST_H +#define SRSRAN_SCHED_NR_COMMON_TEST_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsran/adt/span.h" + +namespace srsenb { + +void test_pdcch_consistency(srsran::const_span dl_pdcch); + +} + +#endif // SRSRAN_SCHED_NR_COMMON_TEST_H diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index cf9b5b431..d15346fad 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -11,6 +11,7 @@ */ #include "sched_nr_cfg_generators.h" +#include "sched_nr_common_test.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_cell.h" #include "srsran/common/test_common.h" #include "srsran/support/srsran_test.h" @@ -53,8 +54,10 @@ void test_single_prach() slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); alloc.new_slot(pdcch_slot); rasched.run_slot(alloc, slot_ues); + const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()]; + test_pdcch_consistency(result->dl_pdcchs); ++pdcch_slot; - return &alloc.res_grid()[alloc.get_pdcch_tti()]; + return result; }; // Start Run @@ -64,6 +67,7 @@ void test_single_prach() TESTASSERT(result->dl_pdcchs.empty()); } + // A PRACH arrives... sched_nr_interface::dl_sched_rar_info_t rainfo{}; rainfo.preamble_idx = 10; rainfo.temp_crnti = rnti; @@ -72,6 +76,7 @@ void test_single_prach() TESTASSERT_SUCCESS(rasched.dl_rach_info(rainfo)); uint16_t ra_rnti = 1 + rainfo.ofdm_symbol_idx + 14 * rainfo.prach_slot.slot_idx() + 14 * 80 * rainfo.freq_idx; + // RAR is scheduled while (true) { result = run_slot(); if (result->is_dl()) { @@ -79,6 +84,7 @@ void test_single_prach() const auto& pdcch = result->dl_pdcchs[0]; TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); + TESTASSERT(pdcch_slot < prach_slot + bwp_cfg.cell_cfg.bwps[0].rar_window_size); break; } else { TESTASSERT(result->dl_pdcchs.empty()); From 8f00c9363c58bf107ed48bcc8cde1b9a4bb7c1af Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 25 Aug 2021 11:57:11 +0200 Subject: [PATCH 19/56] sched,nr: change ra nr sched and bwp allocator interfaces --- srsenb/hdr/stack/mac/nr/sched_nr_cell.h | 8 +++----- srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h | 10 +++++++--- srsenb/src/stack/mac/nr/sched_nr_cell.cc | 14 ++++++-------- .../src/stack/mac/nr/sched_nr_grant_allocator.cc | 3 +-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 4 ++-- srsenb/test/mac/nr/sched_nr_common_test.cc | 1 + srsenb/test/mac/nr/sched_nr_rar_test.cc | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h index 5d5fc7776..addc017b6 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -54,7 +54,7 @@ public: explicit ra_sched(const bwp_params& bwp_cfg_); int dl_rach_info(const dl_sched_rar_info_t& rar_info); - void run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues); + void run_slot(bwp_slot_allocator& slot_grid); bool empty() const { return pending_rars.empty(); } private: @@ -65,10 +65,8 @@ private: srsran::bounded_vector msg3_grant; }; - alloc_result allocate_pending_rar(bwp_slot_allocator& slot_grid, - const pending_rar_t& rar, - slot_ue_map_t& slot_ues, - uint32_t& nof_grants_alloc); + alloc_result + allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc); const bwp_params* bwp_cfg = nullptr; srslog::basic_logger& logger; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index ee9aed46e..35d34c9e8 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -83,13 +83,16 @@ class bwp_slot_allocator public: explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_); - void new_slot(slot_point pdcch_slot_) { pdcch_slot = pdcch_slot_; } + void new_slot(slot_point pdcch_slot_, slot_ue_map_t& ues_) + { + pdcch_slot = pdcch_slot_; + slot_ues = &ues_; + } alloc_result alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs); alloc_result alloc_rar_and_msg3(uint16_t ra_rnti, uint32_t aggr_idx, prb_interval interv, - slot_ue_map_t& ues, srsran::const_span pending_rars); alloc_result alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant); alloc_result alloc_pusch(slot_ue& ue, const prb_grant& dl_mask); @@ -106,7 +109,8 @@ private: srslog::basic_logger& logger; bwp_res_grid& bwp_grid; - slot_point pdcch_slot; + slot_point pdcch_slot; + slot_ue_map_t* slot_ues; }; } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index 9eddfc0ed..7719d981b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -77,10 +77,8 @@ void si_sched::run_slot(bwp_slot_allocator& slot_alloc) ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {} -alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, - const pending_rar_t& rar, - slot_ue_map_t& slot_ues, - uint32_t& nof_grants_alloc) +alloc_result +ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) { const uint32_t rar_aggr_level = 2; const prb_bitmap& prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_prbs.prbs(); @@ -94,8 +92,8 @@ alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx); start_prb_idx = interv.start(); if (interv.length() == nprb) { - ret = slot_grid.alloc_rar_and_msg3( - rar.ra_rnti, rar_aggr_level, interv, slot_ues, msg3_grants.subspan(0, nof_grants_alloc)); + ret = + slot_grid.alloc_rar_and_msg3(rar.ra_rnti, rar_aggr_level, interv, msg3_grants.subspan(0, nof_grants_alloc)); } else { ret = alloc_result::no_sch_space; } @@ -112,7 +110,7 @@ alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, return ret; } -void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues) +void ra_sched::run_slot(bwp_slot_allocator& slot_grid) { slot_point pdcch_slot = slot_grid.get_pdcch_tti(); slot_point msg3_slot = pdcch_slot + bwp_cfg->pusch_ra_list[0].msg3_delay; @@ -145,7 +143,7 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues) // Try to schedule DCIs + RBGs for RAR Grants uint32_t nof_rar_allocs = 0; - alloc_result ret = allocate_pending_rar(slot_grid, rar, slot_ues, nof_rar_allocs); + alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs); if (ret == alloc_result::success) { // If RAR allocation was successful: diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index daffd30b3..28830ed5c 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -84,7 +84,6 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, ui alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t ra_rnti, uint32_t aggr_idx, prb_interval interv, - slot_ue_map_t& ues, srsran::const_span pending_rars) { static const uint32_t msg3_nof_prbs = 3, m = 0; @@ -148,7 +147,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t srsran_slot_cfg_t slot_cfg; slot_cfg.idx = msg3_slot.slot_idx(); for (const dl_sched_rar_info_t& grant : pending_rars) { - slot_ue& ue = ues[grant.temp_crnti]; + slot_ue& ue = (*slot_ues)[grant.temp_crnti]; // Allocate Msg3 prb_interval msg3_interv{last_msg3, last_msg3 + msg3_nof_prbs}; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 5364cf100..4a8bf1b08 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -91,10 +91,10 @@ void slot_cc_worker::run() { srsran_assert(running(), "scheduler worker::run() called for non-active worker"); - bwp_alloc.new_slot(slot_rx + TX_ENB_DELAY); + bwp_alloc.new_slot(slot_rx + TX_ENB_DELAY, slot_ues); // Allocate pending RARs - cell.bwps[0].ra.run_slot(bwp_alloc, slot_ues); + cell.bwps[0].ra.run_slot(bwp_alloc); // TODO: Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion alloc_dl_ues(); diff --git a/srsenb/test/mac/nr/sched_nr_common_test.cc b/srsenb/test/mac/nr/sched_nr_common_test.cc index 07839bae6..99488b470 100644 --- a/srsenb/test/mac/nr/sched_nr_common_test.cc +++ b/srsenb/test/mac/nr/sched_nr_common_test.cc @@ -21,6 +21,7 @@ void test_pdcch_consistency(srsran::const_span dl_pdc if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { TESTASSERT_EQ(pdcch.dci.ctx.format, srsran_dci_format_nr_1_0); TESTASSERT_EQ(pdcch.dci.ctx.ss_type, srsran_search_space_type_common_1); + TESTASSERT(pdcch.dci.ctx.location.L > 0); } } } diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index d15346fad..7c67c3a52 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -52,8 +52,8 @@ void test_single_prach() mac_logger.set_context(pdcch_slot.to_uint()); slot_ues.clear(); slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); - alloc.new_slot(pdcch_slot); - rasched.run_slot(alloc, slot_ues); + alloc.new_slot(pdcch_slot, slot_ues); + rasched.run_slot(alloc); const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()]; test_pdcch_consistency(result->dl_pdcchs); ++pdcch_slot; From da4b7e4f80806c35dc35a136981ef6386310ce39 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 25 Aug 2021 14:51:24 +0200 Subject: [PATCH 20/56] sched,nr: fix sched RAR NR test; update test assert macros --- lib/include/srsran/common/slot_point.h | 2 +- lib/include/srsran/support/srsran_test.h | 30 ++------ .../stack/mac/nr/sched_nr_grant_allocator.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr_helpers.h | 7 ++ srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 2 +- .../stack/mac/nr/sched_nr_grant_allocator.cc | 7 +- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 70 +++++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_worker.cc | 2 +- srsenb/test/mac/nr/sched_nr_rar_test.cc | 30 +++++--- 9 files changed, 114 insertions(+), 37 deletions(-) diff --git a/lib/include/srsran/common/slot_point.h b/lib/include/srsran/common/slot_point.h index d9abee2cc..3ab3f5348 100644 --- a/lib/include/srsran/common/slot_point.h +++ b/lib/include/srsran/common/slot_point.h @@ -157,7 +157,7 @@ struct formatter { template auto format(srsran::slot_point slot, FormatContext& ctx) -> decltype(std::declval().out()) { - return format_to(ctx.out(), "{}/{}", slot.sfn(), slot.slot_idx()); + return format_to(ctx.out(), "{}:{}", slot.sfn(), slot.slot_idx()); } }; } // namespace fmt diff --git a/lib/include/srsran/support/srsran_test.h b/lib/include/srsran/support/srsran_test.h index c247c69af..063ad9d1d 100644 --- a/lib/include/srsran/support/srsran_test.h +++ b/lib/include/srsran/support/srsran_test.h @@ -17,31 +17,15 @@ #include "srsran_assert.h" -namespace srsran { -namespace detail { - -template -[[gnu::noinline, noreturn]] void assert_eq_failure(const T& expected_val, const U& actual_val) -{ - std::string s = fmt::format("Actual value '{}' differs from expected '{}'", actual_val, expected_val); - srsran_assertion_failure("%s", s.c_str()); -} - -template -[[gnu::noinline, noreturn]] void assert_neq_failure(const T& actual_val) -{ - std::string s = fmt::format("Value should not be equal to '{}'", actual_val); - srsran_assertion_failure("%s", s.c_str()); -} - -} // namespace detail -} // namespace srsran - #define TESTASSERT_EQ(EXPECTED, ACTUAL) \ - (void)((EXPECTED == ACTUAL) || (::srsran::detail::assert_eq_failure(EXPECTED, ACTUAL), 0)) + (void)((EXPECTED == ACTUAL) || \ + (srsran_assertion_failure( \ + "%s", fmt::format("Actual value '{}' differs from expected '{}'", ACTUAL, EXPECTED).c_str()), \ + 0)) #define TESTASSERT_NEQ(EXPECTED, ACTUAL) \ - (void)((EXPECTED != ACTUAL) || (::srsran::detail::assert_neq_failure(ACTUAL), 0)) + (void)((EXPECTED != ACTUAL) || \ + (srsran_assertion_failure("%s", fmt::format("Value should not be equal to '{}'", ACTUAL).c_str()), 0)) #define TESTASSERT(cond) srsran_assert((cond), "Fail at \"%s\"", (#cond)) @@ -54,7 +38,7 @@ template #define TESTASSERT(cond) \ do { \ if (!(cond)) { \ - printf("[%s][Line %d] Fail at \"%s\"\n", __FUNCTION__, __LINE__, (#cond)); \ + fprintf(stderr, "%s:%d: Assertion Failure: \"%s\"\n", __FUNCTION__, __LINE__, (#cond)); \ return -1; \ } \ } while (0) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 35d34c9e8..0c4507d2d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -100,6 +100,7 @@ public: slot_point get_pdcch_tti() const { return pdcch_slot; } slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } const bwp_res_grid& res_grid() const { return bwp_grid; } + void log_bwp_sched_result(); const bwp_params& cfg; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h index baecb2f89..53ccc556f 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h @@ -14,12 +14,14 @@ #define SRSRAN_SCHED_NR_HELPERS_H #include "sched_nr_cfg.h" +#include "sched_nr_ue.h" namespace srsenb { namespace sched_nr_impl { class slot_ue; class ul_harq_proc; +struct bwp_res_grid; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -41,6 +43,11 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_location_t dci_pos, srsran_dci_ul_nr_t& dci); +void log_sched_bwp_result(srslog::basic_logger& logger, + slot_point pdcch_slot, + const bwp_res_grid& res_grid, + const slot_ue_map_t& slot_ues); + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 1ae357df2..7ffbbac2e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -54,7 +54,7 @@ public: srsran_pdcch_cfg_nr_t pdcch = {}; srsran_sch_hl_cfg_nr_t pdsch = {}; srsran_sch_hl_cfg_nr_t pusch = {}; - uint32_t rar_window_size = 8; + uint32_t rar_window_size = 10; // See TS 38.331, ra-ResponseWindow: {1, 2, 4, 8, 10, 20, 40, 80} uint32_t numerology_idx = 0; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index 28830ed5c..157f701df 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -341,5 +341,10 @@ alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, b return alloc_result::success; } +void bwp_slot_allocator::log_bwp_sched_result() +{ + log_sched_bwp_result(logger, get_pdcch_tti(), bwp_grid, *slot_ues); +} + } // namespace sched_nr_impl -} // namespace srsenb +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index 02ea342c5..f62430cca 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -11,8 +11,10 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" +#include "srsran/common/string_helpers.h" namespace srsenb { namespace sched_nr_impl { @@ -110,5 +112,73 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, fill_dci_common(ue, bwp_cfg, dci); } +void log_sched_bwp_result(srslog::basic_logger& logger, + slot_point pdcch_slot, + const bwp_res_grid& res_grid, + const slot_ue_map_t& slot_ues) +{ + const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot]; + for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) { + fmt::memory_buffer fmtbuf; + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to( + fmtbuf, + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, dai={}, tbs={}, pdsch_slot={}, tti_ack={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + res_grid.cfg->cc, + ue.rnti, + pdcch.dci.pid, + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.h_dl->nof_retx(), + pdcch.dci.dai, + ue.h_dl->tbs(), + ue.pdsch_slot, + ue.uci_slot); + } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { + fmt::format_to(fmtbuf, + "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, pdsch_slot={}, msg3_slot={}", + res_grid.cfg->cc, + pdcch.dci.ctx.rnti, + pdcch_slot, + pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay); + } else { + fmt::format_to(fmtbuf, "SCHED: unknown format"); + } + + logger.info("%s", srsran::to_c_str(fmtbuf)); + } + for (const pdcch_ul_t& pdcch : bwp_slot.ul_pdcchs) { + fmt::memory_buffer fmtbuf; + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to(fmtbuf, + "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, tbs={}, tti_pusch={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + res_grid.cfg->cc, + ue.rnti, + pdcch.dci.pid, + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.h_dl->nof_retx(), + ue.h_ul->tbs(), + ue.pusch_slot); + } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_tc) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to(fmtbuf, + "SCHED: UL Msg3, cc={}, tc-rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}", + res_grid.cfg->cc, + ue.rnti, + pdcch.dci.pid, + ue.h_dl->nof_retx(), + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.pusch_slot); + } else { + fmt::format_to(fmtbuf, "SCHED: unknown rnti format"); + } + + logger.info("%s", srsran::to_c_str(fmtbuf)); + } +} + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 4a8bf1b08..0c753ca23 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -101,7 +101,7 @@ void slot_cc_worker::run() alloc_ul_ues(); // Log CC scheduler result - log_result(); + bwp_alloc.log_bwp_sched_result(); // releases UE resources slot_ues.clear(); diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index 7c67c3a52..cf15a8c21 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -17,6 +17,9 @@ #include "srsran/support/srsran_test.h" #include +uint32_t seed = 155556739; +// std::chrono::system_clock::now().time_since_epoch().count(); + namespace srsenb { void test_single_prach() @@ -24,20 +27,20 @@ void test_single_prach() using namespace sched_nr_impl; const uint16_t rnti = 0x1234; static srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC"); - std::random_device r; - std::default_random_engine rgen(r()); + std::default_random_engine rand_gen(seed); + std::default_random_engine rgen(rand_gen()); sched_nr_interface::sched_cfg_t sched_cfg{}; std::vector cells_cfg = get_default_cells_cfg(1); sched_params schedparams{sched_cfg}; schedparams.cells.emplace_back(0, cells_cfg[0], sched_cfg); - bwp_params bwp_cfg(cells_cfg[0], sched_cfg, 0, 0); - slot_ue_map_t slot_ues; + const bwp_params& bwpparams = schedparams.cells[0].bwps[0]; + slot_ue_map_t slot_ues; - ra_sched rasched(bwp_cfg); + ra_sched rasched(bwpparams); TESTASSERT(rasched.empty()); - std::unique_ptr res_grid(new bwp_res_grid{bwp_cfg}); + std::unique_ptr res_grid(new bwp_res_grid{bwpparams}); bwp_slot_allocator alloc(*res_grid); // Create UE @@ -54,6 +57,8 @@ void test_single_prach() slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); alloc.new_slot(pdcch_slot, slot_ues); rasched.run_slot(alloc); + + alloc.log_bwp_sched_result(); const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()]; test_pdcch_consistency(result->dl_pdcchs); ++pdcch_slot; @@ -77,14 +82,17 @@ void test_single_prach() uint16_t ra_rnti = 1 + rainfo.ofdm_symbol_idx + 14 * rainfo.prach_slot.slot_idx() + 14 * 80 * rainfo.freq_idx; // RAR is scheduled + const uint32_t prach_duration = 1; while (true) { - result = run_slot(); - if (result->is_dl()) { - TESTASSERT(result->dl_pdcchs.size() == 1); + slot_point current_slot = pdcch_slot; + result = run_slot(); + if (bwpparams.slots[current_slot.slot_idx()].is_dl and + bwpparams.slots[(current_slot + bwpparams.pusch_ra_list[0].msg3_delay).slot_idx()].is_ul) { + TESTASSERT_EQ(result->dl_pdcchs.size(), 1); const auto& pdcch = result->dl_pdcchs[0]; TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); - TESTASSERT(pdcch_slot < prach_slot + bwp_cfg.cell_cfg.bwps[0].rar_window_size); + TESTASSERT(current_slot < prach_slot + prach_duration + bwpparams.cfg.rar_window_size); break; } else { TESTASSERT(result->dl_pdcchs.empty()); @@ -103,5 +111,7 @@ int main(int argc, char** argv) srsran::test_init(argc, argv); + printf("Test seed=%u\n", seed); + srsenb::test_single_prach(); } From 8686a17f69147c957d3b4724dee1ff30c16eb985 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 25 Aug 2021 17:18:31 +0200 Subject: [PATCH 21/56] sched,nr: fill remaining DCI fields of RAR in NR scheduler --- .../stack/mac/nr/sched_nr_grant_allocator.cc | 25 ++++++++++++------- srsenb/test/mac/nr/CMakeLists.txt | 3 ++- srsenb/test/mac/nr/sched_nr_common_test.cc | 16 +++++++++++- srsenb/test/mac/nr/sched_nr_common_test.h | 5 ++-- srsenb/test/mac/nr/sched_nr_rar_test.cc | 16 +++++++++--- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 7 ++++++ .../test/mac/nr/sched_nr_ue_ded_test_suite.cc | 8 ------ 7 files changed, 55 insertions(+), 25 deletions(-) diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index 157f701df..50f43020e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -129,7 +129,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t } // RAR allocation successful. - + bwp_pdcch_slot.dl_prbs |= interv; // Generate DCI for RAR with given RA-RNTI pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch.dci)) { @@ -137,22 +137,29 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); return alloc_result::invalid_coderate; } + auto& phy_cfg = (*slot_ues)[pending_rars[0].temp_crnti].cfg->phy(); + pdcch.dci_cfg = phy_cfg.get_dci_cfg(); // Generate RAR PDSCH - bwp_pdcch_slot.dl_prbs |= interv; + // TODO: Properly fill Msg3 grants + bwp_pdcch_slot.pdschs.emplace_back(); + pdsch_t& pdsch = bwp_pdcch_slot.pdschs.back(); + srsran_slot_cfg_t slot_cfg; + slot_cfg.idx = pdcch_slot.slot_idx(); + bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); + srsran_assert(success, "Error converting DCI to grant"); // Generate Msg3 grants in PUSCH - uint32_t last_msg3 = msg3_rbs.start(); - const int mcs = 0, max_harq_msg3_retx = 4; - int dai = 0; - srsran_slot_cfg_t slot_cfg; - slot_cfg.idx = msg3_slot.slot_idx(); + uint32_t last_msg3 = msg3_rbs.start(); + const int mcs = 0, max_harq_msg3_retx = 4; + int dai = 0; + slot_cfg.idx = msg3_slot.slot_idx(); for (const dl_sched_rar_info_t& grant : pending_rars) { slot_ue& ue = (*slot_ues)[grant.temp_crnti]; // Allocate Msg3 prb_interval msg3_interv{last_msg3, last_msg3 + msg3_nof_prbs}; - ue.h_ul = ue.harq_ent->find_empty_ul_harq(); - bool success = ue.h_ul->new_tx(msg3_slot, msg3_slot, msg3_interv, mcs, 100, max_harq_msg3_retx); + ue.h_ul = ue.harq_ent->find_empty_ul_harq(); + success = ue.h_ul->new_tx(msg3_slot, msg3_slot, msg3_interv, mcs, 100, max_harq_msg3_retx); srsran_assert(success, "Failed to allocate Msg3"); last_msg3 += msg3_nof_prbs; pdcch_ul_t msg3_pdcch; // dummy PDCCH for retx=0 diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index b322a109e..bc7f221d5 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -8,9 +8,10 @@ add_library(sched_nr_test_suite sched_nr_common_test.cc sched_nr_ue_ded_test_suite.cc) -add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc sched_nr_ue_ded_test_suite.cc) +add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc) target_link_libraries(sched_nr_test srsgnb_mac + sched_nr_test_suite srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) diff --git a/srsenb/test/mac/nr/sched_nr_common_test.cc b/srsenb/test/mac/nr/sched_nr_common_test.cc index 99488b470..bc2caf63c 100644 --- a/srsenb/test/mac/nr/sched_nr_common_test.cc +++ b/srsenb/test/mac/nr/sched_nr_common_test.cc @@ -15,13 +15,27 @@ namespace srsenb { -void test_pdcch_consistency(srsran::const_span dl_pdcchs) +void test_dl_pdcch_consistency(srsran::const_span dl_pdcchs) { for (const auto& pdcch : dl_pdcchs) { if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { TESTASSERT_EQ(pdcch.dci.ctx.format, srsran_dci_format_nr_1_0); TESTASSERT_EQ(pdcch.dci.ctx.ss_type, srsran_search_space_type_common_1); TESTASSERT(pdcch.dci.ctx.location.L > 0); + } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + TESTASSERT(pdcch.dci.ctx.format == srsran_dci_format_nr_1_0 or pdcch.dci.ctx.format == srsran_dci_format_nr_1_1); + } + } +} + +void test_pdsch_consistency(srsran::const_span pdschs) +{ + for (const mac_interface_phy_nr::pdsch_t& pdsch : pdschs) { + TESTASSERT(pdsch.sch.grant.nof_layers > 0); + if (pdsch.sch.grant.rnti_type == srsran_rnti_type_c) { + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx != nullptr); + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->buffer_b != nullptr); + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->max_cb > 0); } } } diff --git a/srsenb/test/mac/nr/sched_nr_common_test.h b/srsenb/test/mac/nr/sched_nr_common_test.h index 74b768311..a179c5998 100644 --- a/srsenb/test/mac/nr/sched_nr_common_test.h +++ b/srsenb/test/mac/nr/sched_nr_common_test.h @@ -18,8 +18,9 @@ namespace srsenb { -void test_pdcch_consistency(srsran::const_span dl_pdcch); +void test_dl_pdcch_consistency(srsran::const_span dl_pdcch); +void test_pdsch_consistency(srsran::const_span dl_pdcch); -} +} // namespace srsenb #endif // SRSRAN_SCHED_NR_COMMON_TEST_H diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index cf15a8c21..e6edac3ea 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -17,8 +17,7 @@ #include "srsran/support/srsran_test.h" #include -uint32_t seed = 155556739; -// std::chrono::system_clock::now().time_since_epoch().count(); +uint32_t seed = std::chrono::system_clock::now().time_since_epoch().count(); namespace srsenb { @@ -53,6 +52,7 @@ void test_single_prach() const bwp_slot_grid* result = nullptr; auto run_slot = [&alloc, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* { mac_logger.set_context(pdcch_slot.to_uint()); + u.carriers[0]->new_slot(pdcch_slot, u.cfg()); slot_ues.clear(); slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); alloc.new_slot(pdcch_slot, slot_ues); @@ -60,7 +60,7 @@ void test_single_prach() alloc.log_bwp_sched_result(); const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()]; - test_pdcch_consistency(result->dl_pdcchs); + test_dl_pdcch_consistency(result->dl_pdcchs); ++pdcch_slot; return result; }; @@ -83,6 +83,7 @@ void test_single_prach() // RAR is scheduled const uint32_t prach_duration = 1; + slot_point rar_slot; while (true) { slot_point current_slot = pdcch_slot; result = run_slot(); @@ -93,11 +94,18 @@ void test_single_prach() TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); TESTASSERT(current_slot < prach_slot + prach_duration + bwpparams.cfg.rar_window_size); + rar_slot = current_slot; break; } else { TESTASSERT(result->dl_pdcchs.empty()); } } + + slot_point msg3_slot = rar_slot + bwpparams.pusch_ra_list[0].msg3_delay; + while (pdcch_slot <= msg3_slot) { + result = run_slot(); + } + TESTASSERT(result->puschs.size() == 1); } } // namespace srsenb @@ -111,7 +119,7 @@ int main(int argc, char** argv) srsran::test_init(argc, argv); - printf("Test seed=%u\n", seed); + printf("Test random seed=%u\n\n", seed); srsenb::test_single_prach(); } diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index cb619aee8..9eaef18ae 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -11,6 +11,7 @@ */ #include "sched_nr_sim_ue.h" +#include "sched_nr_common_test.h" #include "sched_nr_ue_ded_test_suite.h" #include "srsran/common/test_common.h" @@ -157,6 +158,12 @@ void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out) sim_nr_enb_ctxt_t ctxt; ctxt = get_enb_ctxt(); + + // Run common tests + test_dl_pdcch_consistency(cc_out.dl_cc_result->pdcch_dl); + test_pdsch_consistency(cc_out.dl_cc_result->pdsch); + + // Run UE-dedicated tests test_dl_sched_result(ctxt, cc_out); for (auto& u : ue_db) { diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc index ecf656dfa..cc434508a 100644 --- a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc @@ -22,7 +22,6 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o { slot_point pdcch_slot = cc_out.slot; const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl; - const pdsch_list_t& pdschs = cc_out.dl_cc_result->pdsch; // Iterate over UE PDCCH allocations for (const pdcch_dl_t& pdcch : pdcchs) { @@ -40,7 +39,6 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o TESTASSERT(ue.ue_cfg.phy_cfg.pdcch.coreset_present[pdcch.dci.ctx.coreset_id]); const auto& coreset = ue.ue_cfg.phy_cfg.pdcch.coreset[pdcch.dci.ctx.coreset_id]; TESTASSERT(coreset.id == pdcch.dci.ctx.coreset_id); - TESTASSERT(pdcch.dci.ctx.format == srsran_dci_format_nr_1_0 or pdcch.dci.ctx.format == srsran_dci_format_nr_1_1); // CHECK: UCI if (pdcch.dci.ctx.format == srsran_dci_format_nr_1_0) { @@ -50,12 +48,6 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o } TESTASSERT(ue.cc_list[cc_out.cc].pending_acks[(pdcch_slot + k1).to_uint()] % 4 == pdcch.dci.dai); } - - for (const pdsch_t& pdsch : pdschs) { - TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx != nullptr); - TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->buffer_b != nullptr); - TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->max_cb > 0); - } } } // namespace srsenb From b486d2a1b535780fbacd80109841f7081b8efbbd Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 25 Aug 2021 18:13:26 +0200 Subject: [PATCH 22/56] sched,nr: implement prb grant fmt formatting --- lib/src/phy/phch/ra_dl_nr.c | 3 +- srsenb/hdr/stack/mac/nr/sched_nr_rb.h | 17 ++++++ srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 1 - srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 34 +++++++----- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 60 --------------------- srsenb/test/mac/nr/CMakeLists.txt | 3 +- srsenb/test/mac/nr/sched_nr_prb_test.cc | 4 ++ srsenb/test/mac/nr/sched_nr_test.cc | 4 +- 8 files changed, 47 insertions(+), 79 deletions(-) diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index 7665370e6..f6aebb3a3 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -339,4 +339,5 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier, uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t length_rb) { return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb); -} \ No newline at end of file +} + diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h index e1030bbfb..9ccf1d251 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h @@ -234,4 +234,21 @@ inline prb_interval find_empty_interval_of_length(const prb_bitmap& mask, size_t } // namespace sched_nr_impl } // namespace srsenb +namespace fmt { + +template <> +struct formatter : public formatter { + template + auto format(const srsenb::sched_nr_impl::prb_grant& grant, FormatContext& ctx) + -> decltype(std::declval().out()) + { + if (grant.is_alloc_type1()) { + return formatter >{}.format(grant.prbs(), ctx); + } + return formatter::format(grant.rbgs(), ctx); + } +}; + +} // namespace fmt + #endif // SRSRAN_SCHED_NR_RB_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 532812946..ccbb9ded0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -53,7 +53,6 @@ private: void alloc_dl_ues(); void alloc_ul_ues(); - void log_result() const; const sched_cell_params& cfg; serv_cell_manager& cell; diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index f62430cca..31c7ff774 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -122,24 +122,30 @@ void log_sched_bwp_result(srslog::basic_logger& logger, fmt::memory_buffer fmtbuf; if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; - fmt::format_to( - fmtbuf, - "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, dai={}, tbs={}, pdsch_slot={}, tti_ack={}", - ue.h_dl->nof_retx() == 0 ? "tx" : "retx", - res_grid.cfg->cc, - ue.rnti, - pdcch.dci.pid, - srsran_dci_format_nr_string(pdcch.dci.ctx.format), - ue.h_dl->nof_retx(), - pdcch.dci.dai, - ue.h_dl->tbs(), - ue.pdsch_slot, - ue.uci_slot); + fmt::format_to(fmtbuf, + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, grant={}, nrtx={}, dai={}, tbs={}, " + "pdsch_slot={}, tti_ack={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + res_grid.cfg->cc, + ue.rnti, + pdcch.dci.pid, + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.h_dl->prbs(), + ue.h_dl->nof_retx(), + pdcch.dci.dai, + ue.h_dl->tbs(), + ue.pdsch_slot, + ue.uci_slot); } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { + const pdsch_t& pdsch = bwp_slot.pdschs[std::distance(bwp_slot.dl_pdcchs.data(), &pdcch)]; + srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb}; + uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); + uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false)); fmt::format_to(fmtbuf, - "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, pdsch_slot={}, msg3_slot={}", + "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, grant={}, pdsch_slot={}, msg3_slot={}", res_grid.cfg->cc, pdcch.dci.ctx.rnti, + srsran::interval{start_idx, end_idx}, pdcch_slot, pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay); } else { diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 0c753ca23..e3e119659 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -129,66 +129,6 @@ void slot_cc_worker::alloc_ul_ues() cell.bwps[0].data_sched->sched_ul_users(slot_ues, bwp_alloc); } -void slot_cc_worker::log_result() const -{ - const bwp_slot_grid& bwp_slot = cell.bwps[0].grid[slot_rx + TX_ENB_DELAY]; - for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) { - fmt::memory_buffer fmtbuf; - if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { - const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; - fmt::format_to( - fmtbuf, - "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, dai={}, tbs={}, tti_pdsch={}, tti_ack={}", - ue.h_dl->nof_retx() == 0 ? "tx" : "retx", - cell.cfg.cc, - ue.rnti, - pdcch.dci.pid, - srsran_dci_format_nr_string(pdcch.dci.ctx.format), - ue.h_dl->nof_retx(), - pdcch.dci.dai, - ue.h_dl->tbs(), - ue.pdsch_slot, - ue.uci_slot); - } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { - fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}", cell.cfg.cc, pdcch.dci.ctx.rnti); - } else { - fmt::format_to(fmtbuf, "SCHED: unknown format"); - } - - logger.info("%s", srsran::to_c_str(fmtbuf)); - } - for (const pdcch_ul_t& pdcch : bwp_slot.ul_pdcchs) { - fmt::memory_buffer fmtbuf; - if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { - const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; - fmt::format_to(fmtbuf, - "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, tbs={}, tti_pusch={}", - ue.h_dl->nof_retx() == 0 ? "tx" : "retx", - cell.cfg.cc, - ue.rnti, - pdcch.dci.pid, - srsran_dci_format_nr_string(pdcch.dci.ctx.format), - ue.h_dl->nof_retx(), - ue.h_ul->tbs(), - ue.pusch_slot); - } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_tc) { - const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; - fmt::format_to(fmtbuf, - "SCHED: UL Msg3, cc={}, tc-rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}", - cell.cfg.cc, - ue.rnti, - pdcch.dci.pid, - ue.h_dl->nof_retx(), - srsran_dci_format_nr_string(pdcch.dci.ctx.format), - ue.pusch_slot); - } else { - fmt::format_to(fmtbuf, "SCHED: unknown rnti format"); - } - - logger.info("%s", srsran::to_c_str(fmtbuf)); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index bc7f221d5..87d48d68c 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -26,4 +26,5 @@ target_link_libraries(sched_nr_prb_test add_test(sched_nr_prb_test sched_nr_prb_test) add_executable(sched_nr_rar_test sched_nr_rar_test.cc) -target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) \ No newline at end of file +target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) +add_test(sched_nr_rar_test sched_nr_rar_test) \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_prb_test.cc b/srsenb/test/mac/nr/sched_nr_prb_test.cc index 71bc78776..25d3c65d4 100644 --- a/srsenb/test/mac/nr/sched_nr_prb_test.cc +++ b/srsenb/test/mac/nr/sched_nr_prb_test.cc @@ -49,6 +49,10 @@ void test_bwp_prb_grant() TESTASSERT(grant.is_alloc_type0() and grant.rbgs().count() == 1); grant = grant2; TESTASSERT(grant.is_alloc_type1() and grant.prbs().length() == 3); + + // TEST: formatting + TESTASSERT_EQ("[2, 5)", fmt::format("{}", grant2)); + TESTASSERT_EQ("0x10000", fmt::format("0x{:x}", grant3)); } void test_bwp_rb_bitmap() diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index fbf8faa80..4fd125e37 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -179,9 +179,9 @@ void sched_nr_cfg_parallel_cc_test() int main() { auto& test_logger = srslog::fetch_basic_logger("TEST"); - test_logger.set_level(srslog::basic_levels::warning); + test_logger.set_level(srslog::basic_levels::info); auto& mac_logger = srslog::fetch_basic_logger("MAC"); - mac_logger.set_level(srslog::basic_levels::warning); + mac_logger.set_level(srslog::basic_levels::info); auto& pool_logger = srslog::fetch_basic_logger("POOL"); pool_logger.set_level(srslog::basic_levels::info); From 05a5f4115f91891bd4f0099283d8187464d2db3c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 26 Aug 2021 14:58:40 +0200 Subject: [PATCH 23/56] sched,nr: extended sched nr DL output to account for RAR content and assist with RAR encoding in the mac_nr class --- srsenb/hdr/stack/mac/mac_nr.h | 3 ++ srsenb/hdr/stack/mac/nr/sched_nr.h | 2 +- .../stack/mac/nr/sched_nr_grant_allocator.h | 2 + srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 23 +++++++-- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 9 ++-- srsenb/src/stack/mac/nr/mac_nr.cc | 51 ++++++++++++------- srsenb/src/stack/mac/nr/sched_nr.cc | 18 +++---- .../stack/mac/nr/sched_nr_grant_allocator.cc | 9 ++++ srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 15 +++--- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 18 ++++--- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 12 ++--- srsenb/test/mac/nr/sched_nr_sim_ue.h | 8 +-- srsenb/test/mac/nr/sched_nr_test.cc | 23 +++++---- .../test/mac/nr/sched_nr_ue_ded_test_suite.cc | 2 +- test/phy/dummy_gnb_stack.h | 4 +- 15 files changed, 128 insertions(+), 71 deletions(-) diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 006545dec..e55f5361a 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -81,6 +81,9 @@ private: // PDU processing int handle_pdu(srsran::unique_byte_buffer_t pdu); + // Encoding + srsran::byte_buffer_t* assemble_rar(srsran::const_span grants); + // Interaction with other components phy_interface_stack_nr* phy = nullptr; stack_interface_mac* stack = nullptr; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index b48675036..a62311ab6 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -47,7 +47,7 @@ public: void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override; void ul_sr_info(slot_point slot_rx, uint16_t rnti) override; - int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_t& result) override; + int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_res_t& result) override; int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) override; private: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 0c4507d2d..872069f35 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -32,6 +32,7 @@ using slot_coreset_list = std::array; +using rar_list_t = sched_nr_interface::sched_rar_list_t; struct harq_ack_t { const srsran::phy_cfg_nr_t* phy_cfg; @@ -48,6 +49,7 @@ struct bwp_slot_grid { pdcch_dl_list_t dl_pdcchs; pdcch_ul_list_t ul_pdcchs; pdsch_list_t pdschs; + rar_list_t rar; slot_coreset_list coresets; pusch_list_t puschs; harq_ack_list_t pending_acks; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 7ffbbac2e..ef6aa3b89 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -100,11 +100,24 @@ public: using dl_sched_t = mac_interface_phy_nr::dl_sched_t; using ul_sched_t = mac_interface_phy_nr::ul_sched_t; - virtual ~sched_nr_interface() = default; - virtual int cell_cfg(srsran::const_span ue_cfg) = 0; - virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; - virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_t& result) = 0; - virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0; + struct sched_rar_grant_t { + dl_sched_rar_info_t data; + srsran_dci_rar_grant_t grant = {}; + }; + struct sched_rar_t { + srsran::bounded_vector grants; + }; + using sched_rar_list_t = srsran::bounded_vector; + struct dl_sched_res_t { + sched_rar_list_t rar; + dl_sched_t dl_sched; + }; + + virtual ~sched_nr_interface() = default; + virtual int cell_cfg(srsran::const_span ue_cfg) = 0; + virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; + virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0; + virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index ccbb9ded0..6ed470fc0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -27,8 +27,9 @@ namespace srsenb { namespace sched_nr_impl { -using dl_sched_t = sched_nr_interface::dl_sched_t; -using ul_sched_t = sched_nr_interface::ul_sched_t; +using dl_sched_t = sched_nr_interface::dl_sched_t; +using ul_sched_t = sched_nr_interface::ul_sched_t; +using dl_sched_res_t = sched_nr_interface::dl_sched_res_t; class slot_cc_worker { @@ -92,7 +93,7 @@ public: sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); - void run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); + void run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res); void enqueue_event(uint16_t rnti, srsran::move_callback ev); void enqueue_cc_event(uint32_t cc, srsran::move_callback ev); @@ -102,7 +103,7 @@ public: } private: - bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); + bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res); const sched_params& cfg; ue_map_t& ue_db; diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 6bd12f247..959930e85 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -265,23 +265,35 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched pdsch_slot++; } - int ret = sched.get_dl_sched(pdsch_slot, 0, dl_sched); - for (pdsch_t& pdsch : dl_sched.pdsch) { - for (auto& tb_data : pdsch.data) { - if (tb_data != nullptr) { - // TODO: exclude retx from packing - uint16_t rnti = pdsch.sch.grant.rnti; - srsran::rwlock_read_guard rw_lock(rwlock); - if (not is_rnti_active_unsafe(rnti)) { - continue; - } - ue_db[rnti]->generate_pdu(tb_data, pdsch.sch.grant.tb->tbs / 8); + sched_nr_interface::dl_sched_res_t dl_res; + int ret = sched.get_dl_sched(pdsch_slot, 0, dl_res); + if (ret != SRSRAN_SUCCESS) { + return ret; + } + dl_sched = dl_res.dl_sched; - if (pcap != nullptr) { - uint32_t pid = 0; // TODO: get PID from PDCCH struct? - pcap->write_dl_crnti_nr(tb_data->msg, tb_data->N_bytes, rnti, pid, slot_cfg.idx); + uint32_t rar_count = 0; + srsran::rwlock_read_guard rw_lock(rwlock); + for (pdsch_t& pdsch : dl_sched.pdsch) { + if (pdsch.sch.grant.rnti_type == srsran_rnti_type_c) { + uint16_t rnti = pdsch.sch.grant.rnti; + if (not is_rnti_active_unsafe(rnti)) { + continue; + } + for (auto& tb_data : pdsch.data) { + if (tb_data != nullptr) { + // TODO: exclude retx from packing + ue_db[rnti]->generate_pdu(tb_data, pdsch.sch.grant.tb->tbs / 8); + + if (pcap != nullptr) { + uint32_t pid = 0; // TODO: get PID from PDCCH struct? + pcap->write_dl_crnti_nr(tb_data->msg, tb_data->N_bytes, rnti, pid, slot_cfg.idx); + } } } + } else if (pdsch.sch.grant.rnti_type == srsran_rnti_type_ra) { + sched_nr_interface::sched_rar_t& rar = dl_res.rar[rar_count++]; + pdsch.data[0] = assemble_rar(rar.grants); } } return SRSRAN_SUCCESS; @@ -307,11 +319,11 @@ int mac_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph return SRSRAN_SUCCESS; } -bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value) +bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg_, const srsran_uci_value_nr_t& value) { // Process HARQ-ACK - for (uint32_t i = 0; i < cfg.ack.count; i++) { - const srsran_harq_ack_bit_t* ack_bit = &cfg.ack.bits[i]; + for (uint32_t i = 0; i < cfg_.ack.count; i++) { + const srsran_harq_ack_bit_t* ack_bit = &cfg_.ack.bits[i]; bool is_ok = (value.ack[i] == 1) and value.valid; sched.dl_ack_info(rnti, 0, ack_bit->pid, 0, is_ok); } @@ -351,4 +363,9 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr:: return SRSRAN_SUCCESS; } +srsran::byte_buffer_t* mac_nr::assemble_rar(srsran::const_span grants) +{ + return nullptr; +} + } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 0b6232b97..9dc058e94 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -34,7 +34,7 @@ public: } } - dl_sched_t& add_dl_result(slot_point tti, uint32_t cc) + dl_sched_res_t& add_dl_result(slot_point tti, uint32_t cc) { if (not has_dl_result(tti, cc)) { results[tti.to_uint()][cc].slot_dl = tti; @@ -55,7 +55,7 @@ public: bool has_ul_result(slot_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].slot_ul == tti; } - dl_sched_t pop_dl_result(slot_point tti, uint32_t cc) + dl_sched_res_t pop_dl_result(slot_point tti, uint32_t cc) { if (has_dl_result(tti, cc)) { results[tti.to_uint()][cc].slot_dl.clear(); @@ -75,10 +75,10 @@ public: private: struct slot_result_t { - slot_point slot_dl; - slot_point slot_ul; - dl_sched_t dl_res; - ul_sched_t ul_res; + slot_point slot_dl; + slot_point slot_ul; + dl_sched_res_t dl_res; + ul_sched_t ul_res; }; srsran::circular_array, TTIMOD_SZ> results; @@ -129,8 +129,8 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) int sched_nr::generate_slot_result(slot_point pdcch_tti, uint32_t cc) { // Copy results to intermediate buffer - dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); - ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); + dl_sched_res_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); + ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); // Generate {slot_idx,cc} result sched_workers->run_slot(pdcch_tti, cc, dl_res, ul_res); @@ -138,7 +138,7 @@ int sched_nr::generate_slot_result(slot_point pdcch_tti, uint32_t cc) return SRSRAN_SUCCESS; } -int sched_nr::get_dl_sched(slot_point slot_tx, uint32_t cc, dl_sched_t& result) +int sched_nr::get_dl_sched(slot_point slot_tx, uint32_t cc, dl_sched_res_t& result) { if (not pending_results->has_dl_result(slot_tx, cc)) { generate_slot_result(slot_tx, cc); diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index 50f43020e..d4109f096 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -153,6 +153,8 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t const int mcs = 0, max_harq_msg3_retx = 4; int dai = 0; slot_cfg.idx = msg3_slot.slot_idx(); + bwp_pdcch_slot.rar.emplace_back(); + sched_nr_interface::sched_rar_t& rar_out = bwp_pdcch_slot.rar.back(); for (const dl_sched_rar_info_t& grant : pending_rars) { slot_ue& ue = (*slot_ues)[grant.temp_crnti]; @@ -166,6 +168,13 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t fill_dci_msg3(ue, *bwp_grid.cfg, msg3_pdcch.dci); msg3_pdcch.dci.time_domain_assigment = dai++; + // Generate RAR grant + rar_out.grants.emplace_back(); + auto& rar_grant = rar_out.grants.back(); + rar_grant.data = grant; + rar_grant.grant.rba = msg3_pdcch.dci.freq_domain_assigment; + rar_grant.grant.trunc_mcs = msg3_pdcch.dci.mcs; + // Generate PUSCH bwp_msg3_slot.puschs.emplace_back(); pusch_t& pusch = bwp_msg3_slot.puschs.back(); diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index 31c7ff774..658f0baf0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -117,13 +117,14 @@ void log_sched_bwp_result(srslog::basic_logger& logger, const bwp_res_grid& res_grid, const slot_ue_map_t& slot_ues) { - const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot]; + const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot]; + size_t rar_count = 0; for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) { fmt::memory_buffer fmtbuf; if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; fmt::format_to(fmtbuf, - "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, grant={}, nrtx={}, dai={}, tbs={}, " + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, prbs={}, nrtx={}, dai={}, tbs={}, " "pdsch_slot={}, tti_ack={}", ue.h_dl->nof_retx() == 0 ? "tx" : "retx", res_grid.cfg->cc, @@ -137,17 +138,19 @@ void log_sched_bwp_result(srslog::basic_logger& logger, ue.pdsch_slot, ue.uci_slot); } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { - const pdsch_t& pdsch = bwp_slot.pdschs[std::distance(bwp_slot.dl_pdcchs.data(), &pdcch)]; + const pdsch_t& pdsch = bwp_slot.pdschs[std::distance(bwp_slot.dl_pdcchs.data(), &pdcch)]; srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb}; - uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); + uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false)); fmt::format_to(fmtbuf, - "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, grant={}, pdsch_slot={}, msg3_slot={}", + "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, prbs={}, pdsch_slot={}, msg3_slot={}, nof_grants={}", res_grid.cfg->cc, pdcch.dci.ctx.rnti, srsran::interval{start_idx, end_idx}, pdcch_slot, - pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay); + pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay, + bwp_slot.rar[rar_count].grants.size()); + rar_count++; } else { fmt::format_to(fmtbuf, "SCHED: unknown format"); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index e3e119659..63ad19e58 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -155,7 +155,7 @@ void sched_worker_manager::enqueue_cc_event(uint32_t cc, srsran::move_callbackworker.enqueue_cc_event(std::move(ev)); } -void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) +void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res) { srsran::bounded_vector waiting_cvars; { @@ -238,19 +238,23 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t& } } - // Copy results to intermediate buffer + // Post-process and copy results to intermediate buffer save_sched_result(slot_tx, cc, dl_res, ul_res); } -bool sched_worker_manager::save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) +bool sched_worker_manager::save_sched_result(slot_point pdcch_slot, + uint32_t cc, + dl_sched_res_t& dl_res, + ul_sched_t& ul_res) { // NOTE: Unlocked region auto& bwp_slot = cells[cc]->bwps[0].grid[pdcch_slot]; - dl_res.pdcch_dl = bwp_slot.dl_pdcchs; - dl_res.pdcch_ul = bwp_slot.ul_pdcchs; - dl_res.pdsch = bwp_slot.pdschs; - ul_res.pusch = bwp_slot.puschs; + dl_res.dl_sched.pdcch_dl = bwp_slot.dl_pdcchs; + dl_res.dl_sched.pdcch_ul = bwp_slot.ul_pdcchs; + dl_res.dl_sched.pdsch = bwp_slot.pdschs; + dl_res.rar = bwp_slot.rar; + ul_res.pusch = bwp_slot.puschs; // Group pending HARQ ACKs srsran_pdsch_ack_nr_t ack = {}; diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index 9eaef18ae..89287467f 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -41,8 +41,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) { update_dl_harqs(cc_out); - for (uint32_t i = 0; i < cc_out.dl_cc_result->pdcch_dl.size(); ++i) { - const auto& data = cc_out.dl_cc_result->pdcch_dl[i]; + for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) { + const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i]; if (data.dci.ctx.rnti != ctxt.rnti) { continue; } @@ -63,8 +63,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) { uint32_t cc = cc_out.cc; - for (uint32_t i = 0; i < cc_out.dl_cc_result->pdcch_dl.size(); ++i) { - const auto& data = cc_out.dl_cc_result->pdcch_dl[i]; + for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) { + const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i]; if (data.dci.ctx.rnti != ctxt.rnti) { continue; } @@ -160,8 +160,8 @@ void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out) ctxt = get_enb_ctxt(); // Run common tests - test_dl_pdcch_consistency(cc_out.dl_cc_result->pdcch_dl); - test_pdsch_consistency(cc_out.dl_cc_result->pdsch); + test_dl_pdcch_consistency(cc_out.dl_cc_result->dl_sched.pdcch_dl); + test_pdsch_consistency(cc_out.dl_cc_result->dl_sched.pdsch); // Run UE-dedicated tests test_dl_sched_result(ctxt, cc_out); diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsenb/test/mac/nr/sched_nr_sim_ue.h index 7a75a7912..cecb1a050 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.h +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.h @@ -34,10 +34,10 @@ struct ue_nr_harq_ctxt_t { slot_point last_slot_tx, first_slot_tx, last_slot_ack; }; struct sched_nr_cc_output_res_t { - slot_point slot; - uint32_t cc; - const sched_nr_interface::dl_sched_t* dl_cc_result; - const sched_nr_interface::ul_sched_t* ul_cc_result; + slot_point slot; + uint32_t cc; + const sched_nr_interface::dl_sched_res_t* dl_cc_result; + const sched_nr_interface::ul_sched_t* ul_cc_result; }; struct ue_nr_cc_ctxt_t { diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 4fd125e37..7ee6cdbf1 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -47,12 +47,14 @@ struct task_job_manager { } sl.count = nof_sectors; } - void finish_cc(slot_point slot, const dl_sched_t& dl_res, const sched_nr_interface::ul_sched_t& ul_res) + void finish_cc(slot_point slot, + const sched_nr_interface::dl_sched_res_t& dl_res, + const sched_nr_interface::ul_sched_t& ul_res) { std::unique_lock lock(mutex); - TESTASSERT(dl_res.pdcch_dl.size() <= 1); + TESTASSERT(dl_res.dl_sched.pdcch_dl.size() <= 1); res_count++; - pdsch_count += dl_res.pdcch_dl.size(); + pdsch_count += dl_res.dl_sched.pdcch_dl.size(); auto& sl = slot_counter[slot.to_uint() % slot_counter.size()]; if (--sl.count == 0) { sl.cvar.notify_one(); @@ -97,9 +99,9 @@ void sched_nr_cfg_serialized_test() tasks.start_slot(slot_rx, nof_sectors); sched_tester.new_slot(slot_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - sched_nr_interface::dl_sched_t dl_res; - sched_nr_interface::ul_sched_t ul_res; - auto tp1 = std::chrono::steady_clock::now(); + sched_nr_interface::dl_sched_res_t dl_res; + sched_nr_interface::ul_sched_t ul_res; + auto tp1 = std::chrono::steady_clock::now(); TESTASSERT(sched_tester.get_sched()->get_dl_sched(slot_tx, cc, dl_res) == SRSRAN_SUCCESS); TESTASSERT(sched_tester.get_sched()->get_ul_sched(slot_tx, cc, ul_res) == SRSRAN_SUCCESS); auto tp2 = std::chrono::steady_clock::now(); @@ -107,7 +109,8 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(slot_rx, dl_res, ul_res); - TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or dl_res.pdcch_dl.size() == 1); + TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or + dl_res.dl_sched.pdcch_dl.size() == 1); } } @@ -146,9 +149,9 @@ void sched_nr_cfg_parallel_cc_test() sched_tester.new_slot(slot_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { srsran::get_background_workers().push_task([cc, slot_tx, &tasks, &sched_tester, &nano_count]() { - sched_nr_interface::dl_sched_t dl_res; - sched_nr_interface::ul_sched_t ul_res; - auto tp1 = std::chrono::steady_clock::now(); + sched_nr_interface::dl_sched_res_t dl_res; + sched_nr_interface::ul_sched_t ul_res; + auto tp1 = std::chrono::steady_clock::now(); TESTASSERT(sched_tester.get_sched()->get_dl_sched(slot_tx, cc, dl_res) == SRSRAN_SUCCESS); TESTASSERT(sched_tester.get_sched()->get_ul_sched(slot_tx, cc, ul_res) == SRSRAN_SUCCESS); auto tp2 = std::chrono::steady_clock::now(); diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc index cc434508a..5e9fadc10 100644 --- a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc @@ -21,7 +21,7 @@ using namespace srsenb::sched_nr_impl; void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_output_res_t& cc_out) { slot_point pdcch_slot = cc_out.slot; - const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl; + const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->dl_sched.pdcch_dl; // Iterate over UE PDCCH allocations for (const pdcch_dl_t& pdcch : pdcchs) { diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 75a7ed21a..71c169e83 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -417,7 +417,9 @@ public: } if (not use_dummy_sched) { - int ret = sched->get_dl_sched(pdsch_slot, 0, dl_sched); + srsenb::sched_nr_interface::dl_sched_res_t dl_res; + int ret = sched->get_dl_sched(pdsch_slot, 0, dl_res); + dl_sched = dl_res.dl_sched; for (pdsch_t& pdsch : dl_sched.pdsch) { // Set TBS From 04e5c81edf6e3fc6d2648c824a8bb783a2b8d60d Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 26 Aug 2021 18:25:07 +0200 Subject: [PATCH 24/56] sched,nr: nr_phy_test now uses the whole mac class rather than just the scheduler --- .../srsran/interfaces/gnb_interfaces.h | 22 +---- .../srsran/interfaces/gnb_mac_interfaces.h | 39 ++++++++ srsenb/hdr/stack/mac/mac_nr.h | 31 ++++--- srsenb/hdr/stack/mac/nr/sched_nr_cell.h | 7 +- .../stack/mac/nr/sched_nr_grant_allocator.h | 19 ++-- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 2 +- srsenb/hdr/stack/rrc/rrc_nr.h | 13 +-- srsenb/hdr/stack/upper/rlc_nr.h | 1 + srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/mac_nr.cc | 82 ++++++++--------- .../stack/mac/nr/sched_nr_grant_allocator.cc | 2 + srsenb/src/stack/rrc/rrc_nr.cc | 19 ++-- srsenb/test/common/dummy_classes_nr.h | 28 +++++- srsenb/test/common/rlc_test_dummy.h | 28 ++++++ srsenb/test/mac/nr/sched_nr_cfg_generators.h | 14 +-- srsenb/test/rrc/rrc_nr_test.cc | 16 ++-- test/phy/CMakeLists.txt | 2 + test/phy/dummy_gnb_stack.h | 88 +++++++++---------- test/phy/nr_phy_test.cc | 9 +- 19 files changed, 255 insertions(+), 169 deletions(-) create mode 100644 lib/include/srsran/interfaces/gnb_mac_interfaces.h create mode 100644 srsenb/test/common/rlc_test_dummy.h diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 3042a5c7c..5faf4945b 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -27,23 +27,6 @@ namespace srsenb { -/***************************** - * MAC INTERFACES - ****************************/ -class mac_interface_rrc_nr -{ -public: - // Provides cell configuration including SIB periodicity, etc. - virtual int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) = 0; - - /// Allocates a new user/RNTI at MAC. Returns RNTI on success or SRSRAN_INVALID_RNTI otherwise. - virtual uint16_t reserve_rnti() = 0; -}; - -// NR interface is identical to EUTRA interface -class mac_interface_rlc_nr : public mac_interface_rlc -{}; - /***************************** * RLC INTERFACES ****************************/ @@ -164,8 +147,7 @@ public: // NR interface identical to EUTRA version class rrc_interface_pdcp_nr : public rrc_interface_pdcp -{ -}; +{}; class phy_interface_rrc_nr { @@ -295,7 +277,7 @@ public: virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0; - virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) = 0; + virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) = 0; virtual void rach_detected(const rach_info_t& rach_info) = 0; }; diff --git a/lib/include/srsran/interfaces/gnb_mac_interfaces.h b/lib/include/srsran/interfaces/gnb_mac_interfaces.h new file mode 100644 index 000000000..c0f633fb6 --- /dev/null +++ b/lib/include/srsran/interfaces/gnb_mac_interfaces.h @@ -0,0 +1,39 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_GNB_MAC_INTERFACES_H +#define SRSRAN_GNB_MAC_INTERFACES_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" + +namespace srsenb { + +class mac_interface_rrc_nr +{ +public: + // Provides cell configuration including SIB periodicity, etc. + virtual int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) = 0; + + /// Allocates a new user/RNTI at MAC. Returns RNTI on success or SRSRAN_INVALID_RNTI otherwise. + virtual uint16_t reserve_rnti(uint32_t enb_cc_idx) = 0; + + virtual int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) = 0; +}; + +// NR interface is identical to EUTRA interface +class mac_interface_rlc_nr : public mac_interface_rlc +{}; + +} // namespace srsenb + +#endif // SRSRAN_GNB_MAC_INTERFACES_H diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index e55f5361a..b9edb9749 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -23,21 +23,21 @@ #include "srsran/common/task_scheduler.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_rlc_interfaces.h" -#include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" namespace srsenb { struct mac_nr_args_t { srsran::phy_cfg_nr_t phy_base_cfg = {}; - int fixed_dl_mcs = -1; - int fixed_ul_mcs = -1; - srsenb::pcap_args_t pcap; + int fixed_dl_mcs = -1; + int fixed_ul_mcs = -1; + srsenb::pcap_args_t pcap; }; class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr { public: - mac_nr(srsran::task_sched_handle task_sched_); + mac_nr(srsran::task_sched_handle task_sched_, const srsenb::sched_nr_interface::sched_cfg_t& sched_cfg = {}); ~mac_nr(); int init(const mac_nr_args_t& args_, @@ -50,9 +50,11 @@ public: void get_metrics(srsenb::mac_metrics_t& metrics); // MAC interface for RRC - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) override; - uint16_t reserve_rnti() override; - int read_pdu_bcch_bch(uint8_t* payload); + int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) override; + uint16_t reserve_rnti(uint32_t enb_cc_idx) override; + int read_pdu_bcch_bch(uint8_t* payload); + int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override; // MAC interface for RLC // TODO: @@ -68,7 +70,8 @@ public: void rach_detected(const rach_info_t& rach_info) override; private: - uint16_t add_ue(uint32_t enb_cc_idx); + uint16_t add_ue_(uint32_t enb_cc_idx); + uint16_t alloc_ue(uint32_t enb_cc_idx); int remove_ue(uint16_t rnti); // internal misc helpers @@ -91,7 +94,7 @@ private: rrc_interface_mac_nr* rrc = nullptr; // args - srsran::task_sched_handle task_sched; + srsran::task_sched_handle task_sched; srsran::task_multiqueue::queue_handle stack_task_queue; std::unique_ptr pcap = nullptr; @@ -100,17 +103,17 @@ private: std::atomic started = {false}; - const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage + const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage srsran::slot_point pdsch_slot, pusch_slot; srsenb::sched_nr sched; srsenb::sched_interface::cell_cfg_t cfg = {}; // Map of active UEs - pthread_rwlock_t rwlock = {}; - static const uint16_t FIRST_RNTI = 0x4601; + pthread_rwlock_t rwlock = {}; + static const uint16_t FIRST_RNTI = 0x4601; srsran::static_circular_map, SRSENB_MAX_UES> ue_db; - std::atomic ue_counter; + std::atomic ue_counter; // BCH buffers struct sib_info_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h index addc017b6..02ada6f30 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -53,8 +53,13 @@ class ra_sched public: explicit ra_sched(const bwp_params& bwp_cfg_); - int dl_rach_info(const dl_sched_rar_info_t& rar_info); + /// Addition of detected PRACH into the queue + int dl_rach_info(const dl_sched_rar_info_t& rar_info); + + /// Allocate pending RARs void run_slot(bwp_slot_allocator& slot_grid); + + /// Check if there are pending RARs bool empty() const { return pending_rars.empty(); } private: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 872069f35..7e996fa93 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -44,15 +44,16 @@ struct bwp_slot_grid { uint32_t slot_idx; const bwp_params* cfg; - bwp_rb_bitmap dl_prbs; - bwp_rb_bitmap ul_prbs; - pdcch_dl_list_t dl_pdcchs; - pdcch_ul_list_t ul_pdcchs; - pdsch_list_t pdschs; - rar_list_t rar; - slot_coreset_list coresets; - pusch_list_t puschs; - harq_ack_list_t pending_acks; + bwp_rb_bitmap dl_prbs; + bwp_rb_bitmap ul_prbs; + pdcch_dl_list_t dl_pdcchs; + pdcch_ul_list_t ul_pdcchs; + pdsch_list_t pdschs; + rar_list_t rar; + slot_coreset_list coresets; + pusch_list_t puschs; + harq_ack_list_t pending_acks; + srsran_softbuffer_tx_t rar_softbuffer; bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index ef6aa3b89..3ed5fe3d5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -91,7 +91,7 @@ public: uint32_t freq_idx; uint32_t ta_cmd; uint16_t temp_crnti; - uint32_t msg3_size; + uint32_t msg3_size = 7; slot_point prach_slot; }; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 55bab1a29..b5cb99443 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -28,6 +28,7 @@ #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include @@ -118,8 +119,8 @@ public: int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); // state - rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; - uint8_t transaction_id = 0; + rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; + uint8_t transaction_id = 0; uint32_t drb1_lcid = 4; }; @@ -128,12 +129,12 @@ private: rrc_nr_cfg_t cfg = {}; // interfaces - phy_interface_stack_nr* phy = nullptr; - mac_interface_rrc_nr* mac = nullptr; + phy_interface_stack_nr* phy = nullptr; + mac_interface_rrc_nr* mac = nullptr; rlc_interface_rrc* rlc = nullptr; pdcp_interface_rrc* pdcp = nullptr; - gtpu_interface_rrc_nr* gtpu = nullptr; - ngap_interface_rrc_nr* ngap = nullptr; + gtpu_interface_rrc_nr* gtpu = nullptr; + ngap_interface_rrc_nr* ngap = nullptr; rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; // args diff --git a/srsenb/hdr/stack/upper/rlc_nr.h b/srsenb/hdr/stack/upper/rlc_nr.h index 4a1fa424a..978439bf4 100644 --- a/srsenb/hdr/stack/upper/rlc_nr.h +++ b/srsenb/hdr/stack/upper/rlc_nr.h @@ -14,6 +14,7 @@ #define SRSENB_RLC_NR_H #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/rlc/rlc.h" #include diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 106627e38..7d3c3f536 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -11,7 +11,7 @@ set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc - sched_nr_grant_allocator.cc + sched_nr_grant_allocator.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 959930e85..afa2d7218 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -24,10 +24,10 @@ namespace srsenb { -mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : +mac_nr::mac_nr(srsran::task_sched_handle task_sched_, const sched_nr_interface::sched_cfg_t& sched_cfg) : logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_), - sched(srsenb::sched_nr_interface::sched_cfg_t{}), + sched(sched_cfg), bcch_bch_payload(srsran::make_byte_buffer()) { stack_task_queue = task_sched.make_task_queue(); @@ -56,12 +56,6 @@ int mac_nr::init(const mac_nr_args_t& args_, pcap->open(args.pcap.filename); } - // configure scheduler for 1 carrier - std::vector cells_cfg = srsenb::get_default_cells_cfg(1); - sched.cell_cfg(cells_cfg); - - detected_rachs.resize(cells_cfg.size()); - logger.info("Started"); started = true; @@ -82,16 +76,19 @@ void mac_nr::stop() void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) {} -int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) +int mac_nr::cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) { - cfg = *cell_cfg; + cfg = cell; + sched.cell_cfg(nr_cells); + detected_rachs.resize(nr_cells.size()); // read SIBs from RRC (SIB1 for now only) for (int i = 0; i < 1 /* srsenb::sched_interface::MAX_SIBS */; i++) { - if (cell_cfg->sibs->len > 0) { + if (cell.sibs->len > 0) { sib_info_t sib = {}; sib.index = i; - sib.periodicity = cell_cfg->sibs->period_rf; + sib.periodicity = cell.sibs->period_rf; sib.payload = srsran::make_byte_buffer(); if (sib.payload == nullptr) { logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); @@ -109,6 +106,34 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } +int mac_nr::ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) +{ + sched.ue_cfg(rnti, ue_cfg); + return SRSRAN_SUCCESS; +} + +uint16_t mac_nr::reserve_rnti(uint32_t enb_cc_idx) +{ + uint16_t rnti = alloc_ue(enb_cc_idx); + if (rnti == SRSRAN_INVALID_RNTI) { + return rnti; + } + + // Add new user to the scheduler so that it can RX/TX SRB0 + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1); + ue_cfg.fixed_dl_mcs = args.fixed_dl_mcs; + ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; + sched.ue_cfg(rnti, ue_cfg); + + // Register new user in RRC + if (rrc->add_user(rnti) == SRSRAN_ERROR) { + // ue_rem(rnti); + return SRSRAN_SUCCESS; + } + + return rnti; +} + void mac_nr::rach_detected(const rach_info_t& rach_info) { static srsran::mutexed_tprof rach_tprof("rach_tprof", "MAC-NR", 1); @@ -117,12 +142,8 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) uint32_t enb_cc_idx = 0; stack_task_queue.push([this, rach_info, enb_cc_idx, rach_tprof_meas]() mutable { - uint16_t rnti = add_ue(enb_cc_idx); - if (rnti == SRSRAN_INVALID_RNTI) { - return; - } - rach_tprof_meas.defer_stop(); + uint16_t rnti = reserve_rnti(enb_cc_idx); // TODO: Generate RAR data // .. @@ -130,25 +151,14 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) // Log this event. ++detected_rachs[enb_cc_idx]; - // Add new user to the scheduler so that it can RX/TX SRB0 - srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1); - ue_cfg.fixed_dl_mcs = args.fixed_dl_mcs; - ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; - sched.ue_cfg(rnti, ue_cfg); - - // Register new user in RRC - if (rrc->add_user(rnti) == SRSRAN_ERROR) { - // ue_rem(rnti); - return; - } - // Trigger scheduler RACH srsenb::sched_nr_interface::dl_sched_rar_info_t rar_info = {}; rar_info.preamble_idx = rach_info.preamble; rar_info.temp_crnti = rnti; + rar_info.ta_cmd = rach_info.time_adv; rar_info.prach_slot = slot_point{NUMEROLOGY_IDX, rach_info.slot_index}; // TODO: fill remaining fields as required - // sched.dl_rach_info(enb_cc_idx, rar_info); + sched.dl_rach_info(enb_cc_idx, rar_info); logger.info("RACH: slot=%d, cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x", rach_info.slot_index, @@ -165,7 +175,7 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) }); } -uint16_t mac_nr::add_ue(uint32_t enb_cc_idx) +uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx) { ue_nr* inserted_ue = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; @@ -216,16 +226,6 @@ int mac_nr::remove_ue(uint16_t rnti) return SRSRAN_SUCCESS; } -uint16_t mac_nr::reserve_rnti() -{ - uint16_t rnti = add_ue(0); - if (rnti == SRSRAN_INVALID_RNTI) { - return rnti; - } - - return rnti; -} - bool mac_nr::is_rnti_valid_unsafe(uint16_t rnti) { if (not started) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index d4109f096..fd243bf7b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -29,6 +29,7 @@ bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl_pdcchs, ul_pdcchs); } } + srsran_softbuffer_tx_init_guru(&rar_softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB); } void bwp_slot_grid::reset() @@ -147,6 +148,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t slot_cfg.idx = pdcch_slot.slot_idx(); bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); srsran_assert(success, "Error converting DCI to grant"); + pdsch.sch.grant.tb[0].softbuffer.tx = &bwp_pdcch_slot.rar_softbuffer; // Generate Msg3 grants in PUSCH uint32_t last_msg3 = msg3_rbs.start(); diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 920532761..c75ebca49 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -12,6 +12,7 @@ #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/common/common_enb.h" +#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" @@ -210,23 +211,25 @@ void rrc_nr::config_phy() void rrc_nr::config_mac() { // Fill MAC scheduler configuration for SIBs - srsenb::sched_interface::cell_cfg_t sched_cfg; - set_sched_cell_cfg_sib1(&sched_cfg, cfg.sib1); + // TODO: use parsed cell NR cfg configuration + std::vector sched_cells_cfg = {srsenb::get_default_cells_cfg(1)}; + sched_interface::cell_cfg_t cell_cfg; + set_sched_cell_cfg_sib1(&cell_cfg, cfg.sib1); // set SIB length for (uint32_t i = 0; i < nof_si_messages + 1; i++) { - sched_cfg.sibs[i].len = sib_buffer[i]->N_bytes; + cell_cfg.sibs[i].len = sib_buffer[i]->N_bytes; } // PUCCH width - sched_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb); - logger.info("Allocating %d PRBs for PUCCH", sched_cfg.nrb_pucch); + cell_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb); + logger.info("Allocating %d PRBs for PUCCH", cell_cfg.nrb_pucch); // Copy Cell configuration - sched_cfg.cell = cfg.cell; + cell_cfg.cell = cfg.cell; // Configure MAC scheduler - mac->cell_cfg(&sched_cfg); + mac->cell_cfg(cell_cfg, sched_cells_cfg); } int32_t rrc_nr::generate_sibs() @@ -405,7 +408,7 @@ int rrc_nr::sgnb_addition_request(uint16_t eutra_rnti) { task_sched.defer_task([this, eutra_rnti]() { // try to allocate new user - uint16_t nr_rnti = mac->reserve_rnti(); + uint16_t nr_rnti = mac->reserve_rnti(0); if (nr_rnti == SRSRAN_INVALID_RNTI) { logger.error("Failed to allocate RNTI at MAC"); rrc_eutra->sgnb_addition_reject(eutra_rnti); diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h index 4237aebe2..d799aadce 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsenb/test/common/dummy_classes_nr.h @@ -14,18 +14,38 @@ #define SRSRAN_DUMMY_NR_CLASSES_H #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" namespace srsenb { -class mac_dummy : public mac_interface_rrc_nr +class rrc_nr_dummy : public rrc_interface_mac_nr { public: - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg_) + int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int add_user(uint16_t rnti) { return SRSRAN_SUCCESS; } +}; + +class rlc_nr_dummy : public rlc_interface_mac_nr +{ +public: + int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) override { return SRSRAN_SUCCESS; } + void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) override {} + void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) override {} +}; + +class mac_nr_dummy : public mac_interface_rrc_nr +{ +public: + int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) override { - cellcfgobj = *cell_cfg_; + cellcfgobj = cell; return SRSRAN_SUCCESS; } - uint16_t reserve_rnti() { return 0x4601; } + uint16_t reserve_rnti(uint32_t enb_cc_idx) override { return 0x4601; } + + int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override { return SRSRAN_SUCCESS; } srsenb::sched_interface::cell_cfg_t cellcfgobj; }; diff --git a/srsenb/test/common/rlc_test_dummy.h b/srsenb/test/common/rlc_test_dummy.h new file mode 100644 index 000000000..377f5567e --- /dev/null +++ b/srsenb/test/common/rlc_test_dummy.h @@ -0,0 +1,28 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RLC_TEST_DUMMY_H +#define SRSRAN_RLC_TEST_DUMMY_H + +#include "srsran/interfaces/enb_rlc_interfaces.h" + +namespace srsenb { + +class rlc_dummy : public rlc_interface_mac +{ + int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { return SRSRAN_SUCCESS; } + void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) {} +}; + +} // namespace srsenb + +#endif // SRSRAN_RLC_TEST_DUMMY_H diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 498f2a578..310c63a6e 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -18,7 +18,7 @@ namespace srsenb { -srsran_coreset_t get_default_coreset0(uint32_t nof_prb) +inline srsran_coreset_t get_default_coreset0(uint32_t nof_prb) { srsran_coreset_t coreset{}; coreset.id = 0; @@ -30,8 +30,8 @@ srsran_coreset_t get_default_coreset0(uint32_t nof_prb) return coreset; } -sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ - srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { sched_nr_interface::cell_cfg_t cell_cfg{}; @@ -65,7 +65,7 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& return cell_cfg; } -std::vector get_default_cells_cfg( +inline std::vector get_default_cells_cfg( uint32_t nof_sectors, const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { @@ -77,9 +77,9 @@ std::vector get_default_cells_cfg( return cells; } -sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc, - const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ - srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +inline sched_nr_interface::ue_cfg_t get_default_ue_cfg( + uint32_t nof_cc, + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { sched_nr_interface::ue_cfg_t uecfg{}; uecfg.carriers.resize(nof_cc); diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index 3875956f9..5803cf84a 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -38,10 +38,10 @@ int test_sib_generation() { srsran::task_scheduler task_sched; - mac_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; @@ -67,10 +67,10 @@ int test_rrc_setup() { srsran::task_scheduler task_sched; - mac_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 841d53339..f76226e2e 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -18,6 +18,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) srsran_radio srsenb_phy srsgnb_mac + srsran_mac ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} @@ -73,6 +74,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_bidir_sched nr_phy_test --reference=carrier=${NR_PHY_TEST_BW} --duration=100 # 100 slots + --rnti=17921 # 0x4601 --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 71c169e83..27efa70c9 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,7 +15,10 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" +#include "srsenb/hdr/stack/mac/mac_nr.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/test/common/dummy_classes_nr.h" +#include "srsenb/test/common/rlc_test_dummy.h" #include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include #include @@ -73,9 +76,12 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; - std::unique_ptr sched; - srsran::slot_point pdsch_slot, pusch_slot; - srslog::basic_logger& sched_logger; + srsran::task_scheduler task_sched; + srsenb::rrc_nr_dummy rrc_obj; + srsenb::rlc_dummy rlc_obj; + std::unique_ptr mac; + srsran::slot_point pdsch_slot, pusch_slot; + srslog::basic_logger& sched_logger; std::mutex metrics_mutex; metrics_t metrics = {}; @@ -291,8 +297,6 @@ private: metrics.mac.tx_errors += tb_count; logger.debug("NACK received!"); } - - sched->dl_ack_info(rnti, 0, ack_bit->pid, 0, is_ok); } // Process SR @@ -305,13 +309,14 @@ private: public: struct args_t { - srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - bool use_dummy_sched = true; ///< Use dummy or real NR scheduler - uint16_t rnti = 0x1234; ///< C-RNTI - uint32_t ss_id = 1; ///< Search Space identifier - uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level - uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + bool use_dummy_sched = true; ///< Use dummy or real NR scheduler + bool wait_preamble = false; ///< Whether a UE is created automatically or the stack waits for a PRACH + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index struct { uint32_t rb_start = 0; ///< Start frequency domain resource block uint32_t rb_length = 10; ///< Number of frequency domain resource blocks @@ -335,15 +340,20 @@ public: srsenb::sched_nr_interface::sched_cfg_t sched_cfg{}; sched_cfg.pdsch_enabled = args.pdsch.slots != "" and args.pdsch.slots != "none"; sched_cfg.pusch_enabled = args.pusch.slots != "" and args.pusch.slots != "none"; - sched.reset(new srsenb::sched_nr{sched_cfg}); + mac.reset(new srsenb::mac_nr{&task_sched, sched_cfg}); + mac->init(srsenb::mac_nr_args_t{}, nullptr, nullptr, &rlc_obj, &rrc_obj); std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); - sched->cell_cfg(cells_cfg); + mac->cell_cfg(srsenb::sched_interface::cell_cfg_t{}, cells_cfg); // add UE to scheduler - srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); - ue_cfg.fixed_dl_mcs = args.pdsch.mcs; - ue_cfg.fixed_ul_mcs = args.pusch.mcs; - sched->ue_cfg(args.rnti, ue_cfg); + if (not use_dummy_sched and not args.wait_preamble) { + mac->reserve_rnti(0); + + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); + ue_cfg.fixed_dl_mcs = args.pdsch.mcs; + ue_cfg.fixed_ul_mcs = args.pusch.mcs; + mac->ue_cfg(args.rnti, ue_cfg); + } dl.mcs = args.pdsch.mcs; ul.mcs = args.pusch.mcs; @@ -417,9 +427,7 @@ public: } if (not use_dummy_sched) { - srsenb::sched_nr_interface::dl_sched_res_t dl_res; - int ret = sched->get_dl_sched(pdsch_slot, 0, dl_res); - dl_sched = dl_res.dl_sched; + int ret = mac->get_dl_sched(slot_cfg, dl_sched); for (pdsch_t& pdsch : dl_sched.pdsch) { // Set TBS @@ -465,7 +473,7 @@ public: } if (not use_dummy_sched) { - int ret = sched->get_ul_sched(pusch_slot, 0, ul_sched); + int ret = mac->get_ul_sched(slot_cfg, ul_sched); return ret; } @@ -541,22 +549,12 @@ public: return SRSRAN_SUCCESS; } - void dl_ack_info(uint16_t rnti_, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override { if (not use_dummy_sched) { - sched->dl_ack_info(rnti_, cc, pid, tb_idx, ack); + mac->pucch_info(slot_cfg, pucch_info); } - } - void ul_crc_info(uint16_t rnti_, uint32_t cc, uint32_t pid, bool crc) - { - if (not use_dummy_sched) { - sched->ul_crc_info(rnti_, cc, pid, crc); - } - } - - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override - { // Handle UCI data if (not handle_uci_data(pucch_info.uci_data.cfg, pucch_info.uci_data.value)) { logger.error("Error handling UCI data from PUCCH reception"); @@ -588,6 +586,10 @@ public: int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override { + if (not use_dummy_sched) { + mac->pusch_info(slot_cfg, pusch_info); + } + // Handle UCI data if (not handle_uci_data(pusch_info.uci_cfg, pusch_info.pusch_data.uci)) { logger.error("Error handling UCI data from PUCCH reception"); @@ -602,23 +604,19 @@ public: metrics.mac.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs(); metrics.mac.rx_pkts++; - ul_crc_info(rnti, 0, pusch_info.pid, pusch_info.pusch_data.tb[0].crc); - return SRSRAN_SUCCESS; } void rach_detected(const rach_info_t& rach_info) override { if (not use_dummy_sched) { - srsenb::sched_nr_interface::dl_sched_rar_info_t ra_info; - ra_info.preamble_idx = rach_info.preamble; - ra_info.ta_cmd = rach_info.time_adv; - ra_info.ofdm_symbol_idx = 0; - ra_info.msg3_size = 7; - ra_info.freq_idx = 0; - ra_info.prach_slot = pdsch_slot - TX_ENB_DELAY; - ra_info.temp_crnti = rnti; - sched->dl_rach_info(0, ra_info); + mac->rach_detected(rach_info); + task_sched.run_pending_tasks(); + + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); + ue_cfg.fixed_dl_mcs = ue_cfg.fixed_dl_mcs; + ue_cfg.fixed_ul_mcs = ue_cfg.fixed_ul_mcs; + mac->ue_cfg(rnti, ue_cfg); } std::unique_lock lock(metrics_mutex); diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index d6071f195..618c85d6b 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -115,8 +115,9 @@ test_bench::args_t::args_t(int argc, char** argv) ue_stack.rnti = rnti; - gnb_stack.rnti = rnti; - gnb_stack.phy_cfg = phy_cfg; + gnb_stack.rnti = rnti; + gnb_stack.phy_cfg = phy_cfg; + gnb_stack.wait_preamble = ue_stack.prach_preamble > 0; if (gnb_stack.pdsch.rb_length == 0) { gnb_stack.pdsch.rb_length = phy_cfg.carrier.nof_prb; @@ -271,8 +272,8 @@ int main(int argc, char** argv) } // Assert metrics - TESTASSERT(metrics.gnb_stack.mac.tx_errors == 0); - TESTASSERT(metrics.gnb_stack.mac.rx_errors == 0); + TESTASSERT_EQ(0, metrics.gnb_stack.mac.tx_errors); + TESTASSERT_EQ(0, metrics.gnb_stack.mac.rx_errors); TESTASSERT(metrics.ue_stack.sr_count == metrics.gnb_stack.sr_count); // If reached here, the test is successful From fec60344dde48b9951d4040e18684791f00d9cad Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 27 Aug 2021 13:57:13 +0200 Subject: [PATCH 25/56] sched,nr: fix rar softbuffer allocation --- srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h | 3 ++- srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 7e996fa93..259daae26 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -53,7 +53,8 @@ struct bwp_slot_grid { slot_coreset_list coresets; pusch_list_t puschs; harq_ack_list_t pending_acks; - srsran_softbuffer_tx_t rar_softbuffer; + + srsran::unique_pool_ptr rar_softbuffer; bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index fd243bf7b..7368e6abd 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -21,7 +21,8 @@ bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : dl_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1), ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1), slot_idx(slot_idx_), - cfg(&bwp_cfg_) + cfg(&bwp_cfg_), + rar_softbuffer(harq_softbuffer_pool::get_instance().get_tx(bwp_cfg_.cfg.rb_width)) { for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) { if (cfg->cfg.pdcch.coreset_present[cs_idx]) { @@ -29,7 +30,6 @@ bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl_pdcchs, ul_pdcchs); } } - srsran_softbuffer_tx_init_guru(&rar_softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB); } void bwp_slot_grid::reset() @@ -148,7 +148,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t slot_cfg.idx = pdcch_slot.slot_idx(); bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); srsran_assert(success, "Error converting DCI to grant"); - pdsch.sch.grant.tb[0].softbuffer.tx = &bwp_pdcch_slot.rar_softbuffer; + pdsch.sch.grant.tb[0].softbuffer.tx = bwp_pdcch_slot.rar_softbuffer->get(); // Generate Msg3 grants in PUSCH uint32_t last_msg3 = msg3_rbs.start(); From 01441d143d8c27e8dffd6a039bce9bf82be02042 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 31 Aug 2021 11:58:13 +0200 Subject: [PATCH 26/56] mac,nr: avoid use of uninitialized rnti value --- srsenb/hdr/stack/mac/mac_nr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index b9edb9749..76b0d591e 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -113,7 +113,7 @@ private: static const uint16_t FIRST_RNTI = 0x4601; srsran::static_circular_map, SRSENB_MAX_UES> ue_db; - std::atomic ue_counter; + std::atomic ue_counter{0}; // BCH buffers struct sib_info_t { From b311806179fedb8b7793386f09dac346a88d152c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 31 Aug 2021 13:40:31 +0200 Subject: [PATCH 27/56] mac,nr: avoid repacking NR DL retxs --- srsenb/hdr/stack/mac/mac.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 20 +++++++++----------- srsenb/src/stack/mac/nr/mac_nr.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_harq.cc | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 0bf5bbc6f..63e5527dd 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -139,7 +139,7 @@ private: /* Map of active UEs */ static const uint16_t FIRST_RNTI = 0x46; rnti_map_t > ue_db; - std::atomic ue_counter; + std::atomic ue_counter{0}; uint8_t* assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32_t enb_cc_idx, diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 0689bd24d..103c6ed80 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -56,12 +56,11 @@ public: bool new_retx(slot_point slot_tx, slot_point slot_ack, const prb_grant& grant); bool new_retx(slot_point slot_tx, slot_point slot_ack); - const uint32_t pid; - -protected: // NOTE: Has to be used before first tx is dispatched bool set_tbs(uint32_t tbs); + const uint32_t pid; + private: struct tb_t { bool active = false; @@ -84,16 +83,15 @@ class dl_harq_proc : public harq_proc public: dl_harq_proc(uint32_t id_, uint32_t nprb); - tx_harq_softbuffer& get_softbuffer() { return *softbuffer; } + tx_harq_softbuffer& get_softbuffer() { return *softbuffer; } srsran::unique_byte_buffer_t* get_tx_pdu() { return &pdu; } - // clear and reset softbuffer and PDU for new tx - bool set_tbs(uint32_t tbs) - { - softbuffer->reset(); - pdu->clear(); - return harq_proc::set_tbs(tbs); - } + bool new_tx(slot_point slot_tx, + slot_point slot_ack, + const prb_grant& grant, + uint32_t mcs, + uint32_t tbs, + uint32_t max_retx); private: srsran::unique_pool_ptr softbuffer; diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index afa2d7218..1ed756142 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -281,7 +281,7 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched continue; } for (auto& tb_data : pdsch.data) { - if (tb_data != nullptr) { + if (tb_data != nullptr and tb_data->N_bytes == 0) { // TODO: exclude retx from packing ue_db[rnti]->generate_pdu(tb_data, pdsch.sch.grant.tb->tbs / 8); diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsenb/src/stack/mac/nr/sched_nr_harq.cc index 0d27c34e7..185a44c9c 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_harq.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_harq.cc @@ -105,6 +105,21 @@ dl_harq_proc::dl_harq_proc(uint32_t id_, uint32_t nprb) : harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_tx(nprb)), pdu(srsran::make_byte_buffer()) {} +bool dl_harq_proc::new_tx(slot_point slot_tx, + slot_point slot_ack, + const prb_grant& grant, + uint32_t mcs, + uint32_t tbs, + uint32_t max_retx) +{ + if (harq_proc::new_tx(slot_tx, slot_ack, grant, mcs, tbs, max_retx)) { + softbuffer->reset(); + pdu->clear(); + return true; + } + return false; +} + harq_entity::harq_entity(uint32_t nprb, uint32_t nof_harq_procs) { // Create HARQs From 5f9cfb56f6d6c048c71235f67faa9ae66d85184e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 27 Aug 2021 12:27:29 +0200 Subject: [PATCH 28/56] lte,gtpu: fix and refactor gtpu tunnel management during handover --- srsenb/hdr/stack/upper/gtpu.h | 4 +- srsenb/src/stack/upper/gtpu.cc | 88 ++++++++++++++++++++-------------- srsenb/test/upper/gtpu_test.cc | 7 +++ 3 files changed, 62 insertions(+), 37 deletions(-) diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 2206a8c33..976a865b2 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -50,7 +50,7 @@ public: // A UE should have <= 3 DRBs active, and each DRB should have two tunnels active at the same time at most const static size_t MAX_TUNNELS_PER_UE = 6; - enum class tunnel_state { pdcp_active, buffering, forward_to, forwarded_from }; + enum class tunnel_state { pdcp_active, buffering, forward_to, forwarded_from, inactive }; struct tunnel { uint16_t rnti = SRSRAN_INVALID_RNTI; @@ -101,13 +101,13 @@ public: void activate_tunnel(uint32_t teid); void suspend_tunnel(uint32_t teid); + void deactivate_tunnel(uint32_t teid); void set_tunnel_priority(uint32_t first_teid, uint32_t second_teid); void handle_rx_pdcp_sdu(uint32_t teid); void buffer_pdcp_sdu(uint32_t teid, uint32_t pdcp_sn, srsran::unique_byte_buffer_t sdu); void setup_forwarding(uint32_t rx_teid, uint32_t tx_teid); bool remove_tunnel(uint32_t teid); - bool remove_bearer(uint16_t rnti, uint32_t lcid); bool remove_rnti(uint16_t rnti); private: diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index 63c5ca35e..c6a20dc41 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -165,6 +165,9 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin) { tunnel& tun = tunnels[teidin]; + // update forwarding paths if required + deactivate_tunnel(teidin); + // erase keeping the relative order auto& ue = ue_teidin_db[tun.rnti]; auto lcid_it = std::lower_bound(ue.begin(), ue.end(), lcid_tunnel{tun.lcid, tun.teid_in}); @@ -176,28 +179,10 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin) return true; } -bool gtpu_tunnel_manager::remove_bearer(uint16_t rnti, uint32_t lcid) -{ - logger.info("Removing rnti=0x%x,lcid=%d", rnti, lcid); - bool removed = false; - for (srsran::span to_rem = find_rnti_lcid_tunnels(rnti, lcid); not to_rem.empty(); - to_rem = find_rnti_lcid_tunnels(rnti, lcid)) { - uint32_t teid = to_rem.front().teid; - bool ret = remove_tunnel(teid); - srsran_expect(ret, - "Inconsistency detected between internal data structures for rnti=0x%x,lcid=%d," TEID_IN_FMT, - rnti, - lcid, - teid); - removed |= ret; - } - return removed; -} - bool gtpu_tunnel_manager::remove_rnti(uint16_t rnti) { if (not ue_teidin_db.contains(rnti)) { - logger.warning("removing rnti. rnti=0x%x not found.", rnti); + logger.warning("Removing rnti. rnti=0x%x not found.", rnti); return false; } logger.info("Removing rnti=0x%x", rnti); @@ -249,10 +234,28 @@ void gtpu_tunnel_manager::suspend_tunnel(uint32_t teid) tun.state = tunnel_state::buffering; } +void gtpu_tunnel_manager::deactivate_tunnel(uint32_t teid) +{ + tunnel& tun = tunnels[teid]; + + if (tun.state == tunnel_state::forwarded_from) { + // Deactivate respective MME->SeNB forwarding tunnel + for (auto lcid_tun : find_rnti_lcid_tunnels(tun.rnti, tun.lcid)) { + if (lcid_tun.teid != tun.teid_in) { + const gtpu_tunnel_manager::tunnel* mmeenb_tun = find_tunnel(lcid_tun.teid); + if (mmeenb_tun->state == gtpu_tunnel_manager::tunnel_state::forward_to and mmeenb_tun->fwd_tunnel == &tun) { + deactivate_tunnel(mmeenb_tun->teid_in); + } + } + } + } + + tun.state = tunnel_state::inactive; +} + void gtpu_tunnel_manager::set_tunnel_priority(uint32_t before_teid, uint32_t after_teid) { tunnel& before_tun = tunnels[before_teid]; - tunnel& after_tun = tunnels[after_teid]; // GTPU should not forward SDUs from main tunnel until the SeNB-TeNB tunnel has been flushed suspend_tunnel(after_teid); @@ -518,11 +521,15 @@ void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active) void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) { - if (tunnels.find_rnti_lcid_tunnels(rnti, lcid).empty()) { - logger.error("Removing non-existent bearer rnti=0x%x,lcid=%d", rnti, lcid); + srsran::span lcid_tuns = tunnels.find_rnti_lcid_tunnels(rnti, lcid); + if (lcid_tuns.empty()) { + logger.info("Removing bearer rnti=0x%x,lcid=%d without any active tunnels", rnti, lcid); return; } - tunnels.remove_bearer(rnti, lcid); + do { + rem_tunnel(lcid_tuns.front().teid); + lcid_tuns = tunnels.find_rnti_lcid_tunnels(rnti, lcid); + } while (not lcid_tuns.empty()); } void gtpu::mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) @@ -532,27 +539,33 @@ void gtpu::mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) void gtpu::rem_tunnel(uint32_t teidin) { - if (not tunnels.has_teid(teidin)) { + const gtpu_tunnel_manager::tunnel* tun = tunnels.find_tunnel(teidin); + if (tun == nullptr) { logger.warning("Removing tunnel - " TEID_IN_FMT " does not exist", teidin); return; } + if (tun->state == gtpu_tunnel_manager::tunnel_state::forwarded_from) { + // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover + // END MARKER should be forwarded to TeNB if forwarding is activated + send_end_marker(tun->teid_in); + } else if (tun->state == gtpu_tunnel_manager::tunnel_state::forward_to) { + // Delete respective forwarding SeNB-TeNB tunnel + send_end_marker(tun->fwd_tunnel->teid_in); + rem_tunnel(tun->fwd_tunnel->teid_in); + } tunnels.remove_tunnel(teidin); } void gtpu::rem_user(uint16_t rnti) { - const auto* tun_lst = tunnels.find_rnti_tunnels(rnti); + const gtpu_tunnel_manager::ue_lcid_tunnel_list* tun_lst = tunnels.find_rnti_tunnels(rnti); if (tun_lst == nullptr) { logger.info("Removing user - rnti=0x%x not found.", rnti); return; } - for (gtpu_tunnel_manager::lcid_tunnel tun_elem : *tun_lst) { - const gtpu_tunnel* tun = tunnels.find_tunnel(tun_elem.teid); - if (tun != nullptr and tun->state == gtpu_tunnel_manager::tunnel_state::forwarded_from) { - // In case of forwarding tunnel tx endpoint, send one extra End Marker on removal - send_end_marker(tun->teid_in); - rem_tunnel(tun->teid_in); - } + while (not tun_lst->empty()) { + // Note: May send End-Marker to active forwarding tunnels during their removal + rem_tunnel(tun_lst->front().teid); } tunnels.remove_rnti(rnti); } @@ -560,7 +573,7 @@ void gtpu::rem_user(uint16_t rnti) void gtpu::handle_end_marker(const gtpu_tunnel& rx_tunnel) { uint16_t rnti = rx_tunnel.rnti; - logger.info("Received GTPU End Marker for " TEID_IN_FMT ", rnti=0x%x.", rx_tunnel.teid_in, rnti); + logger.info("Rx GTPU End Marker, " TEID_IN_FMT ", rnti=0x%x.", rx_tunnel.teid_in, rnti); if (rx_tunnel.state == gtpu_tunnel_state::forward_to) { // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover @@ -765,12 +778,12 @@ void gtpu::echo_response(in_addr_t addr, in_port_t port, uint16_t seq) ***************************************************************************/ bool gtpu::send_end_marker(uint32_t teidin) { - logger.info("TX GTPU End Marker."); const gtpu_tunnel* tx_tun = tunnels.find_tunnel(teidin); if (tx_tun == nullptr) { logger.error("TEID=%d not found to send the end marker to", teidin); return false; } + logger.info("Tx GTPU End Marker, " TEID_IN_FMT ", rnti=0x%x", teidin, tx_tun->rnti); gtpu_header_t header = {}; unique_byte_buffer_t pdu = make_byte_buffer(); @@ -792,7 +805,12 @@ bool gtpu::send_end_marker(uint32_t teidin) servaddr.sin_addr.s_addr = htonl(tx_tun->spgw_addr); servaddr.sin_port = htons(GTPU_PORT); - return sendto(fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)) > 0; + bool success = + sendto(fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)) > 0; + if (success) { + tunnels.deactivate_tunnel(tx_tun->teid_in); + } + return success; } /**************************************************************************** diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index b33e27867..b6b1d6fba 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -358,6 +358,13 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) } srsran::span encoded_data2{tenb_pdcp.last_sdu->msg + 20u, tenb_pdcp.last_sdu->msg + 30u}; TESTASSERT(std::all_of(encoded_data2.begin(), encoded_data2.end(), [N_pdus](uint8_t b) { return b == N_pdus - 1; })); + if (event != tunnel_test_event::ue_removal_no_marker) { + // The User is removed in SeNB in case it hasn't and there was no reestablishment + if (std::uniform_int_distribution{0, 1}(g) > 0) { + senb_gtpu.rem_bearer(0x46, 3); + } + senb_gtpu.rem_user(0x46); + } return SRSRAN_SUCCESS; } From c63932f514d1b8fa826bb396939aa80cdfaee740 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Wed, 25 Aug 2021 12:08:24 +0200 Subject: [PATCH 29/56] Added RACH, PDSCH, PUCCH, Sounding Reference Signal and UL Power Control configurations from target cell to RRCConnectionReconfigurationMessage --- srsenb/src/stack/rrc/rrc_mobility.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 534bfe082..7888799d2 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -494,12 +494,24 @@ void rrc::ue::rrc_mobility::fill_mobility_reconf_common(asn1::rrc::dl_dcch_msg_s mob_info.target_pci = target_cell.cell_cfg.pci; mob_info.t304 = target_cell.cell_cfg.t304; mob_info.new_ue_id.from_number(rrc_ue->rnti); - mob_info.rr_cfg_common.pusch_cfg_common = target_cell.sib2.rr_cfg_common.pusch_cfg_common; - mob_info.rr_cfg_common.prach_cfg.root_seq_idx = target_cell.sib2.rr_cfg_common.prach_cfg.root_seq_idx; - mob_info.rr_cfg_common.ul_cp_len = target_cell.sib2.rr_cfg_common.ul_cp_len; - mob_info.rr_cfg_common.p_max_present = true; - mob_info.rr_cfg_common.p_max = rrc_enb->cfg.sib1.p_max; - mob_info.carrier_freq_present = false; // same frequency handover for now + + mob_info.rr_cfg_common.rach_cfg_common_present = true; + mob_info.rr_cfg_common.rach_cfg_common = target_cell.sib2.rr_cfg_common.rach_cfg_common; + mob_info.rr_cfg_common.prach_cfg.root_seq_idx = target_cell.sib2.rr_cfg_common.prach_cfg.root_seq_idx; + mob_info.rr_cfg_common.pdsch_cfg_common_present = true; + mob_info.rr_cfg_common.pdsch_cfg_common = target_cell.sib2.rr_cfg_common.pdsch_cfg_common; + mob_info.rr_cfg_common.pusch_cfg_common = target_cell.sib2.rr_cfg_common.pusch_cfg_common; + mob_info.rr_cfg_common.pucch_cfg_common_present = true; + mob_info.rr_cfg_common.pucch_cfg_common = target_cell.sib2.rr_cfg_common.pucch_cfg_common; + mob_info.rr_cfg_common.srs_ul_cfg_common_present = true; + mob_info.rr_cfg_common.srs_ul_cfg_common = target_cell.sib2.rr_cfg_common.srs_ul_cfg_common; + mob_info.rr_cfg_common.ul_pwr_ctrl_common_present = true; + mob_info.rr_cfg_common.ul_pwr_ctrl_common = target_cell.sib2.rr_cfg_common.ul_pwr_ctrl_common; + mob_info.rr_cfg_common.p_max_present = true; + mob_info.rr_cfg_common.p_max = rrc_enb->cfg.sib1.p_max; + mob_info.rr_cfg_common.ul_cp_len = target_cell.sib2.rr_cfg_common.ul_cp_len; + + mob_info.carrier_freq_present = false; // same frequency handover for now asn1::number_to_enum(mob_info.carrier_bw.dl_bw, target_cell.mib.dl_bw.to_number()); if (target_cell.cell_cfg.dl_earfcn != src_dl_earfcn) { mob_info.carrier_freq_present = true; From 78d60bc1386034da94b57b4185ea9b2740df9373 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 14:51:56 +0200 Subject: [PATCH 30/56] nas: remove all uses of atomic from 4G and 5G classes the NAS classes aren't thread safe and thread-safety shouldn't be pretended by using atomics. Remove them and add explicit notice. --- srsue/hdr/stack/upper/nas.h | 7 +++++++ srsue/hdr/stack/upper/nas_5g.h | 6 ++++++ srsue/hdr/stack/upper/nas_5gmm_state.h | 6 +++--- srsue/hdr/stack/upper/nas_emm_state.h | 9 ++++----- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index bfb4d2a6a..d919a6050 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -35,6 +35,13 @@ class usim_interface_nas; class gw_interface_nas; class rrc_interface_nas; +/** + * @brief This class implements the NAS layer of a EUTRA UE. + * + * The class is *NOT* thread-safe. + * + */ + class nas : public nas_interface_rrc, public srsran::timer_callback, public nas_base { public: diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index fc13ede48..0695aaf17 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -33,6 +33,12 @@ using srsran::byte_buffer_t; namespace srsue { +/** + * @brief This class implements the NAS layer of a 5G UE. + * + * The class is *NOT* thread-safe. + * + */ class nas_5g : public nas_base, public nas_5g_interface_rrc_nr, public nas_5g_interface_procedures { public: diff --git a/srsue/hdr/stack/upper/nas_5gmm_state.h b/srsue/hdr/stack/upper/nas_5gmm_state.h index 28c5efdbd..b28280b61 100644 --- a/srsue/hdr/stack/upper/nas_5gmm_state.h +++ b/srsue/hdr/stack/upper/nas_5gmm_state.h @@ -74,9 +74,9 @@ public: const std::string get_full_state_text(); private: - std::atomic state{state_t::null}; - std::atomic deregistered_substate{deregistered_substate_t::null}; - std::atomic registered_substate{registered_substate_t::null}; + state_t state = state_t::null; + deregistered_substate_t deregistered_substate = deregistered_substate_t::null; + registered_substate_t registered_substate = registered_substate_t::null; srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS-5G"); }; diff --git a/srsue/hdr/stack/upper/nas_emm_state.h b/srsue/hdr/stack/upper/nas_emm_state.h index e541d10d2..ebb44ee19 100644 --- a/srsue/hdr/stack/upper/nas_emm_state.h +++ b/srsue/hdr/stack/upper/nas_emm_state.h @@ -14,7 +14,6 @@ #define SRSUE_NAS_EMM_STATE_H #include "srsran/srslog/srslog.h" -#include #include namespace srsue { @@ -77,10 +76,10 @@ public: const std::string get_full_state_text(); private: - std::atomic state{state_t::null}; // The GW might require to know the NAS state from another thread - std::atomic deregistered_substate{deregistered_substate_t::null}; - std::atomic registered_substate{registered_substate_t::null}; - srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS"); + state_t state = state_t::null; + deregistered_substate_t deregistered_substate = deregistered_substate_t::null; + registered_substate_t registered_substate = registered_substate_t::null; + srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS"); }; const char* emm_state_text(emm_state_t::state_t type); From 79cdc28015b28e81b2f99c58ea1accc82d1b172a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 14:53:23 +0200 Subject: [PATCH 31/56] nas_test_common: call NAS layer from stack thread context since NAS layers insn't thread safe, all calls must come from the same thread --- srsue/hdr/stack/upper/test/nas_test_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/stack/upper/test/nas_test_common.h b/srsue/hdr/stack/upper/test/nas_test_common.h index faa40bf51..bc88a9e89 100644 --- a/srsue/hdr/stack/upper/test/nas_test_common.h +++ b/srsue/hdr/stack/upper/test/nas_test_common.h @@ -155,7 +155,7 @@ public: } bool switch_on() { - nas->switch_on(); + task_sched.defer_task([this]() { nas->switch_on(); }); return true; } void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); } From 40499e6b6db7dd6c3066b9d308a0da4532a2109e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 15:00:18 +0200 Subject: [PATCH 32/56] ue_stack_lte: use std::atomic for running var --- srsue/hdr/stack/ue_stack_lte.h | 2 +- srsue/src/stack/ue_stack_lte.cc | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index b3916b913..55938bc3c 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -180,7 +180,7 @@ private: const std::chrono::milliseconds TTI_WARN_THRESHOLD_MS{5}; const uint32_t SYNC_QUEUE_WARN_THRESHOLD = 5; - bool running; + std::atomic running{false}; srsue::stack_args_t args; srsran::tti_point current_tti; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 3d84ea6ab..e65144b96 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -25,7 +25,6 @@ using namespace srsran; namespace srsue { ue_stack_lte::ue_stack_lte() : - running(false), args(), stack_logger(srslog::fetch_basic_logger("STCK", false)), mac_logger(srslog::fetch_basic_logger("MAC")), @@ -40,8 +39,6 @@ ue_stack_lte::ue_stack_lte() : pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", false)), mac_pcap(), mac_nr_pcap(), - usim(nullptr), - phy(nullptr), rlc("RLC"), mac("MAC", &task_sched), rrc(this, &task_sched), From e1776f8d28938b801570faf702bb49ed39792cea Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 15:00:51 +0200 Subject: [PATCH 33/56] ue,phy: update the PRACH params inside the lambda that also executes the reconfig setting the new PRACH params (writing the the local var) needs to protected as well because it is called from the RRC context and the PHY worker will call configure_prach_params() if it sees changes to it. --- srsue/src/phy/phy.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index da093bd7c..288df38f2 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -454,16 +454,16 @@ bool phy::set_config(const srsran::phy_cfg_t& config_, uint32_t cc_idx) Info("Setting configuration"); - // The PRACH configuration shall be updated only if: - // - The new configuration belongs to the primary cell - // - The PRACH configuration is present - if (!cc_idx && config_.prach_cfg_present) { - prach_cfg = config_.prach_cfg; - prach_cfg.tdd_config = tdd_config; - } - // Apply configurations asynchronously to avoid race conditions cmd_worker.add_cmd([this, config_, cc_idx]() { + // The PRACH configuration shall be updated only if: + // - The new configuration belongs to the primary cell + // - The PRACH configuration is present + if (!cc_idx && config_.prach_cfg_present) { + prach_cfg = config_.prach_cfg; + prach_cfg.tdd_config = tdd_config; + } + logger_phy.info("Setting new PHY configuration cc_idx=%d...", cc_idx); lte_workers.set_config(cc_idx, config_); From aa43e3c8d61457dbbca1dc0d2896752de06b9f1d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 15:03:05 +0200 Subject: [PATCH 34/56] ue,mac: adding missing mutex when updating metrics --- srsue/src/stack/mac/mac.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index 4ee3d5e55..0cfe6b663 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -493,15 +493,19 @@ void mac::new_grant_ul(uint32_t cc_idx, } ul_harq.at(cc_idx)->new_grant_ul(grant, action); - metrics[cc_idx].tx_pkts++; - if (grant.phich_available) { - if (!grant.hi_value) { - metrics[cc_idx].tx_errors++; - } else { - metrics[cc_idx].tx_brate += ul_harq.at(cc_idx)->get_current_tbs(grant.pid) * 8; + { + std::lock_guard lock(metrics_mutex); + metrics[cc_idx].tx_pkts++; + + if (grant.phich_available) { + if (!grant.hi_value) { + metrics[cc_idx].tx_errors++; + } else { + metrics[cc_idx].tx_brate += ul_harq.at(cc_idx)->get_current_tbs(grant.pid) * 8; + } } - } + } // end of holding metrics mutex } void mac::new_mch_dl(const srsran_pdsch_grant_t& phy_grant, tb_action_dl_t* action) @@ -623,6 +627,8 @@ void mac::mch_start_rx(uint32_t lcid) void mac::get_metrics(mac_metrics_t m[SRSRAN_MAX_CARRIERS]) { + std::lock_guard lock(metrics_mutex); + int tx_pkts = 0; int tx_errors = 0; int tx_brate = 0; From 4ef1ac264922c26232f75f3eec1abf52f4d3ff12 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 15:03:51 +0200 Subject: [PATCH 35/56] gw: (re-)use class mutex when updating the DL/UL metrics --- srsue/src/stack/upper/gw.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index af75a7438..2df179468 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -88,6 +88,8 @@ void gw::stop() void gw::get_metrics(gw_metrics_t& m, const uint32_t nof_tti) { + std::lock_guard lock(gw_mutex); + std::chrono::duration secs = std::chrono::high_resolution_clock::now() - metrics_tp; double dl_tput_mbps_real_time = (dl_tput_bytes * 8 / (double)1e6) / secs.count(); @@ -115,7 +117,10 @@ void gw::get_metrics(gw_metrics_t& m, const uint32_t nof_tti) void gw::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) { logger.info(pdu->msg, pdu->N_bytes, "RX PDU. Stack latency: %ld us", pdu->get_latency_us().count()); - dl_tput_bytes += pdu->N_bytes; + { + std::unique_lock lock(gw_mutex); + dl_tput_bytes += pdu->N_bytes; + } if (!if_up) { logger.warning("TUN/TAP not up - dropping gw RX message"); } else if (pdu->N_bytes < 20) { @@ -143,7 +148,10 @@ void gw::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) "RX MCH PDU (%d B). Stack latency: %ld us", pdu->N_bytes, pdu->get_latency_us().count()); - dl_tput_bytes += pdu->N_bytes; + { + std::unique_lock lock(gw_mutex); + dl_tput_bytes += pdu->N_bytes; + } // Hack to drop initial 2 bytes pdu->msg += 2; From 9bf74843f6e83006dc723ebd7d469ec140d3202d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 18:01:42 +0200 Subject: [PATCH 36/56] mac_pdu_nr: add error handling to init_tx() method check provided byte_buffer and return error if it's not valid --- lib/include/srsran/mac/mac_sch_pdu_nr.h | 2 +- lib/src/mac/mac_sch_pdu_nr.cc | 7 ++++++- srsenb/src/stack/mac/nr/ue_nr.cc | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/include/srsran/mac/mac_sch_pdu_nr.h b/lib/include/srsran/mac/mac_sch_pdu_nr.h index 08da38bca..197612d39 100644 --- a/lib/include/srsran/mac/mac_sch_pdu_nr.h +++ b/lib/include/srsran/mac/mac_sch_pdu_nr.h @@ -128,7 +128,7 @@ public: const mac_sch_subpdu_nr& get_subpdu(const uint32_t& index); bool is_ulsch(); - void init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool is_ulsch_ = false); + int init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool is_ulsch_ = false); void init_rx(bool ulsch_ = false); // Add SDU or CEs to PDU diff --git a/lib/src/mac/mac_sch_pdu_nr.cc b/lib/src/mac/mac_sch_pdu_nr.cc index e06b50831..17c5f93a1 100644 --- a/lib/src/mac/mac_sch_pdu_nr.cc +++ b/lib/src/mac/mac_sch_pdu_nr.cc @@ -334,13 +334,18 @@ bool mac_sch_pdu_nr::is_ulsch() return ulsch; } -void mac_sch_pdu_nr::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool ulsch_) +int mac_sch_pdu_nr::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool ulsch_) { + if (buffer_ == nullptr || buffer_->msg == nullptr) { + logger.error("Invalid buffer"); + return SRSRAN_ERROR; + } buffer = buffer_; subpdus.clear(); pdu_len = pdu_len_; remaining_len = pdu_len_; ulsch = ulsch_; + return SRSRAN_SUCCESS; } void mac_sch_pdu_nr::init_rx(bool ulsch_) diff --git a/srsenb/src/stack/mac/nr/ue_nr.cc b/srsenb/src/stack/mac/nr/ue_nr.cc index 26a48d126..c124e41e8 100644 --- a/srsenb/src/stack/mac/nr/ue_nr.cc +++ b/srsenb/src/stack/mac/nr/ue_nr.cc @@ -111,7 +111,10 @@ int ue_nr::generate_pdu(srsran::byte_buffer_t* pdu, uint32_t grant_size) { std::lock_guard lock(mutex); - mac_pdu_dl.init_tx(pdu, grant_size); + if (mac_pdu_dl.init_tx(pdu, grant_size) != SRSRAN_SUCCESS) { + logger.error("Couldn't initialize MAC PDU buffer"); + return SRSRAN_ERROR; + } // read RLC PDU ue_rlc_buffer->clear(); From f20e131083bd796aff72e2d5e52f09b8bde5609a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 18:02:41 +0200 Subject: [PATCH 37/56] mac_nr: when reserving RNTI in MAC, don't automatically reserve it in RRC we assume that RRC itself will reserve the RNTI if it needs to --- srsenb/src/stack/mac/nr/mac_nr.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 1ed756142..eb314cd25 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -125,12 +125,6 @@ uint16_t mac_nr::reserve_rnti(uint32_t enb_cc_idx) ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; sched.ue_cfg(rnti, ue_cfg); - // Register new user in RRC - if (rrc->add_user(rnti) == SRSRAN_ERROR) { - // ue_rem(rnti); - return SRSRAN_SUCCESS; - } - return rnti; } From a80fdc0703981e5967b19da9a9547f9370657141 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 30 Aug 2021 18:03:30 +0200 Subject: [PATCH 38/56] mac_nr: set logger slot context in get_dl_sched() --- srsenb/src/stack/mac/nr/mac_nr.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index eb314cd25..5320bf9da 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -253,6 +253,8 @@ int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { + logger.set_context(slot_cfg.idx); + if (not pdsch_slot.valid()) { pdsch_slot = srsran::slot_point{NUMEROLOGY_IDX, slot_cfg.idx}; } else { From 01390a73400e16d42c72a05167ddd994c8b1e3fa Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Aug 2021 16:23:10 +0200 Subject: [PATCH 39/56] Better NR softbuffer size adjustment --- lib/include/srsran/phy/common/phy_common_nr.h | 6 +++++- lib/include/srsran/phy/fec/ldpc/base_graph.h | 8 +++----- lib/include/srsran/phy/phch/sch_nr.h | 6 +++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index bf8270082..7cd174c82 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -36,7 +36,6 @@ extern "C" { #define SRSRAN_SF_LEN_PRB_NR(nof_prb) (srsran_min_symbol_sz_rb(nof_prb) * 15) #define SRSRAN_SLOT_MAX_LEN_RE_NR (SRSRAN_SLOT_LEN_RE_NR(SRSRAN_MAX_PRB_NR)) -#define SRSRAN_SLOT_MAX_NOF_BITS_NR (SRSRAN_SLOT_MAX_LEN_RE_NR * SRSRAN_MAX_QM) #define SRSRAN_MAX_LAYERS_NR 8 /** @@ -114,6 +113,11 @@ extern "C" { */ #define SRSRAN_PDSCH_MAX_RE_NR (SRSRAN_MAX_NRE_NR * SRSRAN_MAX_PRB_NR) +/** + * @brief defines the maximum number of bits that can be transmitted in a slot + */ +#define SRSRAN_SLOT_MAX_NOF_BITS_NR (SRSRAN_PDSCH_MAX_RE_NR * SRSRAN_MAX_QM) + /** * @brief Maximum number of PDSCH time domain resource allocations. This is defined by TS 38.331 v15.10.0 * as maxNrofDL-Allocations diff --git a/lib/include/srsran/phy/fec/ldpc/base_graph.h b/lib/include/srsran/phy/fec/ldpc/base_graph.h index 3c8699b97..594e84370 100644 --- a/lib/include/srsran/phy/fec/ldpc/base_graph.h +++ b/lib/include/srsran/phy/fec/ldpc/base_graph.h @@ -32,11 +32,9 @@ #include -#define SRSRAN_LDPC_BG1_MAX_LEN_CB 8448 /*!< \brief Maximum code block size for LDPC BG1 */ -#define SRSRAN_LDPC_BG2_MAX_LEN_CB 3840 /*!< \brief Maximum code block size for LDPC BG2 */ -#define SRSRAN_LDPC_MAX_LEN_CB \ - SRSRAN_MAX(SRSRAN_LDPC_BG1_MAX_LEN_CB, \ - SRSRAN_LDPC_BG2_MAX_LEN_CB) /*!< \brief Maximum code block size for LDPC BG1 or BG2 */ +#define SRSRAN_LDPC_BG1_MAX_LEN_CB 8448 /*!< \brief Maximum code block size for LDPC BG1 */ +#define SRSRAN_LDPC_BG2_MAX_LEN_CB 3840 /*!< \brief Maximum code block size for LDPC BG2 */ +#define SRSRAN_LDPC_MAX_LEN_CB SRSRAN_LDPC_BG1_MAX_LEN_CB /*!< \brief Maximum code block size for LDPC BG1 or BG2 */ #define BG1Nfull 68 /*!< \brief Number of variable nodes in BG1. */ #define BG1N 66 /*!< \brief Number of variable nodes in BG1 after puncturing. */ diff --git a/lib/include/srsran/phy/phch/sch_nr.h b/lib/include/srsran/phy/phch/sch_nr.h index 68819b863..87ff204b4 100644 --- a/lib/include/srsran/phy/phch/sch_nr.h +++ b/lib/include/srsran/phy/phch/sch_nr.h @@ -29,8 +29,12 @@ #include "srsran/phy/fec/ldpc/ldpc_rm.h" #include "srsran/phy/phch/phch_cfg_nr.h" +/** + * @brief Maximum number of codeblocks for a NR shared channel transmission. It assumes a rate of 1.0 for the maximum + * amount of bits a resource grid can fit + */ #define SRSRAN_SCH_NR_MAX_NOF_CB_LDPC \ - ((SRSRAN_SLOT_MAX_NOF_BITS_NR + (SRSRAN_LDPC_BG2_MAX_LEN_CB - 1)) / SRSRAN_LDPC_BG2_MAX_LEN_CB) + ((SRSRAN_SLOT_MAX_NOF_BITS_NR + (SRSRAN_LDPC_MAX_LEN_CB - 1)) / SRSRAN_LDPC_MAX_LEN_CB) /** * @brief Groups NR-PUSCH data for reception From 14a85d31ecfb9e4126de211962f44be8eb55a7ac Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Aug 2021 16:23:37 +0200 Subject: [PATCH 40/56] Fix symbol size simensioning for LTE standard rate --- lib/src/phy/common/phy_common_nr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 3dbc974e7..5b4096e83 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -194,6 +194,9 @@ uint32_t srsran_min_symbol_sz_rb(uint32_t nof_prb) const uint32_t* symbol_table = phy_common_nr_valid_symbol_sz; if (srsran_symbol_size_is_standard()) { symbol_table = phy_common_nr_valid_std_symbol_sz; + + // Add extra RE to ensure a minimum guard band and prevent 100 RB use an FFT size of 1536 + nof_re += (3 * nof_re) / 10; } for (uint32_t i = 0; i < PHY_COMMON_NR_NOF_VALID_SYMB_SZ; i++) { From 54c39d8447338e364d4657c92128613dac6d2f40 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Aug 2021 16:24:13 +0200 Subject: [PATCH 41/56] Set nr_phy_test scheduler logger to the level defined in the arguments --- test/phy/dummy_gnb_stack.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 27efa70c9..e1e943f76 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -334,7 +334,8 @@ public: sched_logger(srslog::fetch_basic_logger("MAC")) { logger.set_level(srslog::str_to_basic_level(args.log_level)); - sched_logger.set_level(srslog::basic_levels::debug); + sched_logger.set_level(srslog::str_to_basic_level(args.log_level)); + srslog::fetch_basic_logger("MAC-NR").set_level(srslog::str_to_basic_level(args.log_level)); // create sched object srsenb::sched_nr_interface::sched_cfg_t sched_cfg{}; From 4858202bf6e0fbe47a194f59b8541e092d4b7775 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Aug 2021 16:37:52 +0200 Subject: [PATCH 42/56] Fix NR symbol size for 270RB --- lib/src/phy/common/phy_common_nr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 5b4096e83..2b80becaf 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -195,8 +195,10 @@ uint32_t srsran_min_symbol_sz_rb(uint32_t nof_prb) if (srsran_symbol_size_is_standard()) { symbol_table = phy_common_nr_valid_std_symbol_sz; - // Add extra RE to ensure a minimum guard band and prevent 100 RB use an FFT size of 1536 - nof_re += (3 * nof_re) / 10; + // Force bandwidths bigger than 79 RB to use 2048 FFT + if (nof_prb > 79 && nof_prb < 1536 / 12) { + return 2048; + } } for (uint32_t i = 0; i < PHY_COMMON_NR_NOF_VALID_SYMB_SZ; i++) { From 9e1669c403b7b3da14156d005cbc48102cd46143 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 31 Aug 2021 15:37:16 +0200 Subject: [PATCH 43/56] Better comments in minimum size symbol selection --- lib/src/phy/common/phy_common_nr.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 2b80becaf..cb8b5e642 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -191,22 +191,31 @@ uint32_t srsran_min_symbol_sz_rb(uint32_t nof_prb) return 0; } + // Select all valid symbol sizes by default const uint32_t* symbol_table = phy_common_nr_valid_symbol_sz; + + // Select standard LTE symbol sizes table if (srsran_symbol_size_is_standard()) { symbol_table = phy_common_nr_valid_std_symbol_sz; - // Force bandwidths bigger than 79 RB to use 2048 FFT - if (nof_prb > 79 && nof_prb < 1536 / 12) { + // As the selected symbol size is the minimum that fits the entire number of RE, 106 RB would select into 1536 point + // symbol size. However, it shall use 2048 point symbol size to match LTE standard rate. Because of this, it forces + // bandwidths bigger than 79 RB that would use 1536 symbol size to select 2048. + if (nof_prb > 79 && nof_prb < 1536 / SRSRAN_NRE) { return 2048; } } + // For each symbol size in the table... for (uint32_t i = 0; i < PHY_COMMON_NR_NOF_VALID_SYMB_SZ; i++) { + // Check if the number of RE fit in the symbol if (symbol_table[i] > nof_re) { + // Returns the smallest symbol size that fits the number of RE return symbol_table[i]; } } + // The number of RE exceeds the maximum symbol size return 0; } From 2fb2598f8c067cca787f707318fab5f934aa76b9 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 30 Aug 2021 12:14:25 +0200 Subject: [PATCH 44/56] sched,nr: avoid extra copy of DL result and other small fixes --- srsenb/hdr/stack/mac/nr/sched_nr.h | 5 +- srsenb/hdr/stack/mac/nr/sched_nr_cell.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 9 +-- .../stack/mac/nr/sched_nr_grant_allocator.h | 36 +++++------ srsenb/hdr/stack/mac/nr/sched_nr_helpers.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 5 +- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 3 +- srsenb/src/stack/mac/nr/sched_nr.cc | 59 +++++-------------- srsenb/src/stack/mac/nr/sched_nr_cell.cc | 6 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 7 ++- .../stack/mac/nr/sched_nr_grant_allocator.cc | 47 ++++++++------- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 19 ++---- srsenb/test/mac/nr/sched_nr_rar_test.cc | 2 +- 13 files changed, 88 insertions(+), 113 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index a62311ab6..0fcddcd84 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -31,7 +31,7 @@ class serv_cell_manager; } // namespace sched_nr_impl class ue_event_manager; -class sched_result_manager; +class ul_sched_result_buffer; class sched_nr final : public sched_nr_interface { @@ -51,7 +51,6 @@ public: int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) override; private: - int generate_slot_result(slot_point pdcch_tti, uint32_t cc); void ue_cfg_impl(uint16_t rnti, const ue_cfg_t& cfg); // args @@ -66,7 +65,7 @@ private: ue_map_t ue_db; // management of Sched Result buffering - std::unique_ptr pending_results; + std::unique_ptr pending_results; // management of cell resources std::vector > cells; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h index 02ada6f30..d07a00253 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -57,7 +57,7 @@ public: int dl_rach_info(const dl_sched_rar_info_t& rar_info); /// Allocate pending RARs - void run_slot(bwp_slot_allocator& slot_grid); + void run_slot(bwp_slot_allocator& slot_alloc); /// Check if there are pending RARs bool empty() const { return pending_rars.empty(); } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 65dbcd0f7..a236c12f2 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -53,8 +53,9 @@ struct bwp_params { const sched_cfg_t& sched_cfg; // derived params - uint32_t P; - uint32_t N_rbg; + srslog::basic_logger& logger; + uint32_t P; + uint32_t N_rbg; struct slot_cfg { bool is_dl; @@ -70,9 +71,9 @@ struct bwp_params { }; std::vector pusch_ra_list; - bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); - bwp_cce_pos_list rar_cce_list; + + bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); }; struct sched_cell_params { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 259daae26..17d5d8a0c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -30,9 +30,9 @@ using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t; const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = std::array, MAX_CORESET_PER_BWP>; -using pdsch_t = mac_interface_phy_nr::pdsch_t; -using pdsch_list_t = srsran::bounded_vector; -using rar_list_t = sched_nr_interface::sched_rar_list_t; +using pdsch_t = mac_interface_phy_nr::pdsch_t; +using pdsch_list_t = srsran::bounded_vector; +using sched_rar_list_t = sched_nr_interface::sched_rar_list_t; struct harq_ack_t { const srsran::phy_cfg_nr_t* phy_cfg; @@ -41,18 +41,18 @@ struct harq_ack_t { using harq_ack_list_t = srsran::bounded_vector; struct bwp_slot_grid { - uint32_t slot_idx; - const bwp_params* cfg; - - bwp_rb_bitmap dl_prbs; - bwp_rb_bitmap ul_prbs; - pdcch_dl_list_t dl_pdcchs; - pdcch_ul_list_t ul_pdcchs; - pdsch_list_t pdschs; - rar_list_t rar; - slot_coreset_list coresets; - pusch_list_t puschs; - harq_ack_list_t pending_acks; + uint32_t slot_idx = 0; + const bwp_params* cfg = nullptr; + + bwp_rb_bitmap dl_prbs; + bwp_rb_bitmap ul_prbs; + pdcch_dl_list_t dl_pdcchs; + pdcch_ul_list_t ul_pdcchs; + pdsch_list_t pdschs; + sched_rar_list_t rar; + slot_coreset_list coresets; + pusch_list_t puschs; + harq_ack_list_t pending_acks; srsran::unique_pool_ptr rar_softbuffer; @@ -65,7 +65,7 @@ struct bwp_slot_grid { }; struct bwp_res_grid { - bwp_res_grid(const bwp_params& bwp_cfg_); + explicit bwp_res_grid(const bwp_params& bwp_cfg_); bwp_slot_grid& operator[](slot_point tti) { return slots[tti.to_uint() % slots.capacity()]; }; const bwp_slot_grid& operator[](slot_point tti) const { return slots[tti.to_uint() % slots.capacity()]; }; @@ -78,6 +78,8 @@ private: srsran::bounded_vector slots; }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** * Class responsible for jointly filling the DL/UL sched result fields and allocate RB/PDCCH resources in the RB grid * to avoid potential RB/PDCCH collisions @@ -104,11 +106,11 @@ public: slot_point get_pdcch_tti() const { return pdcch_slot; } slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } const bwp_res_grid& res_grid() const { return bwp_grid; } - void log_bwp_sched_result(); const bwp_params& cfg; private: + alloc_result verify_pdsch_space(bwp_slot_grid& pdsch_grid, bwp_slot_grid& pdcch_grid) const; alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid = nullptr) const; srslog::basic_logger& logger; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h index 53ccc556f..4241fcf96 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h @@ -43,6 +43,7 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_location_t dci_pos, srsran_dci_ul_nr_t& dci); +/// Log Scheduling Result for a given BWP and slot void log_sched_bwp_result(srslog::basic_logger& logger, slot_point pdcch_slot, const bwp_res_grid& res_grid, diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 3ed5fe3d5..daa35b72b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -66,8 +66,9 @@ public: }; struct sched_cfg_t { - bool pdsch_enabled = true; - bool pusch_enabled = true; + bool pdsch_enabled = true; + bool pusch_enabled = true; + std::string logger_name = "MAC"; }; struct ue_cc_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 6ed470fc0..25c8612c2 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -38,8 +38,7 @@ public: explicit slot_cc_worker(serv_cell_manager& sched); - void start(slot_point pdcch_slot, ue_map_t& ue_db_); - void run(); + void run(slot_point pdcch_slot, ue_map_t& ue_db_); void finish(); bool running() const { return slot_rx.valid(); } diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 9dc058e94..a86d6108c 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -24,24 +24,16 @@ static int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class sched_result_manager +class ul_sched_result_buffer { public: - explicit sched_result_manager(uint32_t nof_cc_) + explicit ul_sched_result_buffer(uint32_t nof_cc_) { for (auto& v : results) { v.resize(nof_cc_); } } - dl_sched_res_t& add_dl_result(slot_point tti, uint32_t cc) - { - if (not has_dl_result(tti, cc)) { - results[tti.to_uint()][cc].slot_dl = tti; - results[tti.to_uint()][cc].dl_res = {}; - } - return results[tti.to_uint()][cc].dl_res; - } ul_sched_t& add_ul_result(slot_point tti, uint32_t cc) { if (not has_ul_result(tti, cc)) { @@ -51,19 +43,8 @@ public: return results[tti.to_uint()][cc].ul_res; } - bool has_dl_result(slot_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].slot_dl == tti; } - bool has_ul_result(slot_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].slot_ul == tti; } - dl_sched_res_t pop_dl_result(slot_point tti, uint32_t cc) - { - if (has_dl_result(tti, cc)) { - results[tti.to_uint()][cc].slot_dl.clear(); - return results[tti.to_uint()][cc].dl_res; - } - return {}; - } - ul_sched_t pop_ul_result(slot_point tti, uint32_t cc) { if (has_ul_result(tti, cc)) { @@ -75,10 +56,8 @@ public: private: struct slot_result_t { - slot_point slot_dl; - slot_point slot_ul; - dl_sched_res_t dl_res; - ul_sched_t ul_res; + slot_point slot_ul; + ul_sched_t ul_res; }; srsran::circular_array, TTIMOD_SZ> results; @@ -104,7 +83,7 @@ int sched_nr::cell_cfg(srsran::const_span cell_list) cells.emplace_back(new serv_cell_manager{cfg.cells[cc]}); } - pending_results.reset(new sched_result_manager(cell_list.size())); + pending_results.reset(new ul_sched_result_buffer(cell_list.size())); sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg, cells)); return SRSRAN_SUCCESS; @@ -125,36 +104,28 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) } } -/// Generate {tti,cc} scheduling decision -int sched_nr::generate_slot_result(slot_point pdcch_tti, uint32_t cc) +/// Generate {pdcch_slot,cc} scheduling decision +int sched_nr::get_dl_sched(slot_point slot_dl, uint32_t cc, dl_sched_res_t& result) { - // Copy results to intermediate buffer - dl_sched_res_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); - ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); + // Copy UL results to intermediate buffer + ul_sched_t& ul_res = pending_results->add_ul_result(slot_dl, cc); // Generate {slot_idx,cc} result - sched_workers->run_slot(pdcch_tti, cc, dl_res, ul_res); + sched_workers->run_slot(slot_dl, cc, result, ul_res); return SRSRAN_SUCCESS; } -int sched_nr::get_dl_sched(slot_point slot_tx, uint32_t cc, dl_sched_res_t& result) -{ - if (not pending_results->has_dl_result(slot_tx, cc)) { - generate_slot_result(slot_tx, cc); - } - - result = pending_results->pop_dl_result(slot_tx, cc); - return SRSRAN_SUCCESS; -} -int sched_nr::get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) +/// Fetch {ul_slot,cc} UL scheduling decision +int sched_nr::get_ul_sched(slot_point slot_ul, uint32_t cc, ul_sched_t& result) { - if (not pending_results->has_ul_result(pusch_tti, cc)) { + if (not pending_results->has_ul_result(slot_ul, cc)) { // sched result hasn't been generated + result = {}; return SRSRAN_SUCCESS; } - result = pending_results->pop_ul_result(pusch_tti, cc); + result = pending_results->pop_ul_result(slot_ul, cc); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index 7719d981b..7caa57e97 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -110,9 +110,9 @@ ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_ return ret; } -void ra_sched::run_slot(bwp_slot_allocator& slot_grid) +void ra_sched::run_slot(bwp_slot_allocator& slot_alloc) { - slot_point pdcch_slot = slot_grid.get_pdcch_tti(); + slot_point pdcch_slot = slot_alloc.get_pdcch_tti(); slot_point msg3_slot = pdcch_slot + bwp_cfg->pusch_ra_list[0].msg3_delay; if (not bwp_cfg->slots[pdcch_slot.slot_idx()].is_dl or not bwp_cfg->slots[msg3_slot.slot_idx()].is_ul) { // RAR only allowed if PDCCH is available and respective Msg3 slot is available for UL @@ -143,7 +143,7 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid) // Try to schedule DCIs + RBGs for RAR Grants uint32_t nof_rar_allocs = 0; - alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs); + alloc_result ret = allocate_pending_rar(slot_alloc, rar, nof_rar_allocs); if (ret == alloc_result::success) { // If RAR allocation was successful: diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 91fc5dd7d..1b42e8066 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -21,7 +21,12 @@ namespace srsenb { namespace sched_nr_impl { bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc_, uint32_t bwp_id_) : - cell_cfg(cell), sched_cfg(sched_cfg_), cc(cc_), bwp_id(bwp_id_), cfg(cell.bwps[bwp_id_]) + cell_cfg(cell), + sched_cfg(sched_cfg_), + cc(cc_), + bwp_id(bwp_id_), + cfg(cell.bwps[bwp_id_]), + logger(srslog::fetch_basic_logger(sched_cfg_.logger_name)) { srsran_assert(bwp_id != 0 or cfg.pdcch.coreset_present[0], "CORESET#0 has to be active for initial BWP"); diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index 7368e6abd..7e4c29a43 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -58,7 +58,7 @@ bwp_res_grid::bwp_res_grid(const bwp_params& bwp_cfg_) : cfg(&bwp_cfg_) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : - logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_) + logger(bwp_grid_.cfg->logger), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_) {} alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs) @@ -96,17 +96,13 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t if (ret != alloc_result::success) { return ret; } - - if (bwp_pdcch_slot.dl_pdcchs.full()) { - logger.warning("SCHED: Maximum number of DL allocations reached"); - return alloc_result::no_grant_space; + ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot); + if (ret != alloc_result::success) { + return ret; } // Check DL RB collision - const prb_bitmap& pdsch_mask = bwp_pdcch_slot.dl_prbs.prbs(); - prb_bitmap dl_mask(pdsch_mask.size()); - dl_mask.fill(interv.start(), interv.stop()); - if ((pdsch_mask & dl_mask).any()) { + if (bwp_pdcch_slot.dl_prbs.collides(interv)) { logger.debug("SCHED: Provided RBG mask collides with allocation previously made."); return alloc_result::sch_collision; } @@ -204,14 +200,9 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr bwp_slot_grid& bwp_pdcch_slot = bwp_grid[ue.pdcch_slot]; bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_slot]; bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_slot]; - if (not bwp_pdsch_slot.is_dl()) { - logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx); - return alloc_result::no_sch_space; - } - pdcch_dl_list_t& pdsch_grants = bwp_pdsch_slot.dl_pdcchs; - if (pdsch_grants.full()) { - logger.warning("SCHED: Maximum number of DL allocations reached"); - return alloc_result::no_grant_space; + alloc_result result = verify_pdsch_space(bwp_pdsch_slot, bwp_pdcch_slot); + if (result != alloc_result::success) { + return result; } if (bwp_pdcch_slot.dl_prbs.collides(dl_grant)) { return alloc_result::sch_collision; @@ -335,6 +326,23 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const prb_grant& ul_pr return alloc_result::success; } +alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& bwp_pdsch, bwp_slot_grid& bwp_pdcch) const +{ + if (not bwp_pdsch.is_dl() or not bwp_pdcch.is_dl()) { + logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch.slot_idx); + return alloc_result::no_sch_space; + } + if (bwp_pdcch.dl_pdcchs.full()) { + logger.warning("SCHED: Maximum number of DL PDCCH allocations reached"); + return alloc_result::no_cch_space; + } + if (bwp_pdsch.pdschs.full()) { + logger.warning("SCHED: Maximum number of DL PDSCH grants reached"); + return alloc_result::no_sch_space; + } + return alloc_result::success; +} + alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid) const { if (not pusch_grid.is_ul()) { @@ -359,10 +367,5 @@ alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, b return alloc_result::success; } -void bwp_slot_allocator::log_bwp_sched_result() -{ - log_sched_bwp_result(logger, get_pdcch_tti(), bwp_grid, *slot_ues); -} - } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 63ad19e58..afc93f6a7 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -58,8 +58,8 @@ void slot_cc_worker::run_feedback(ue_map_t& ue_db) tmp_feedback_to_run.clear(); } -/// Called at the beginning of TTI in a locked context, to reserve available UE resources -void slot_cc_worker::start(slot_point pdcch_slot, ue_map_t& ue_db) +/// Called within a locked context, to generate {slot, cc} scheduling decision +void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); slot_rx = pdcch_slot - TX_ENB_DELAY; @@ -85,12 +85,8 @@ void slot_cc_worker::start(slot_point pdcch_slot, ue_map_t& ue_db) } // UE acquired successfully for scheduling in this {slot, cc} } -} - -void slot_cc_worker::run() -{ - srsran_assert(running(), "scheduler worker::run() called for non-active worker"); + // Create an BWP allocator object that will passed along to RA, SI, Data schedulers bwp_alloc.new_slot(slot_rx + TX_ENB_DELAY, slot_ues); // Allocate pending RARs @@ -101,7 +97,7 @@ void slot_cc_worker::run() alloc_ul_ues(); // Log CC scheduler result - bwp_alloc.log_bwp_sched_result(); + log_sched_bwp_result(logger, bwp_alloc.get_pdcch_tti(), cell.bwps[0].grid, slot_ues); // releases UE resources slot_ues.clear(); @@ -207,11 +203,8 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_re } } - // process pending feedback and pre-cache UE state for slot decision - cc_worker_list[cc]->worker.start(slot_tx, ue_db); - - // Get {slot, cc} scheduling decision - cc_worker_list[cc]->worker.run(); + // process pending feedback, generate {slot, cc} scheduling decision + cc_worker_list[cc]->worker.run(slot_tx, ue_db); // decrement the number of active workers int rem_workers = worker_count.fetch_sub(1, std::memory_order_release) - 1; diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index e6edac3ea..e4ef8ff56 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -58,7 +58,7 @@ void test_single_prach() alloc.new_slot(pdcch_slot, slot_ues); rasched.run_slot(alloc); - alloc.log_bwp_sched_result(); + log_sched_bwp_result(mac_logger, alloc.get_pdcch_tti(), alloc.res_grid(), slot_ues); const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()]; test_dl_pdcch_consistency(result->dl_pdcchs); ++pdcch_slot; From de06dbc684f7d8e12fc22d12293e6494ef3f6e85 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 31 Aug 2021 18:26:38 +0200 Subject: [PATCH 45/56] sched,nr: implemented basic UE buffer status manager --- srsenb/hdr/stack/mac/common/sched_config.h | 37 ++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 9 ++- .../stack/mac/nr/sched_nr_ue_buffer_manager.h | 66 +++++++++++++++++ srsenb/src/stack/mac/nr/CMakeLists.txt | 3 +- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 3 +- .../mac/nr/sched_nr_ue_buffer_manager.cc | 70 +++++++++++++++++++ 6 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 srsenb/hdr/stack/mac/common/sched_config.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h create mode 100644 srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc diff --git a/srsenb/hdr/stack/mac/common/sched_config.h b/srsenb/hdr/stack/mac/common/sched_config.h new file mode 100644 index 000000000..94bdf663c --- /dev/null +++ b/srsenb/hdr/stack/mac/common/sched_config.h @@ -0,0 +1,37 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_CONFIG_H +#define SRSRAN_SCHED_CONFIG_H + +#include + +namespace srsenb { + +/** + * Structure used in UE logical channel configuration + */ +struct logical_channel_cfg_t { + enum direction_t { IDLE = 0, UL, DL, BOTH } direction = IDLE; + int priority = 1; // channel priority (1 is highest) + uint32_t bsd = 1000; // msec + uint32_t pbr = -1; // prioritised bit rate + int group = 0; // logical channel group + + bool is_active() const { return direction != IDLE; } + bool is_dl() const { return direction == DL or direction == BOTH; } + bool is_ul() const { return direction == UL or direction == BOTH; } +}; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_CONFIG_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 678708486..79f0d503e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -16,6 +16,7 @@ #include "sched_nr_cfg.h" #include "sched_nr_harq.h" #include "sched_nr_interface.h" +#include "sched_nr_ue_buffer_manager.h" #include "srsran/adt/circular_map.h" #include "srsran/adt/move_callback.h" #include "srsran/adt/pool/cached_alloc.h" @@ -52,8 +53,8 @@ public: slot_point uci_slot; uint32_t dl_cqi = 0; uint32_t ul_cqi = 0; - dl_harq_proc* h_dl = nullptr; - ul_harq_proc* h_ul = nullptr; + dl_harq_proc* h_dl = nullptr; + ul_harq_proc* h_ul = nullptr; }; class ue_carrier @@ -88,6 +89,7 @@ public: const ue_cfg_t& cfg() const { return ue_cfg; } void ul_sr_info(slot_point slot_rx) { pending_sr = true; } + void ul_bsr(uint32_t lcg, uint32_t bsr_val) { buffers.ul_bsr(lcg, bsr_val); } bool has_ca() const { return ue_cfg.carriers.size() > 1; } uint32_t pcell_cc() const { return ue_cfg.carriers[0].cc; } @@ -98,7 +100,8 @@ private: const uint16_t rnti; const sched_params& sched_cfg; - bool pending_sr = false; + bool pending_sr = false; + ue_buffer_manager buffers; ue_cfg_t ue_cfg; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h new file mode 100644 index 000000000..ec88132c0 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h @@ -0,0 +1,66 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H +#define SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H + +#include "srsenb/hdr/stack/mac/common/sched_config.h" +#include "srsran/srslog/srslog.h" +#include "srsran/support/srsran_assert.h" + +namespace srsenb { +namespace sched_nr_impl { + +class ue_buffer_manager +{ + const static uint32_t MAX_LCG_ID = 7; + const static uint32_t MAX_LC_ID = 32; + const static uint32_t MAX_SRB_LC_ID = 3; + +public: + explicit ue_buffer_manager(srslog::basic_logger& logger_); + + // Configuration getters + bool is_channel_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); } + bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); } + bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); } + const logical_channel_cfg_t& get_cfg(uint32_t lcid) const + { + srsran_assert(lcid < MAX_LC_ID, "Provided LCID=%d is above limit=%d", lcid, MAX_LC_ID); + return channels[lcid].cfg; + } + + // Buffer Status update + void ul_bsr(uint32_t lcg_id, uint32_t val); + void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue); + + // UL BSR methods + bool is_lcg_active(uint32_t lcg) const; + int get_bsr(uint32_t lcg) const; + +private: + srslog::basic_logger& logger; + + struct logical_channel { + logical_channel_cfg_t cfg; + int buf_tx = 0; + int buf_retx = 0; + }; + std::array channels; + + std::array lcg_bsr{0}; +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 7d3c3f536..5ca49c739 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -19,6 +19,7 @@ set(SOURCES mac_nr.cc sched_nr_cell.cc sched_nr_rb.cc sched_nr_time_rr.cc - harq_softbuffer.cc) + harq_softbuffer.cc + sched_nr_ue_buffer_manager.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index f0ad196d9..6d3cf5509 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -12,6 +12,7 @@ #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsran/common/string_helpers.h" namespace srsenb { namespace sched_nr_impl { @@ -83,7 +84,7 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : - rnti(rnti_), sched_cfg(sched_cfg_), ue_cfg(cfg) + rnti(rnti_), sched_cfg(sched_cfg_), ue_cfg(cfg), buffers(srslog::fetch_basic_logger(sched_cfg_.sched_cfg.logger_name)) { for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc b/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc new file mode 100644 index 000000000..ac0a27b55 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc @@ -0,0 +1,70 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h" +#include "srsran/common/string_helpers.h" +#include "srsran/srslog/bundled/fmt/format.h" +#include "srsran/srslog/bundled/fmt/ranges.h" + +namespace srsenb { +namespace sched_nr_impl { + +ue_buffer_manager::ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_) {} + +bool ue_buffer_manager::is_lcg_active(uint32_t lcg) const +{ + if (lcg == 0) { + return true; + } + for (uint32_t lcid = 0; lcid < MAX_LC_ID; ++lcid) { + if (is_bearer_ul(lcid) and channels[lcid].cfg.group == (int)lcg) { + return true; + } + } + return false; +} + +int ue_buffer_manager::get_bsr(uint32_t lcg) const +{ + return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0; +} + +void ue_buffer_manager::ul_bsr(uint32_t lcg_id, uint32_t val) +{ + srsran_assert(lcg_id < MAX_LCG_ID, "Provided LCG_ID=%d is above its limit=%d", lcg_id, MAX_LCG_ID); + lcg_bsr[lcg_id] = val; + + if (logger.debug.enabled()) { + fmt::memory_buffer str_buffer; + fmt::format_to(str_buffer, "{}", lcg_bsr); + logger.debug("SCHED: lcg_id=%d, bsr=%s. Current state=%s", lcg_id, val, srsran::to_c_str(str_buffer)); + } +} + +void ue_buffer_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue) +{ + if (lcid >= MAX_LC_ID) { + logger.warning("The provided lcid=%d is not valid", lcid); + return; + } + if (lcid <= MAX_SRB_LC_ID and + (channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) { + logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); + } else { + logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); + } + channels[lcid].buf_retx = retx_queue; + channels[lcid].buf_tx = tx_queue; +} + +} // namespace sched_nr_impl +} // namespace srsenb From 020bec025e1053f837eef80c5b2cb5ef840ce1c0 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 1 Sep 2021 11:02:36 +0200 Subject: [PATCH 46/56] sched: created class common to LTE and NR for ue buffer status management --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 +- lib/include/srsran/asn1/rrc_utils.h | 2 +- lib/include/srsran/common/common_nr.h | 2 +- .../srsran/interfaces/enb_mac_interfaces.h | 10 +- .../srsran/interfaces/enb_rrc_interfaces.h | 2 +- .../srsran/interfaces/gnb_interfaces.h | 2 +- srsenb/hdr/enb.h | 2 +- srsenb/hdr/stack/mac/common/sched_config.h | 24 ++- .../hdr/stack/mac/common/ue_buffer_manager.h | 95 +++++++++++ srsenb/hdr/stack/mac/mac.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 6 +- .../stack/mac/nr/sched_nr_ue_buffer_manager.h | 66 -------- srsenb/hdr/stack/mac/nr/ue_nr.h | 2 +- srsenb/hdr/stack/mac/sched.h | 4 +- srsenb/hdr/stack/mac/sched_grid.h | 2 +- srsenb/hdr/stack/mac/sched_helpers.h | 4 +- .../hdr/stack/mac}/sched_interface.h | 13 +- srsenb/hdr/stack/mac/sched_lte_common.h | 2 +- srsenb/hdr/stack/mac/sched_ue.h | 5 +- .../hdr/stack/mac/sched_ue_ctrl/sched_harq.h | 2 +- .../hdr/stack/mac/sched_ue_ctrl/sched_lch.h | 56 +++---- srsenb/hdr/stack/mac/ue.h | 2 +- srsenb/hdr/stack/rrc/mac_controller.h | 4 +- srsenb/hdr/stack/rrc/rrc_ue.h | 2 +- srsenb/src/stack/mac/CMakeLists.txt | 3 + srsenb/src/stack/mac/common/CMakeLists.txt | 10 ++ .../src/stack/mac/common/ue_buffer_manager.cc | 116 +++++++++++++ srsenb/src/stack/mac/mac.cc | 4 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 4 +- .../mac/nr/sched_nr_ue_buffer_manager.cc | 70 -------- srsenb/src/stack/mac/sched.cc | 2 +- srsenb/src/stack/mac/sched_helpers.cc | 16 -- srsenb/src/stack/mac/sched_ue.cc | 6 +- .../src/stack/mac/sched_ue_ctrl/sched_lch.cc | 157 +++--------------- .../stack/mac/sched_ue_ctrl/sched_ue_cell.cc | 2 +- srsenb/src/stack/rrc/mac_controller.cc | 32 ++-- srsenb/src/stack/rrc/rrc.cc | 2 +- srsenb/src/stack/rrc/rrc_mobility.cc | 2 +- srsenb/src/stack/rrc/rrc_ue.cc | 10 +- srsenb/test/common/dummy_classes.h | 2 +- srsenb/test/mac/sched_common_test_suite.h | 2 +- srsenb/test/mac/sched_lc_ch_test.cc | 12 +- srsenb/test/mac/sched_sim_ue.cc | 4 +- srsenb/test/mac/sched_sim_ue.h | 6 +- srsenb/test/mac/sched_test_rand.cc | 2 +- srsenb/test/mac/sched_test_utils.h | 38 ++--- srsenb/test/rrc/rrc_mobility_test.cc | 21 +-- 47 files changed, 397 insertions(+), 441 deletions(-) create mode 100644 srsenb/hdr/stack/mac/common/ue_buffer_manager.h delete mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h rename {lib/include/srsran/interfaces => srsenb/hdr/stack/mac}/sched_interface.h (96%) create mode 100644 srsenb/src/stack/mac/common/CMakeLists.txt create mode 100644 srsenb/src/stack/mac/common/ue_buffer_manager.cc delete mode 100644 srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 9d88feb82..bb5ad0326 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -13,11 +13,11 @@ #ifndef SRSRAN_RRC_NR_UTILS_H #define SRSRAN_RRC_NR_UTILS_H +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/phy_cfg_nr.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/interfaces/rlc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" /************************ * Forward declarations diff --git a/lib/include/srsran/asn1/rrc_utils.h b/lib/include/srsran/asn1/rrc_utils.h index 18d4a4b4a..58f3d58a5 100644 --- a/lib/include/srsran/asn1/rrc_utils.h +++ b/lib/include/srsran/asn1/rrc_utils.h @@ -13,11 +13,11 @@ #ifndef SRSRAN_RRC_UTILS_H #define SRSRAN_RRC_UTILS_H +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/interfaces/rlc_interface_types.h" #include "srsran/interfaces/rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" /************************ * Forward declarations diff --git a/lib/include/srsran/common/common_nr.h b/lib/include/srsran/common/common_nr.h index 0257938e3..17e9e2521 100644 --- a/lib/include/srsran/common/common_nr.h +++ b/lib/include/srsran/common/common_nr.h @@ -55,7 +55,7 @@ enum class nr_drb { invalid }; const uint32_t MAX_NR_DRB_ID = 29; -const uint32_t MAX_NR_NOF_BEARERS = MAX_NR_DRB_ID + MAX_NR_SRB_ID; +const uint32_t MAX_NR_NOF_BEARERS = MAX_NR_DRB_ID + MAX_NR_SRB_ID; // 32 constexpr bool is_nr_lcid(uint32_t lcid) { diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 9e2ea5673..ba13e75dc 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -10,8 +10,8 @@ * */ +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/interfaces/rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" #ifndef SRSRAN_ENB_MAC_INTERFACES_H #define SRSRAN_ENB_MAC_INTERFACES_H @@ -239,14 +239,14 @@ public: virtual int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) = 0; /* Manages UE bearers and associated configuration */ - virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) = 0; - virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; - virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0; + virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, mac_lc_ch_cfg_t* cfg) = 0; + virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; + virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0; virtual void write_mcch(const srsran::sib2_mbms_t* sib2_, const srsran::sib13_t* sib13_, const srsran::mcch_msg_t* mcch_, const uint8_t* mcch_payload, - const uint8_t mcch_payload_length) = 0; + const uint8_t mcch_payload_length) = 0; /** * Allocate a C-RNTI for a new user, without adding it to the phy layer and scheduler yet diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index 4948b1a47..85f961080 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -10,9 +10,9 @@ * */ +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/asn1/s1ap_utils.h" #include "srsran/interfaces/enb_rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" #ifndef SRSRAN_ENB_RRC_INTERFACES_H #define SRSRAN_ENB_RRC_INTERFACES_H diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 5faf4945b..d7116276c 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -15,12 +15,12 @@ #include "srsran/srsran.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/interfaces_common.h" #include "srsran/common/security.h" #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/interfaces/rlc_interface_types.h" #include "srsran/interfaces/rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" // EUTRA interfaces that are used unmodified #include "srsran/interfaces/enb_mac_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 1974b3901..a04a72c43 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -31,6 +31,7 @@ #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/rrc/rrc_config.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/bcd_helpers.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/interfaces_common.h" @@ -38,7 +39,6 @@ #include "srsran/common/security.h" #include "srsran/interfaces/enb_command_interface.h" #include "srsran/interfaces/enb_metrics_interface.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/interfaces/ue_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsran/system/sys_metrics_processor.h" diff --git a/srsenb/hdr/stack/mac/common/sched_config.h b/srsenb/hdr/stack/mac/common/sched_config.h index 94bdf663c..3a16ee158 100644 --- a/srsenb/hdr/stack/mac/common/sched_config.h +++ b/srsenb/hdr/stack/mac/common/sched_config.h @@ -20,7 +20,7 @@ namespace srsenb { /** * Structure used in UE logical channel configuration */ -struct logical_channel_cfg_t { +struct mac_lc_ch_cfg_t { enum direction_t { IDLE = 0, UL, DL, BOTH } direction = IDLE; int priority = 1; // channel priority (1 is highest) uint32_t bsd = 1000; // msec @@ -30,8 +30,30 @@ struct logical_channel_cfg_t { bool is_active() const { return direction != IDLE; } bool is_dl() const { return direction == DL or direction == BOTH; } bool is_ul() const { return direction == UL or direction == BOTH; } + bool operator==(const mac_lc_ch_cfg_t& other) const + { + return direction == other.direction and priority == other.priority and bsd == other.bsd and pbr == other.pbr and + group == other.group; + } + bool operator!=(const mac_lc_ch_cfg_t& other) const { return not(*this == other); } }; +inline const char* to_string(mac_lc_ch_cfg_t::direction_t dir) +{ + switch (dir) { + case mac_lc_ch_cfg_t::direction_t::IDLE: + return "idle"; + case mac_lc_ch_cfg_t::direction_t::BOTH: + return "bi-dir"; + case mac_lc_ch_cfg_t::direction_t::DL: + return "DL"; + case mac_lc_ch_cfg_t::direction_t::UL: + return "UL"; + default: + return "unrecognized direction"; + } +} + } // namespace srsenb #endif // SRSRAN_SCHED_CONFIG_H diff --git a/srsenb/hdr/stack/mac/common/ue_buffer_manager.h b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h new file mode 100644 index 000000000..ea722b8be --- /dev/null +++ b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h @@ -0,0 +1,95 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_UE_BUFFER_MANAGER_H +#define SRSRAN_UE_BUFFER_MANAGER_H + +#include "sched_config.h" +#include "srsran/common/common_lte.h" +#include "srsran/common/common_nr.h" +#include "srsran/srslog/srslog.h" +#include "srsran/support/srsran_assert.h" + +namespace srsenb { + +/** + * Class to handle UE DL+UL RLC and MAC buffers state + */ +template +class ue_buffer_manager +{ +protected: + const static uint32_t MAX_LC_ID = isNR ? srsran::MAX_NR_NOF_BEARERS : srsran::MAX_LTE_LCID; + const static uint32_t MAX_LCG_ID = isNR ? 7 : 3; + const static uint32_t MAX_SRB_LC_ID = isNR ? srsran::MAX_NR_SRB_ID : srsran::MAX_LTE_SRB_ID; + const static uint32_t MAX_NOF_LCIDS = MAX_LC_ID + 1; + const static uint32_t MAX_NOF_LCGS = MAX_LCG_ID + 1; + constexpr static uint32_t pbr_infinity = -1; + +public: + explicit ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_) {} + + // Bearer configuration + void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg); + + // Buffer Status update + void ul_bsr(uint32_t lcg_id, uint32_t val); + void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue); + + // Configuration getters + bool is_bearer_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); } + bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); } + bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); } + const mac_lc_ch_cfg_t& get_cfg(uint32_t lcid) const + { + srsran_assert(is_lcid_valid(lcid), "Provided LCID=%d is above limit=%d", lcid, MAX_LC_ID); + return channels[lcid].cfg; + } + + /// DL newtx buffer status for given LCID (no RLC overhead included) + int get_dl_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_tx : 0; } + + /// DL retx buffer status for given LCID (no RLC overhead included) + int get_dl_retx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_retx : 0; } + + /// Sum of DL RLC newtx and retx buffer status for given LCID (no RLC overhead included) + int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_retx(lcid); } + + /// Sum of DL RLC newtx and retx buffer status for all LCIDS + int get_dl_tx_total() const; + + // UL BSR methods + bool is_lcg_active(uint32_t lcg) const; + int get_bsr(uint32_t lcg) const; + const std::array& get_bsr_state() const { return lcg_bsr; } + + static bool is_lcid_valid(uint32_t lcid) { return lcid <= MAX_LC_ID; } + static bool is_lcg_valid(uint32_t lcg) { return lcg <= MAX_LCG_ID; } + +protected: + srslog::basic_logger& logger; + + struct logical_channel { + mac_lc_ch_cfg_t cfg; + int buf_tx = 0; + int buf_retx = 0; + int Bj = 0; + int bucket_size = 0; + }; + std::array channels; + + std::array lcg_bsr{0}; +}; + +} // namespace srsenb + +#endif // SRSRAN_UE_BUFFER_MANAGER_H diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 63e5527dd..cbb7e4af3 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -14,6 +14,7 @@ #define SRSENB_MAC_H #include "sched.h" +#include "sched_interface.h" #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.h" #include "srsran/adt/circular_map.h" @@ -26,7 +27,6 @@ #include "srsran/interfaces/enb_mac_interfaces.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/srslog/srslog.h" #include "ta.h" #include "ue.h" @@ -86,7 +86,7 @@ public: void phy_config_enabled(uint16_t rnti, bool enabled) override; /* Manages UE bearers and associated configuration */ - int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) override; + int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, mac_lc_ch_cfg_t* cfg) override; int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override; int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) override; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 79f0d503e..24b563745 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -16,7 +16,7 @@ #include "sched_nr_cfg.h" #include "sched_nr_harq.h" #include "sched_nr_interface.h" -#include "sched_nr_ue_buffer_manager.h" +#include "srsenb/hdr/stack/mac/common/ue_buffer_manager.h" #include "srsran/adt/circular_map.h" #include "srsran/adt/move_callback.h" #include "srsran/adt/pool/cached_alloc.h" @@ -100,8 +100,8 @@ private: const uint16_t rnti; const sched_params& sched_cfg; - bool pending_sr = false; - ue_buffer_manager buffers; + bool pending_sr = false; + ue_buffer_manager buffers; ue_cfg_t ue_cfg; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h deleted file mode 100644 index ec88132c0..000000000 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H -#define SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H - -#include "srsenb/hdr/stack/mac/common/sched_config.h" -#include "srsran/srslog/srslog.h" -#include "srsran/support/srsran_assert.h" - -namespace srsenb { -namespace sched_nr_impl { - -class ue_buffer_manager -{ - const static uint32_t MAX_LCG_ID = 7; - const static uint32_t MAX_LC_ID = 32; - const static uint32_t MAX_SRB_LC_ID = 3; - -public: - explicit ue_buffer_manager(srslog::basic_logger& logger_); - - // Configuration getters - bool is_channel_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); } - bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); } - bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); } - const logical_channel_cfg_t& get_cfg(uint32_t lcid) const - { - srsran_assert(lcid < MAX_LC_ID, "Provided LCID=%d is above limit=%d", lcid, MAX_LC_ID); - return channels[lcid].cfg; - } - - // Buffer Status update - void ul_bsr(uint32_t lcg_id, uint32_t val); - void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue); - - // UL BSR methods - bool is_lcg_active(uint32_t lcg) const; - int get_bsr(uint32_t lcg) const; - -private: - srslog::basic_logger& logger; - - struct logical_channel { - logical_channel_cfg_t cfg; - int buf_tx = 0; - int buf_retx = 0; - }; - std::array channels; - - std::array lcg_bsr{0}; -}; - -} // namespace sched_nr_impl -} // namespace srsenb - -#endif // SRSRAN_SCHED_NR_UE_BUFFER_MANAGER_H diff --git a/srsenb/hdr/stack/mac/nr/ue_nr.h b/srsenb/hdr/stack/mac/nr/ue_nr.h index 0e644cb9e..5d33623b1 100644 --- a/srsenb/hdr/stack/mac/nr/ue_nr.h +++ b/srsenb/hdr/stack/mac/nr/ue_nr.h @@ -14,10 +14,10 @@ #define SRSENB_UE_NR_H #include "srsenb/hdr/stack/mac/common/mac_metrics.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/block_queue.h" #include "srsran/common/interfaces_common.h" #include "srsran/interfaces/enb_rlc_interfaces.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/mac/mac_sch_pdu_nr.h" #include #include diff --git a/srsenb/hdr/stack/mac/sched.h b/srsenb/hdr/stack/mac/sched.h index 8aaf1195a..36fa3f8a6 100644 --- a/srsenb/hdr/stack/mac/sched.h +++ b/srsenb/hdr/stack/mac/sched.h @@ -14,9 +14,9 @@ #define SRSENB_SCHEDULER_H #include "sched_grid.h" +#include "sched_interface.h" #include "sched_ue.h" #include "srsenb/hdr/common/common_enb.h" -#include "srsran/interfaces/sched_interface.h" #include #include #include @@ -47,7 +47,7 @@ public: void phy_config_enabled(uint16_t rnti, bool enabled); - int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const ue_bearer_cfg_t& cfg) final; + int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const mac_lc_ch_cfg_t& cfg) final; int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) final; uint32_t get_ul_buffer(uint16_t rnti) final; diff --git a/srsenb/hdr/stack/mac/sched_grid.h b/srsenb/hdr/stack/mac/sched_grid.h index f7d7ce183..7341cdaba 100644 --- a/srsenb/hdr/stack/mac/sched_grid.h +++ b/srsenb/hdr/stack/mac/sched_grid.h @@ -13,8 +13,8 @@ #ifndef SRSRAN_SCHED_GRID_H #define SRSRAN_SCHED_GRID_H -#include "lib/include/srsran/interfaces/sched_interface.h" #include "sched_common.h" +#include "sched_interface.h" #include "sched_phy_ch/sched_result.h" #include "sched_phy_ch/sf_cch_allocator.h" #include "sched_ue.h" diff --git a/srsenb/hdr/stack/mac/sched_helpers.h b/srsenb/hdr/stack/mac/sched_helpers.h index 651dae6b8..bea8e667f 100644 --- a/srsenb/hdr/stack/mac/sched_helpers.h +++ b/srsenb/hdr/stack/mac/sched_helpers.h @@ -13,8 +13,8 @@ #ifndef SRSRAN_SCHED_HELPERS_H #define SRSRAN_SCHED_HELPERS_H +#include "sched_interface.h" #include "srsenb/hdr/stack/mac/sched_lte_common.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/srslog/srslog.h" namespace srsenb { @@ -96,8 +96,6 @@ void log_phich_cc_results(srslog::basic_logger& logger, uint32_t enb_cc_idx, const sched_interface::ul_sched_res_t& result); -const char* to_string(sched_interface::ue_bearer_cfg_t::direction_t dir); - } // namespace srsenb #endif // SRSRAN_SCHED_HELPERS_H diff --git a/lib/include/srsran/interfaces/sched_interface.h b/srsenb/hdr/stack/mac/sched_interface.h similarity index 96% rename from lib/include/srsran/interfaces/sched_interface.h rename to srsenb/hdr/stack/mac/sched_interface.h index aae980273..d6eafc012 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/srsenb/hdr/stack/mac/sched_interface.h @@ -10,6 +10,7 @@ * */ +#include "common/sched_config.h" #include "srsran/adt/bounded_vector.h" #include "srsran/common/common.h" #include "srsran/srsran.h" @@ -116,14 +117,6 @@ public: std::vector scell_list; }; - struct ue_bearer_cfg_t { - int priority = 1; - uint32_t bsd = 1000; // msec - uint32_t pbr = -1; - int group = 0; - enum direction_t { IDLE = 0, UL, DL, BOTH } direction = IDLE; - }; - struct ant_info_ded_t { enum class tx_mode_t { tm1, tm2, tm3, tm4, tm5, tm6, tm7, tm8_v920, nulltype } tx_mode = tx_mode_t::tm1; enum class codebook_t { @@ -153,7 +146,7 @@ public: bool continuous_pusch = false; srsran_uci_offset_cfg_t uci_offset = {15, 12, 10}; srsran_pucch_cfg_t pucch_cfg = {}; - std::array ue_bearers = {}; + std::array ue_bearers = {}; std::vector supported_cc_list; ///< list of UE supported CCs. First index for PCell ant_info_ded_t dl_ant_info; bool use_tbs_index_alt = false; @@ -258,7 +251,7 @@ public: virtual bool ue_exists(uint16_t rnti) = 0; /* Manages UE bearers and associated configuration */ - virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const ue_bearer_cfg_t& cfg) = 0; + virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const mac_lc_ch_cfg_t& cfg) = 0; virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; virtual uint32_t get_ul_buffer(uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/mac/sched_lte_common.h b/srsenb/hdr/stack/mac/sched_lte_common.h index 39bd4bf9e..e76d8f676 100644 --- a/srsenb/hdr/stack/mac/sched_lte_common.h +++ b/srsenb/hdr/stack/mac/sched_lte_common.h @@ -13,9 +13,9 @@ #ifndef SRSRAN_SCHED_LTE_COMMON_H #define SRSRAN_SCHED_LTE_COMMON_H +#include "sched_interface.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/common/tti_point.h" -#include "srsran/interfaces/sched_interface.h" namespace srsenb { diff --git a/srsenb/hdr/stack/mac/sched_ue.h b/srsenb/hdr/stack/mac/sched_ue.h index da03a9fc2..fc68c70c8 100644 --- a/srsenb/hdr/stack/mac/sched_ue.h +++ b/srsenb/hdr/stack/mac/sched_ue.h @@ -32,8 +32,7 @@ typedef enum { UCI_PUSCH_NONE = 0, UCI_PUSCH_CQI, UCI_PUSCH_ACK, UCI_PUSCH_ACK_C */ class sched_ue { - using ue_cfg_t = sched_interface::ue_cfg_t; - using bearer_cfg_t = sched_interface::ue_bearer_cfg_t; + using ue_cfg_t = sched_interface::ue_cfg_t; public: sched_ue(uint16_t rnti, const std::vector& cell_list_params_, const ue_cfg_t& cfg); @@ -48,7 +47,7 @@ public: void phy_config_enabled(tti_point tti_rx, bool enabled); void set_cfg(const ue_cfg_t& cfg); - void set_bearer_cfg(uint32_t lc_id, const bearer_cfg_t& cfg); + void set_bearer_cfg(uint32_t lc_id, const mac_lc_ch_cfg_t& cfg); void rem_bearer(uint32_t lc_id); void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue); diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h index 50577374f..6bdfa3290 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h @@ -13,9 +13,9 @@ #ifndef SRSENB_SCHEDULER_HARQ_H #define SRSENB_SCHEDULER_HARQ_H +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/common/tti_point.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/srslog/srslog.h" namespace srsenb { diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_lch.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_lch.h index 90b79fd93..c4ce54b77 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_lch.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_lch.h @@ -13,70 +13,58 @@ #ifndef SRSRAN_SCHED_LCH_H #define SRSRAN_SCHED_LCH_H +#include "srsenb/hdr/stack/mac/common/ue_buffer_manager.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/adt/pool/cached_alloc.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/mac/pdu.h" #include "srsran/srslog/srslog.h" namespace srsenb { -class lch_ue_manager +class lch_ue_manager : private ue_buffer_manager { - constexpr static uint32_t pbr_infinity = -1; - constexpr static uint32_t MAX_LC = sched_interface::MAX_LC; + using base_type = ue_buffer_manager; public: - lch_ue_manager() : logger(srslog::fetch_basic_logger("MAC")) {} + lch_ue_manager() : ue_buffer_manager(srslog::fetch_basic_logger("MAC")) {} void set_cfg(const sched_interface::ue_cfg_t& cfg_); void new_tti(); - void config_lcid(uint32_t lcg_id, const sched_interface::ue_bearer_cfg_t& bearer_cfg); - void ul_bsr(uint8_t lcg_id, uint32_t bsr); + // Inherited methods from ue_buffer_manager base class + using base_type::config_lcid; + using base_type::dl_buffer_state; + using base_type::get_bsr; + using base_type::get_bsr_state; + using base_type::get_dl_retx; + using base_type::get_dl_tx; + using base_type::get_dl_tx_total; + using base_type::is_bearer_active; + using base_type::is_bearer_dl; + using base_type::is_bearer_ul; + using base_type::is_lcg_active; + using base_type::ul_bsr; + void ul_buffer_add(uint8_t lcid, uint32_t bytes); - void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue); int alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* lcid, int rem_bytes); - bool is_bearer_active(uint32_t lcid) const; - bool is_bearer_ul(uint32_t lcid) const; - bool is_bearer_dl(uint32_t lcid) const; - bool has_pending_dl_txs() const; - int get_dl_tx_total() const; - int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_retx(lcid); } int get_dl_tx_total_with_overhead(uint32_t lcid) const; - int get_dl_tx(uint32_t lcid) const; int get_dl_tx_with_overhead(uint32_t lcid) const; - int get_dl_retx(uint32_t lcid) const; int get_dl_retx_with_overhead(uint32_t lcid) const; - bool is_lcg_active(uint32_t lcg) const; - int get_bsr(uint32_t lcid) const; - int get_bsr_with_overhead(uint32_t lcid) const; - int get_max_prio_lcid() const; - - const std::array& get_bsr_state() const; + int get_bsr_with_overhead(uint32_t lcid) const; + int get_max_prio_lcid() const; // Control Element Command queue using ce_cmd = srsran::dl_sch_lcid; srsran::deque pending_ces; private: - struct ue_bearer_t { - sched_interface::ue_bearer_cfg_t cfg = {}; - int bucket_size = 0; - int buf_tx = 0; - int buf_retx = 0; - int Bj = 0; - }; - int alloc_retx_bytes(uint8_t lcid, int rem_bytes); int alloc_tx_bytes(uint8_t lcid, int rem_bytes); - size_t prio_idx = 0; - srslog::basic_logger& logger; - std::array lch = {}; - std::array lcg_bsr = {}; + size_t prio_idx = 0; }; /** diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 4fb3a6d58..f9040ef5c 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -14,6 +14,7 @@ #define SRSENB_UE_H #include "common/mac_metrics.h" +#include "sched_interface.h" #include "srsran/adt/circular_array.h" #include "srsran/adt/circular_map.h" #include "srsran/adt/pool/pool_interface.h" @@ -21,7 +22,6 @@ #include "srsran/common/mac_pcap.h" #include "srsran/common/mac_pcap_net.h" #include "srsran/common/tti_point.h" -#include "srsran/interfaces/sched_interface.h" #include "srsran/mac/pdu.h" #include "srsran/mac/pdu_queue.h" #include "srsran/srslog/srslog.h" diff --git a/srsenb/hdr/stack/rrc/mac_controller.h b/srsenb/hdr/stack/rrc/mac_controller.h index ff9a62b60..2056881eb 100644 --- a/srsenb/hdr/stack/rrc/mac_controller.h +++ b/srsenb/hdr/stack/rrc/mac_controller.h @@ -15,8 +15,8 @@ #include "rrc_bearer_cfg.h" #include "rrc_cell_cfg.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/interfaces/rrc_interface_types.h" -#include "srsran/interfaces/sched_interface.h" #include namespace srsenb { @@ -55,7 +55,7 @@ public: const srsran::rrc_ue_capabilities_t& uecaps); void handle_ho_prep(const asn1::rrc::ho_prep_info_r8_ies_s& ho_prep); - void set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::direction_t dir); + void set_radio_bearer_state(mac_lc_ch_cfg_t::direction_t dir); const ue_cfg_t& get_ue_sched_cfg() const { return current_sched_ue_cfg; } bool is_crnti_set() const { return crnti_set; } diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 2a9d19b8d..3f66332cb 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -49,7 +49,7 @@ public: void rlf_timer_expired(uint32_t timeout_id); void max_rlc_retx_reached(); void protocol_failure(); - void deactivate_bearers() { mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::IDLE); } + void deactivate_bearers() { mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); } rrc_state_t get_state(); void get_metrics(rrc_ue_metrics_t& ue_metrics) const; diff --git a/srsenb/src/stack/mac/CMakeLists.txt b/srsenb/src/stack/mac/CMakeLists.txt index 0ee0ac9bf..44bea9de7 100644 --- a/srsenb/src/stack/mac/CMakeLists.txt +++ b/srsenb/src/stack/mac/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_subdirectory(common) + add_subdirectory(schedulers) set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_ue_ctrl/sched_harq.cc sched_ue.cc @@ -13,5 +15,6 @@ set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_ue_ctrl/s sched_phy_ch/sf_cch_allocator.cc sched_phy_ch/sched_dci.cc sched_phy_ch/sched_phy_resource.cc sched_helpers.cc) add_library(srsenb_mac STATIC ${SOURCES} $) +target_link_libraries(srsenb_mac srsenb_mac_common) add_subdirectory(nr) \ No newline at end of file diff --git a/srsenb/src/stack/mac/common/CMakeLists.txt b/srsenb/src/stack/mac/common/CMakeLists.txt new file mode 100644 index 000000000..328c5c30f --- /dev/null +++ b/srsenb/src/stack/mac/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright 2013-2021 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +set(SOURCES ue_buffer_manager.cc) +add_library(srsenb_mac_common STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/common/ue_buffer_manager.cc b/srsenb/src/stack/mac/common/ue_buffer_manager.cc new file mode 100644 index 000000000..775d20fb1 --- /dev/null +++ b/srsenb/src/stack/mac/common/ue_buffer_manager.cc @@ -0,0 +1,116 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/common/ue_buffer_manager.h" +#include "srsran/common/string_helpers.h" +#include "srsran/srslog/bundled/fmt/format.h" +#include "srsran/srslog/bundled/fmt/ranges.h" + +namespace srsenb { + +template +void ue_buffer_manager::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg) +{ + if (not is_lcid_valid(lcid)) { + logger.warning("Configuring bearer with invalid logical channel id=%d", lcid); + return; + } + if (not is_lcg_valid(bearer_cfg.group)) { + logger.warning("Configuring bearer with invalid logical channel group id=%d", bearer_cfg.group); + return; + } + + // update bearer config + if (bearer_cfg != channels[lcid].cfg) { + channels[lcid].cfg = bearer_cfg; + if (channels[lcid].cfg.pbr == pbr_infinity) { + channels[lcid].bucket_size = std::numeric_limits::max(); + channels[lcid].Bj = std::numeric_limits::max(); + } else { + channels[lcid].bucket_size = channels[lcid].cfg.bsd * channels[lcid].cfg.pbr; + channels[lcid].Bj = 0; + } + logger.info("SCHED: bearer configured: lcid=%d, mode=%s, prio=%d", + lcid, + to_string(channels[lcid].cfg.direction), + channels[lcid].cfg.priority); + } +} + +template +int ue_buffer_manager::get_dl_tx_total() const +{ + int sum = 0; + for (size_t lcid = 0; is_lcid_valid(lcid); ++lcid) { + sum += get_dl_tx_total(lcid); + } + return sum; +} + +template +bool ue_buffer_manager::is_lcg_active(uint32_t lcg) const +{ + if (lcg == 0) { + return true; + } + for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) { + if (is_bearer_ul(lcid) and channels[lcid].cfg.group == (int)lcg) { + return true; + } + } + return false; +} + +template +int ue_buffer_manager::get_bsr(uint32_t lcg) const +{ + return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0; +} + +template +void ue_buffer_manager::ul_bsr(uint32_t lcg_id, uint32_t val) +{ + if (not is_lcg_valid(lcg_id)) { + logger.warning("The provided logical channel group id=%d is not valid", lcg_id); + return; + } + lcg_bsr[lcg_id] = val; + + if (logger.debug.enabled()) { + fmt::memory_buffer str_buffer; + fmt::format_to(str_buffer, "{}", lcg_bsr); + logger.debug("SCHED: lcg_id=%d, bsr=%d. Current state=%s", lcg_id, val, srsran::to_c_str(str_buffer)); + } +} + +template +void ue_buffer_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue) +{ + if (not is_lcid_valid(lcid)) { + logger.warning("The provided lcid=%d is not valid", lcid); + return; + } + if (lcid <= MAX_SRB_LC_ID and + (channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) { + logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); + } else { + logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); + } + channels[lcid].buf_retx = retx_queue; + channels[lcid].buf_tx = tx_queue; +} + +// Explicit instantiation +template class ue_buffer_manager; +template class ue_buffer_manager; + +} // namespace srsenb diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index f9fcd278a..aee82af20 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -147,7 +147,7 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint return ret; } -int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) +int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, mac_lc_ch_cfg_t* cfg) { srsran::rwlock_read_guard lock(rwlock); return check_ue_active(rnti) ? scheduler.bearer_ue_cfg(rnti, lc_id, *cfg) : -1; @@ -552,7 +552,7 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx uecfg.supported_cc_list.emplace_back(); uecfg.supported_cc_list.back().active = true; uecfg.supported_cc_list.back().enb_cc_idx = enb_cc_idx; - uecfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + uecfg.ue_bearers[0].direction = mac_lc_ch_cfg_t::BOTH; uecfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; if (ue_cfg(rnti, &uecfg) != SRSRAN_SUCCESS) { return; diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 5ca49c739..51e8d57eb 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -19,7 +19,7 @@ set(SOURCES mac_nr.cc sched_nr_cell.cc sched_nr_rb.cc sched_nr_time_rr.cc - harq_softbuffer.cc - sched_nr_ue_buffer_manager.cc) + harq_softbuffer.cc) add_library(srsgnb_mac STATIC ${SOURCES}) +target_link_libraries(srsgnb_mac srsenb_mac_common) diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc b/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc deleted file mode 100644 index ac0a27b55..000000000 --- a/srsenb/src/stack/mac/nr/sched_nr_ue_buffer_manager.cc +++ /dev/null @@ -1,70 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include "srsenb/hdr/stack/mac/nr/sched_nr_ue_buffer_manager.h" -#include "srsran/common/string_helpers.h" -#include "srsran/srslog/bundled/fmt/format.h" -#include "srsran/srslog/bundled/fmt/ranges.h" - -namespace srsenb { -namespace sched_nr_impl { - -ue_buffer_manager::ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_) {} - -bool ue_buffer_manager::is_lcg_active(uint32_t lcg) const -{ - if (lcg == 0) { - return true; - } - for (uint32_t lcid = 0; lcid < MAX_LC_ID; ++lcid) { - if (is_bearer_ul(lcid) and channels[lcid].cfg.group == (int)lcg) { - return true; - } - } - return false; -} - -int ue_buffer_manager::get_bsr(uint32_t lcg) const -{ - return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0; -} - -void ue_buffer_manager::ul_bsr(uint32_t lcg_id, uint32_t val) -{ - srsran_assert(lcg_id < MAX_LCG_ID, "Provided LCG_ID=%d is above its limit=%d", lcg_id, MAX_LCG_ID); - lcg_bsr[lcg_id] = val; - - if (logger.debug.enabled()) { - fmt::memory_buffer str_buffer; - fmt::format_to(str_buffer, "{}", lcg_bsr); - logger.debug("SCHED: lcg_id=%d, bsr=%s. Current state=%s", lcg_id, val, srsran::to_c_str(str_buffer)); - } -} - -void ue_buffer_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue) -{ - if (lcid >= MAX_LC_ID) { - logger.warning("The provided lcid=%d is not valid", lcid); - return; - } - if (lcid <= MAX_SRB_LC_ID and - (channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) { - logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); - } else { - logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); - } - channels[lcid].buf_retx = retx_queue; - channels[lcid].buf_tx = tx_queue; -} - -} // namespace sched_nr_impl -} // namespace srsenb diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index f55023c23..f01a209fe 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -136,7 +136,7 @@ void sched::phy_config_enabled(uint16_t rnti, bool enabled) rnti, [this, enabled](sched_ue& ue) { ue.phy_config_enabled(last_tti, enabled); }, __PRETTY_FUNCTION__); } -int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg_) +int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const mac_lc_ch_cfg_t& cfg_) { return ue_db_access_locked(rnti, [lc_id, cfg_](sched_ue& ue) { ue.set_bearer_cfg(lc_id, cfg_); }); } diff --git a/srsenb/src/stack/mac/sched_helpers.cc b/srsenb/src/stack/mac/sched_helpers.cc index 0dd785551..5b7d78f20 100644 --- a/srsenb/src/stack/mac/sched_helpers.cc +++ b/srsenb/src/stack/mac/sched_helpers.cc @@ -450,20 +450,4 @@ int check_ue_cfg_correctness(const sched_interface::ue_cfg_t& ue_cfg) return ret; } -const char* to_string(sched_interface::ue_bearer_cfg_t::direction_t dir) -{ - switch (dir) { - case sched_interface::ue_bearer_cfg_t::IDLE: - return "idle"; - case sched_interface::ue_bearer_cfg_t::BOTH: - return "bi-dir"; - case sched_interface::ue_bearer_cfg_t::DL: - return "DL"; - case sched_interface::ue_bearer_cfg_t::UL: - return "UL"; - default: - return "unrecognized direction"; - } -} - } // namespace srsenb diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 0b8f07107..fd9031323 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -104,7 +104,7 @@ void sched_ue::new_subframe(tti_point tti_rx, uint32_t enb_cc_idx) * *******************************************************/ -void sched_ue::set_bearer_cfg(uint32_t lc_id, const bearer_cfg_t& cfg_) +void sched_ue::set_bearer_cfg(uint32_t lc_id, const mac_lc_ch_cfg_t& cfg_) { cfg.ue_bearers[lc_id] = cfg_; lch_handler.config_lcid(lc_id, cfg_); @@ -112,8 +112,8 @@ void sched_ue::set_bearer_cfg(uint32_t lc_id, const bearer_cfg_t& cfg_) void sched_ue::rem_bearer(uint32_t lc_id) { - cfg.ue_bearers[lc_id] = sched_interface::ue_bearer_cfg_t{}; - lch_handler.config_lcid(lc_id, sched_interface::ue_bearer_cfg_t{}); + cfg.ue_bearers[lc_id] = mac_lc_ch_cfg_t{}; + lch_handler.config_lcid(lc_id, mac_lc_ch_cfg_t{}); } void sched_ue::phy_config_enabled(tti_point tti_rx, bool enabled) diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_lch.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_lch.cc index 10869e80b..3bd85f603 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_lch.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_lch.cc @@ -57,7 +57,7 @@ uint32_t get_ul_mac_sdu_size_with_overhead(uint32_t rlc_pdu_bytes) void lch_ue_manager::set_cfg(const sched_interface::ue_cfg_t& cfg) { - for (uint32_t lcid = 0; lcid < sched_interface::MAX_LC; lcid++) { + for (uint32_t lcid = 0; is_lcid_valid(lcid); lcid++) { config_lcid(lcid, cfg.ue_bearers[lcid]); } } @@ -67,85 +67,27 @@ void lch_ue_manager::new_tti() prio_idx++; for (uint32_t lcid = 0; lcid < sched_interface::MAX_LC; ++lcid) { if (is_bearer_active(lcid)) { - if (lch[lcid].cfg.pbr != pbr_infinity) { - lch[lcid].Bj = std::min(lch[lcid].Bj + (int)(lch[lcid].cfg.pbr * tti_duration_ms), lch[lcid].bucket_size); + if (channels[lcid].cfg.pbr != pbr_infinity) { + channels[lcid].Bj = + std::min(channels[lcid].Bj + (int)(channels[lcid].cfg.pbr * tti_duration_ms), channels[lcid].bucket_size); } } } } -void lch_ue_manager::config_lcid(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& bearer_cfg) -{ - if (lc_id >= sched_interface::MAX_LC) { - logger.warning("Adding bearer with invalid logical channel id=%d", lc_id); - return; - } - if (bearer_cfg.group >= sched_interface::MAX_LC_GROUP) { - logger.warning("Adding bearer with invalid logical channel group id=%d", bearer_cfg.group); - return; - } - - // update bearer config - bool is_equal = memcmp(&bearer_cfg, &lch[lc_id].cfg, sizeof(bearer_cfg)) == 0; - - if (not is_equal) { - lch[lc_id].cfg = bearer_cfg; - if (lch[lc_id].cfg.pbr == pbr_infinity) { - lch[lc_id].bucket_size = std::numeric_limits::max(); - lch[lc_id].Bj = std::numeric_limits::max(); - } else { - lch[lc_id].bucket_size = lch[lc_id].cfg.bsd * lch[lc_id].cfg.pbr; - lch[lc_id].Bj = 0; - } - logger.info("SCHED: bearer configured: lc_id=%d, mode=%s, prio=%d", - lc_id, - to_string(lch[lc_id].cfg.direction), - lch[lc_id].cfg.priority); - } -} - -void lch_ue_manager::ul_bsr(uint8_t lcg_id, uint32_t bsr) -{ - if (lcg_id >= sched_interface::MAX_LC_GROUP) { - logger.warning("The provided logical channel group id=%d is not valid", lcg_id); - return; - } - lcg_bsr[lcg_id] = bsr; - if (logger.debug.enabled()) { - fmt::memory_buffer str_buffer; - fmt::format_to(str_buffer, "{}", get_bsr_state()); - logger.debug("SCHED: bsr=%d, lcg_id=%d, bsr=%s", bsr, lcg_id, srsran::to_c_str(str_buffer)); - } -} - void lch_ue_manager::ul_buffer_add(uint8_t lcid, uint32_t bytes) { if (lcid >= sched_interface::MAX_LC) { logger.warning("The provided lcid=%d is not valid", lcid); return; } - lcg_bsr[lch[lcid].cfg.group] += bytes; + lcg_bsr[channels[lcid].cfg.group] += bytes; if (logger.debug.enabled()) { fmt::memory_buffer str_buffer; fmt::format_to(str_buffer, "{}", get_bsr_state()); logger.debug( - "SCHED: UL buffer update=%d, lcg_id=%d, bsr=%s", bytes, lch[lcid].cfg.group, srsran::to_c_str(str_buffer)); - } -} - -void lch_ue_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue) -{ - if (lcid >= sched_interface::MAX_LC) { - logger.warning("The provided lcid=%d is not valid", lcid); - return; - } - if (lcid < 3 and (lch[lcid].buf_tx != (int)tx_queue or lch[lcid].buf_retx != (int)retx_queue)) { - logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); - } else { - logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue); + "SCHED: UL buffer update=%d, lcg_id=%d, bsr=%s", bytes, channels[lcid].cfg.group, srsran::to_c_str(str_buffer)); } - lch[lcid].buf_retx = retx_queue; - lch[lcid].buf_tx = tx_queue; } int lch_ue_manager::get_max_prio_lcid() const @@ -153,9 +95,9 @@ int lch_ue_manager::get_max_prio_lcid() const int min_prio_val = std::numeric_limits::max(), prio_lcid = -1; // Prioritize retxs - for (uint32_t lcid = 0; lcid < MAX_LC; ++lcid) { - if (get_dl_retx(lcid) > 0 and lch[lcid].cfg.priority < min_prio_val) { - min_prio_val = lch[lcid].cfg.priority; + for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) { + if (get_dl_retx(lcid) > 0 and channels[lcid].cfg.priority < min_prio_val) { + min_prio_val = channels[lcid].cfg.priority; prio_lcid = lcid; } } @@ -164,9 +106,9 @@ int lch_ue_manager::get_max_prio_lcid() const } // Select lcid with new txs using Bj - for (uint32_t lcid = 0; lcid < MAX_LC; ++lcid) { - if (get_dl_tx(lcid) > 0 and lch[lcid].Bj > 0 and lch[lcid].cfg.priority < min_prio_val) { - min_prio_val = lch[lcid].cfg.priority; + for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) { + if (get_dl_tx(lcid) > 0 and channels[lcid].Bj > 0 and channels[lcid].cfg.priority < min_prio_val) { + min_prio_val = channels[lcid].cfg.priority; prio_lcid = lcid; } } @@ -175,15 +117,15 @@ int lch_ue_manager::get_max_prio_lcid() const } // Disregard Bj - size_t nof_lcids = 0; - std::array chosen_lcids = {}; - for (uint32_t lcid = 0; lcid < MAX_LC; ++lcid) { + size_t nof_lcids = 0; + std::array chosen_lcids = {}; + for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) { if (get_dl_tx_total(lcid) > 0) { - if (lch[lcid].cfg.priority < min_prio_val) { - min_prio_val = lch[lcid].cfg.priority; + if (channels[lcid].cfg.priority < min_prio_val) { + min_prio_val = channels[lcid].cfg.priority; chosen_lcids[0] = lcid; nof_lcids = 1; - } else if (lch[lcid].cfg.priority == min_prio_val) { + } else if (channels[lcid].cfg.priority == min_prio_val) { chosen_lcids[nof_lcids++] = lcid; } } @@ -234,7 +176,7 @@ int lch_ue_manager::alloc_retx_bytes(uint8_t lcid, int rem_bytes) } int rem_bytes_no_header = rem_bytes - rlc_overhead; int alloc = std::min(rem_bytes_no_header, get_dl_retx(lcid)); - lch[lcid].buf_retx -= alloc; + channels[lcid].buf_retx -= alloc; return alloc + (alloc > 0 ? rlc_overhead : 0); } @@ -246,35 +188,20 @@ int lch_ue_manager::alloc_tx_bytes(uint8_t lcid, int rem_bytes) } int rem_bytes_no_header = rem_bytes - rlc_overhead; int alloc = std::min(rem_bytes_no_header, get_dl_tx(lcid)); - lch[lcid].buf_tx -= alloc; - if (alloc > 0 and lch[lcid].cfg.pbr != pbr_infinity) { + channels[lcid].buf_tx -= alloc; + if (alloc > 0 and channels[lcid].cfg.pbr != pbr_infinity) { // Update Bj - lch[lcid].Bj -= alloc; + channels[lcid].Bj -= alloc; } return alloc + (alloc > 0 ? rlc_overhead : 0); } -bool lch_ue_manager::is_bearer_active(uint32_t lcid) const -{ - return lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::IDLE; -} - -bool lch_ue_manager::is_bearer_ul(uint32_t lcid) const -{ - return is_bearer_active(lcid) and lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::DL; -} - -bool lch_ue_manager::is_bearer_dl(uint32_t lcid) const -{ - return is_bearer_active(lcid) and lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::UL; -} - bool lch_ue_manager::has_pending_dl_txs() const { if (not pending_ces.empty()) { return true; } - for (uint32_t lcid = 0; lcid < lch.size(); ++lcid) { + for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) { if (get_dl_tx_total(lcid) > 0) { return true; } @@ -282,64 +209,26 @@ bool lch_ue_manager::has_pending_dl_txs() const return false; } -int lch_ue_manager::get_dl_tx_total() const -{ - int sum = 0; - for (size_t lcid = 0; lcid < lch.size(); ++lcid) { - sum += get_dl_tx_total(lcid); - } - return sum; -} - int lch_ue_manager::get_dl_tx_total_with_overhead(uint32_t lcid) const { return get_dl_retx_with_overhead(lcid) + get_dl_tx_with_overhead(lcid); } -int lch_ue_manager::get_dl_tx(uint32_t lcid) const -{ - return is_bearer_dl(lcid) ? lch[lcid].buf_tx : 0; -} int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const { return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_tx(lcid)); } -int lch_ue_manager::get_dl_retx(uint32_t lcid) const -{ - return is_bearer_dl(lcid) ? lch[lcid].buf_retx : 0; -} int lch_ue_manager::get_dl_retx_with_overhead(uint32_t lcid) const { return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_retx(lcid)); } -bool lch_ue_manager::is_lcg_active(uint32_t lcg) const -{ - if (lcg == 0) { - return true; - } - for (uint32_t lcid = 0; lcid < MAX_LC; ++lcid) { - if (is_bearer_ul(lcid) and lch[lcid].cfg.group == (int)lcg) { - return true; - } - } - return false; -} -int lch_ue_manager::get_bsr(uint32_t lcg) const -{ - return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0; -} int lch_ue_manager::get_bsr_with_overhead(uint32_t lcg) const { return get_ul_mac_sdu_size_with_overhead(get_bsr(lcg)); } -const std::array& lch_ue_manager::get_bsr_state() const -{ - return lcg_bsr; -} - uint32_t allocate_mac_sdus(sched_interface::dl_sched_data_t* data, lch_ue_manager& lch_handler, uint32_t total_tbs, diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index a4c28cdaa..24dd95133 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -255,7 +255,7 @@ int sched_ue_cell::set_ack_info(tti_point tti_rx, uint32_t tb_idx, bool ack) int sched_ue_cell::set_ul_snr(tti_point tti_rx, float ul_snr, uint32_t ul_ch_code) { CHECK_VALID_CC("UL SNR estimate"); - if (ue_cfg->ue_bearers[1].direction == sched_interface::ue_bearer_cfg_t::IDLE) { + if (ue_cfg->ue_bearers[1].direction == mac_lc_ch_cfg_t::IDLE) { // Ignore Msg3 SNR samples as Msg3 uses a separate power control loop return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/mac_controller.cc b/srsenb/src/stack/rrc/mac_controller.cc index 1f36d2ef8..1b4925508 100644 --- a/srsenb/src/stack/rrc/mac_controller.cc +++ b/srsenb/src/stack/rrc/mac_controller.cc @@ -23,28 +23,28 @@ using ue_cfg_t = sched_interface::ue_cfg_t; /********* Helper Methods ********/ // TS 36.331 9.1.1.2 - CCCH configuration -sched_interface::ue_bearer_cfg_t get_bearer_default_ccch_config() +mac_lc_ch_cfg_t get_bearer_default_ccch_config() { - sched_interface::ue_bearer_cfg_t bearer = {}; - bearer.direction = sched_interface::ue_bearer_cfg_t::BOTH; - bearer.priority = 1; - bearer.pbr = -1; - bearer.bsd = -1; - bearer.group = 0; + mac_lc_ch_cfg_t bearer = {}; + bearer.direction = mac_lc_ch_cfg_t::BOTH; + bearer.priority = 1; + bearer.pbr = -1; + bearer.bsd = -1; + bearer.group = 0; return bearer; } // TS 36.331 9.2.1.1 - SRB1 -sched_interface::ue_bearer_cfg_t get_bearer_default_srb1_config() +mac_lc_ch_cfg_t get_bearer_default_srb1_config() { return get_bearer_default_ccch_config(); } // TS 36.331 9.2.1.2 - SRB2 -sched_interface::ue_bearer_cfg_t get_bearer_default_srb2_config() +mac_lc_ch_cfg_t get_bearer_default_srb2_config() { - sched_interface::ue_bearer_cfg_t bearer = get_bearer_default_srb1_config(); - bearer.priority = 3; + mac_lc_ch_cfg_t bearer = get_bearer_default_srb1_config(); + bearer.priority = 3; return bearer; } @@ -233,7 +233,7 @@ void mac_controller::apply_current_bearers_cfg() for (const drb_to_add_mod_s& drb : drbs) { auto& bcfg = current_sched_ue_cfg.ue_bearers[drb.lc_ch_id]; bcfg = {}; - bcfg.direction = sched_interface::ue_bearer_cfg_t::BOTH; + bcfg.direction = mac_lc_ch_cfg_t::BOTH; bcfg.group = 1; bcfg.priority = 4; if (drb.lc_ch_cfg_present and drb.lc_ch_cfg.ul_specific_params_present) { @@ -283,7 +283,7 @@ void mac_controller::handle_intraenb_ho_cmd(const asn1::rrc::rrc_conn_recfg_r8_i // Stop any SRB UL (including SRs) for (uint32_t i = srb_to_lcid(lte_srb::srb1); i <= srb_to_lcid(lte_srb::srb2); ++i) { - current_sched_ue_cfg.ue_bearers[i].direction = sched_interface::ue_bearer_cfg_t::DL; + current_sched_ue_cfg.ue_bearers[i].direction = mac_lc_ch_cfg_t::DL; } update_mac(mac_controller::config_tx); @@ -297,7 +297,7 @@ void mac_controller::handle_ho_prep(const asn1::rrc::ho_prep_info_r8_ies_s& ho_p } } -void mac_controller::set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::direction_t dir) +void mac_controller::set_radio_bearer_state(mac_lc_ch_cfg_t::direction_t dir) { for (uint32_t i = srb_to_lcid(lte_srb::srb0); i <= srb_to_lcid(lte_srb::srb2); ++i) { current_sched_ue_cfg.ue_bearers[i].direction = dir; @@ -319,7 +319,7 @@ void mac_controller::set_drb_activation(bool active) { for (const drb_to_add_mod_s& drb : bearer_list.get_established_drbs()) { current_sched_ue_cfg.ue_bearers[drb_to_lcid((lte_drb)drb.drb_id)].direction = - active ? sched_interface::ue_bearer_cfg_t::BOTH : sched_interface::ue_bearer_cfg_t::IDLE; + active ? mac_lc_ch_cfg_t::BOTH : mac_lc_ch_cfg_t::IDLE; } } @@ -388,7 +388,7 @@ void ue_cfg_apply_srb_updates(ue_cfg_t& ue_cfg, const srb_to_add_mod_list_l& srb srslog::fetch_basic_logger("RRC").warning("Invalid SRB ID %d", (int)srb.srb_id); bcfg = {}; } - bcfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + bcfg.direction = srsenb::mac_lc_ch_cfg_t::BOTH; if (srb.lc_ch_cfg_present and srb.lc_ch_cfg.type().value == srb_to_add_mod_s::lc_ch_cfg_c_::types_opts::explicit_value and srb.lc_ch_cfg.explicit_value().ul_specific_params_present) { diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 078a51dbd..c74506a07 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/rrc/rrc.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsenb/hdr/stack/rrc/rrc_cell_cfg.h" #include "srsenb/hdr/stack/rrc/rrc_endc.h" #include "srsenb/hdr/stack/rrc/rrc_mobility.h" @@ -24,7 +25,6 @@ #include "srsran/interfaces/enb_mac_interfaces.h" #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" -#include "srsran/interfaces/sched_interface.h" using srsran::byte_buffer_t; diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 7888799d2..946f977de 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -161,7 +161,7 @@ uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& ue_cfg.supported_cc_list.resize(1); ue_cfg.supported_cc_list[0].active = true; ue_cfg.supported_cc_list[0].enb_cc_idx = target_cell->enb_cc_idx; - ue_cfg.ue_bearers[0].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[0].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; uint16_t rnti = mac->reserve_new_crnti(ue_cfg); if (rnti == SRSRAN_INVALID_RNTI) { diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index ddaab20cc..81fad3b40 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -136,7 +136,7 @@ void rrc::ue::set_radiolink_dl_state(bool crc_res) parent->logger.info( "DL RLF timer stopped for rnti=0x%x (time elapsed=%dms)", rnti, phy_dl_rlf_timer.time_elapsed()); phy_dl_rlf_timer.stop(); - mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::BOTH); + mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::BOTH); } return; } @@ -151,7 +151,7 @@ void rrc::ue::set_radiolink_dl_state(bool crc_res) consecutive_kos_dl++; if (consecutive_kos_dl > parent->cfg.max_mac_dl_kos) { parent->logger.info("Max KOs in DL reached, starting RLF timer rnti=0x%x", rnti); - mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::IDLE); + mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); phy_dl_rlf_timer.run(); } } @@ -168,7 +168,7 @@ void rrc::ue::set_radiolink_ul_state(bool crc_res) parent->logger.info( "UL RLF timer stopped for rnti=0x%x (time elapsed=%dms)", rnti, phy_ul_rlf_timer.time_elapsed()); phy_ul_rlf_timer.stop(); - mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::BOTH); + mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::BOTH); } return; } @@ -190,7 +190,7 @@ void rrc::ue::set_radiolink_ul_state(bool crc_res) consecutive_kos_ul++; if (consecutive_kos_ul > parent->cfg.max_mac_ul_kos) { parent->logger.info("Max KOs in UL reached, starting RLF timer rnti=0x%x", rnti); - mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::IDLE); + mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); phy_ul_rlf_timer.run(); } } @@ -250,7 +250,7 @@ void rrc::ue::max_rlc_retx_reached() parent->logger.info("Max RLC retx reached for rnti=0x%x", rnti); // Turn off scheduling but give UE chance to start re-establishment - mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::IDLE); + mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); rlc_rlf_timer.run(); } diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index d439a44d1..e27f57dad 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -30,7 +30,7 @@ public: int ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) override { return 0; } int ue_rem(uint16_t rnti) override { return 0; } int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) override { return 0; } - int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) override { return 0; } + int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, mac_lc_ch_cfg_t* cfg) override { return 0; } int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override { return 0; } void phy_config_enabled(uint16_t rnti, bool enabled) override {} void write_mcch(const srsran::sib2_mbms_t* sib2_, diff --git a/srsenb/test/mac/sched_common_test_suite.h b/srsenb/test/mac/sched_common_test_suite.h index 7ff5c9f93..bc4d35dfb 100644 --- a/srsenb/test/mac/sched_common_test_suite.h +++ b/srsenb/test/mac/sched_common_test_suite.h @@ -13,11 +13,11 @@ #ifndef SRSRAN_SCHED_COMMON_TEST_SUITE_H #define SRSRAN_SCHED_COMMON_TEST_SUITE_H +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h" #include "srsran/adt/span.h" #include "srsran/common/tti_point.h" -#include "srsran/interfaces/sched_interface.h" namespace srsenb { diff --git a/srsenb/test/mac/sched_lc_ch_test.cc b/srsenb/test/mac/sched_lc_ch_test.cc index 530050e92..d321bb144 100644 --- a/srsenb/test/mac/sched_lc_ch_test.cc +++ b/srsenb/test/mac/sched_lc_ch_test.cc @@ -81,12 +81,12 @@ int test_lc_ch_pbr_infinity() srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg(); ue_cfg = generate_setup_ue_cfg(ue_cfg); ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))] = {}; - ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))] = {}; - ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].priority = 5; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))] = {}; - ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].priority = 3; lch_handler.set_cfg(ue_cfg); @@ -131,14 +131,14 @@ int test_lc_ch_pbr_finite() srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg(); ue_cfg = generate_setup_ue_cfg(ue_cfg); ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))] = {}; - ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid((lte_srb::srb1))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))] = {}; - ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].pbr = 256; // kBps ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].bsd = 50; // msec ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb1))].priority = 5; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))] = {}; - ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].direction = sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].direction = mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].pbr = 8; // kBps ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].bsd = 50; // msec ue_cfg.ue_bearers[drb_to_lcid((lte_drb::drb2))].priority = 3; diff --git a/srsenb/test/mac/sched_sim_ue.cc b/srsenb/test/mac/sched_sim_ue.cc index 4606ba400..fbbb22f44 100644 --- a/srsenb/test/mac/sched_sim_ue.cc +++ b/srsenb/test/mac/sched_sim_ue.cc @@ -61,7 +61,7 @@ void ue_sim::set_cfg(const sched_interface::ue_cfg_t& ue_cfg_) } } -void ue_sim::bearer_cfg(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg) +void ue_sim::bearer_cfg(uint32_t lc_id, const mac_lc_ch_cfg_t& cfg) { ctxt.ue_cfg.ue_bearers.at(lc_id) = cfg; } @@ -269,7 +269,7 @@ int sched_sim_base::ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_ return SRSRAN_SUCCESS; } -int sched_sim_base::bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg) +int sched_sim_base::bearer_cfg(uint16_t rnti, uint32_t lc_id, const mac_lc_ch_cfg_t& cfg) { ue_db.at(rnti).bearer_cfg(lc_id, cfg); return sched_ptr->bearer_ue_cfg(rnti, lc_id, cfg); diff --git a/srsenb/test/mac/sched_sim_ue.h b/srsenb/test/mac/sched_sim_ue.h index 8a39426f5..11fcea029 100644 --- a/srsenb/test/mac/sched_sim_ue.h +++ b/srsenb/test/mac/sched_sim_ue.h @@ -14,7 +14,7 @@ #define SRSRAN_SCHED_SIM_UE_H #include "sched_common_test_suite.h" -#include "srsran/interfaces/sched_interface.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/srslog/srslog.h" #include #include @@ -80,7 +80,7 @@ public: uint32_t preamble_idx); void set_cfg(const sched_interface::ue_cfg_t& ue_cfg_); - void bearer_cfg(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg); + void bearer_cfg(uint32_t lc_id, const mac_lc_ch_cfg_t& cfg); int update(const sf_output_res_t& sf_out); @@ -106,7 +106,7 @@ public: int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx); int ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_); - int bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg); + int bearer_cfg(uint16_t rnti, uint32_t lc_id, const mac_lc_ch_cfg_t& cfg); int rem_user(uint16_t rnti); void new_tti(srsran::tti_point tti_rx); diff --git a/srsenb/test/mac/sched_test_rand.cc b/srsenb/test/mac/sched_test_rand.cc index 766230bea..c55145715 100644 --- a/srsenb/test/mac/sched_test_rand.cc +++ b/srsenb/test/mac/sched_test_rand.cc @@ -19,7 +19,7 @@ #include #include -#include "srsran/interfaces/sched_interface.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/phy/utils/debug.h" #include "sched_common_test_suite.h" diff --git a/srsenb/test/mac/sched_test_utils.h b/srsenb/test/mac/sched_test_utils.h index ed1745ef2..15d96511e 100644 --- a/srsenb/test/mac/sched_test_utils.h +++ b/srsenb/test/mac/sched_test_utils.h @@ -15,8 +15,8 @@ #include "srsenb/hdr/common/common_enb.h" #include "srsenb/hdr/stack/mac/sched.h" +#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/test_common.h" -#include "srsran/interfaces/sched_interface.h" #include #include #include @@ -71,10 +71,10 @@ inline srsenb::sched_interface::ue_cfg_t generate_default_ue_cfg() ue_cfg.supported_cc_list[0].enb_cc_idx = 0; ue_cfg.supported_cc_list[0].active = true; ue_cfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; - ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].group = 1; ue_cfg.pucch_cfg.sr_configured = true; @@ -88,9 +88,9 @@ inline srsenb::sched_interface::ue_cfg_t generate_default_ue_cfg2() { srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg(); - ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].group = 1; return ue_cfg; @@ -99,7 +99,7 @@ inline srsenb::sched_interface::ue_cfg_t generate_default_ue_cfg2() inline srsenb::sched_interface::ue_cfg_t generate_rach_ue_cfg(const srsenb::sched_interface::ue_cfg_t& final_cfg) { srsenb::sched_interface::ue_cfg_t cfg = {}; - cfg.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + cfg.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; cfg.supported_cc_list.resize(1); cfg.supported_cc_list[0].enb_cc_idx = final_cfg.supported_cc_list[0].enb_cc_idx; cfg.supported_cc_list[0].active = true; @@ -111,7 +111,7 @@ inline srsenb::sched_interface::ue_cfg_t generate_setup_ue_cfg(const srsenb::sch srsenb::sched_interface::ue_cfg_t cfg = generate_rach_ue_cfg(final_cfg); cfg.maxharq_tx = final_cfg.maxharq_tx; - cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + cfg.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; cfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; cfg.continuous_pusch = final_cfg.continuous_pusch; @@ -150,11 +150,11 @@ struct tti_ev { uint32_t dl_nof_retxs = 0; ///< update DL buffer retx }; struct user_cfg_ev { - uint16_t rnti; - std::unique_ptr ue_sim_cfg; ///< optional ue_cfg call - std::unique_ptr bearer_cfg; ///< optional bearer_cfg call - std::unique_ptr buffer_ev; ///< update of a user dl/ul buffer - bool rem_user = false; ///< whether to remove a ue + uint16_t rnti; + std::unique_ptr ue_sim_cfg; ///< optional ue_cfg call + std::unique_ptr bearer_cfg; ///< optional bearer_cfg call + std::unique_ptr buffer_ev; ///< update of a user dl/ul buffer + bool rem_user = false; ///< whether to remove a ue }; std::vector user_updates; }; @@ -259,11 +259,9 @@ struct sched_sim_event_generator { ue_sim_cfg.ue_cfg = generate_default_ue_cfg(); user->ue_sim_cfg.reset(new ue_ctxt_test_cfg{ue_sim_cfg}); // it should by now have a DRB1. Add other DRBs manually - user->ue_sim_cfg->ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = - srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - user->ue_sim_cfg->ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = - srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - user->ue_sim_cfg->ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].group = 1; + user->ue_sim_cfg->ue_cfg.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + user->ue_sim_cfg->ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction = srsenb::mac_lc_ch_cfg_t::BOTH; + user->ue_sim_cfg->ue_cfg.ue_bearers[drb_to_lcid(lte_drb::drb1)].group = 1; return user; } diff --git a/srsenb/test/rrc/rrc_mobility_test.cc b/srsenb/test/rrc/rrc_mobility_test.cc index 0c7ac9838..15739a1f7 100644 --- a/srsenb/test/rrc/rrc_mobility_test.cc +++ b/srsenb/test/rrc/rrc_mobility_test.cc @@ -323,7 +323,7 @@ int test_s1ap_tenb_mobility(test_event test_params) auto& mac_ue = tester.mac.ue_db[0x46]; TESTASSERT(mac_ue.supported_cc_list[0].active); TESTASSERT(mac_ue.supported_cc_list[0].enb_cc_idx == 0); - TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction == sched_interface::ue_bearer_cfg_t::BOTH); + TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb0)].direction == mac_lc_ch_cfg_t::BOTH); // Check Security Configuration TESTASSERT(tester.pdcp.bearers.count(0x46)); TESTASSERT(tester.pdcp.bearers[0x46].count(srb_to_lcid(lte_srb::srb1)) and @@ -384,9 +384,9 @@ int test_s1ap_tenb_mobility(test_event test_params) copy_msg_to_buffer(pdu, recfg_complete); tester.rrc.write_pdu(0x46, srb_to_lcid(lte_srb::srb1), std::move(pdu)); tester.tic(); - TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == sched_interface::ue_bearer_cfg_t::BOTH); - TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == sched_interface::ue_bearer_cfg_t::BOTH); - TESTASSERT(mac_ue.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction == sched_interface::ue_bearer_cfg_t::BOTH); + TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == mac_lc_ch_cfg_t::BOTH); + TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == mac_lc_ch_cfg_t::BOTH); + TESTASSERT(mac_ue.ue_bearers[drb_to_lcid(lte_drb::drb1)].direction == mac_lc_ch_cfg_t::BOTH); TESTASSERT(mac_ue.pucch_cfg.I_sr == recfg_r8.rr_cfg_ded.phys_cfg_ded.sched_request_cfg.setup().sr_cfg_idx); TESTASSERT(mac_ue.pucch_cfg.n_pucch_sr == recfg_r8.rr_cfg_ded.phys_cfg_ded.sched_request_cfg.setup().sr_pucch_res_idx); @@ -474,8 +474,8 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) TESTASSERT((1 + recfg_r8.meas_cfg.meas_gap_cfg.setup().gap_offset.type().value) * 40u == tester.cfg.cell_list[1].meas_cfg.meas_gap_period); auto* ue_cfg = &tester.mac.ue_db[tester.rnti]; - TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == srsenb::sched_interface::ue_bearer_cfg_t::DL); - TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == srsenb::sched_interface::ue_bearer_cfg_t::DL); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == srsenb::mac_lc_ch_cfg_t::DL); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == srsenb::mac_lc_ch_cfg_t::DL); /* Test Case: The UE sends a C-RNTI CE. Bearers are reestablished, PHY is configured */ tester.pdcp.last_sdu.sdu = nullptr; @@ -485,12 +485,9 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) TESTASSERT(tester.phy.phy_cfg_set); TESTASSERT(tester.phy.last_cfg.size() == 1 and ue_cfg->supported_cc_list.size() == 1); TESTASSERT(tester.phy.last_cfg[0].enb_cc_idx == ue_cfg->supported_cc_list[0].enb_cc_idx); - TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb0)].direction == - srsenb::sched_interface::ue_bearer_cfg_t::BOTH); - TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == - srsenb::sched_interface::ue_bearer_cfg_t::BOTH); - TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == - srsenb::sched_interface::ue_bearer_cfg_t::BOTH); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb0)].direction == srsenb::mac_lc_ch_cfg_t::BOTH); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == srsenb::mac_lc_ch_cfg_t::BOTH); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == srsenb::mac_lc_ch_cfg_t::BOTH); /* Test Case: The UE receives a duplicate C-RNTI CE. Nothing should happen */ if (test_params == test_event::duplicate_crnti_ce) { From 510a87e4b2ae2f8c06362675827209567f545edf Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 1 Sep 2021 16:44:58 +0200 Subject: [PATCH 47/56] sched,nr: added logic to update UE DL and UL buffer status --- .../hdr/stack/mac/common/ue_buffer_manager.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr.h | 2 + srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 54 ++---------- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 6 ++ srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 7 +- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 6 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 24 ++++-- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 3 +- .../src/stack/mac/common/ue_buffer_manager.cc | 12 +++ srsenb/src/stack/mac/nr/sched_nr.cc | 11 +++ srsenb/src/stack/mac/nr/sched_nr_ue.cc | 84 +++++++++++++------ srsenb/src/stack/mac/nr/sched_nr_worker.cc | 44 +++++----- srsenb/test/mac/nr/sched_nr_rar_test.cc | 14 +++- 13 files changed, 158 insertions(+), 110 deletions(-) diff --git a/srsenb/hdr/stack/mac/common/ue_buffer_manager.h b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h index ea722b8be..52d62beee 100644 --- a/srsenb/hdr/stack/mac/common/ue_buffer_manager.h +++ b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h @@ -70,6 +70,7 @@ public: // UL BSR methods bool is_lcg_active(uint32_t lcg) const; int get_bsr(uint32_t lcg) const; + int get_bsr() const; const std::array& get_bsr_state() const { return lcg_bsr; } static bool is_lcid_valid(uint32_t lcid) { return lcid <= MAX_LC_ID; } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 0fcddcd84..7a5b9e54d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -46,6 +46,8 @@ public: void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override; void ul_sr_info(slot_point slot_rx, uint16_t rnti) override; + void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr); + void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx); int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_res_t& result) override; int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) override; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index a236c12f2..b2295c2fc 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -27,10 +27,14 @@ namespace sched_nr_impl { const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS; -using pucch_t = mac_interface_phy_nr::pucch_t; -using pucch_list_t = srsran::bounded_vector; -using pusch_t = mac_interface_phy_nr::pusch_t; -using pusch_list_t = srsran::bounded_vector; +using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; +using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; +using pdcch_dl_list_t = srsran::bounded_vector; +using pdcch_ul_list_t = srsran::bounded_vector; +using pucch_t = mac_interface_phy_nr::pucch_t; +using pucch_list_t = srsran::bounded_vector; +using pusch_t = mac_interface_phy_nr::pusch_t; +using pusch_list_t = srsran::bounded_vector; using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; @@ -159,48 +163,6 @@ public: std::vector cc_params; }; -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -struct resource_guard { -public: - resource_guard() = default; - resource_guard(const resource_guard& other) = delete; - resource_guard(resource_guard&& other) = delete; - resource_guard& operator=(const resource_guard& other) = delete; - resource_guard& operator=(resource_guard&& other) = delete; - bool busy() const { return flag; } - - struct token { - token() = default; - token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag) - { - if (flag != nullptr) { - *flag = true; - } - } - token(token&&) noexcept = default; - token& operator=(token&&) noexcept = default; - void release() { flag.reset(); } - bool owns_token() const { return flag != nullptr; } - bool empty() const { return flag == nullptr; } - - private: - struct release_deleter { - void operator()(bool* ptr) - { - if (ptr != nullptr) { - srsran_assert(*ptr == true, "resource token: detected inconsistency token state"); - *ptr = false; - } - } - }; - std::unique_ptr flag; - }; - -private: - bool flag = false; -}; - } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 103c6ed80..66f83f90b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -41,6 +41,7 @@ public: uint32_t ndi() const { return tb[0].ndi; } uint32_t mcs() const { return tb[0].mcs; } const prb_grant& prbs() const { return prbs_; } + slot_point harq_slot_tx() const { return slot_tx; } slot_point harq_slot_ack() const { return slot_ack; } bool ack_info(uint32_t tb_idx, bool ack); @@ -126,6 +127,11 @@ public: void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } void ul_crc_info(uint32_t pid, bool ack) { ul_harqs[pid].ack_info(0, ack); } + uint32_t nof_dl_harqs() const { return dl_harqs.size(); } + uint32_t nof_ul_harqs() const { return ul_harqs.size(); } + const dl_harq_proc& dl_harq(uint32_t pid) const { return dl_harqs[pid]; } + const ul_harq_proc& ul_harq(uint32_t pid) const { return ul_harqs[pid]; } + dl_harq_proc* find_pending_dl_retx() { return find_dl([this](const dl_harq_proc& h) { return h.has_pending_retx(slot_rx); }); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index daa35b72b..b0e7ec713 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -66,9 +66,10 @@ public: }; struct sched_cfg_t { - bool pdsch_enabled = true; - bool pusch_enabled = true; - std::string logger_name = "MAC"; + bool pdsch_enabled = true; + bool pusch_enabled = true; + bool auto_refill_buffer = true; + std::string logger_name = "MAC"; }; struct ue_cc_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index 98e59f34a..d2dad1b36 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -29,11 +29,7 @@ enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data }; class slot_ue; -using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; -using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; -using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; -using pdcch_dl_list_t = srsran::bounded_vector; -using pdcch_ul_list_t = srsran::bounded_vector; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; class coreset_region { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 24b563745..044d10fdd 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -42,7 +42,7 @@ public: uint32_t cc = SCHED_NR_MAX_CARRIERS; // UE parameters common to all sectors - bool pending_sr = false; + int dl_pending_bytes = 0, ul_pending_bytes = 0; // UE parameters that are sector specific const bwp_ue_cfg* cfg = nullptr; @@ -61,8 +61,7 @@ class ue_carrier { public: ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_); - void new_slot(slot_point pdcch_slot, const ue_cfg_t& uecfg_); - slot_ue try_reserve(slot_point pdcch_slot); + slot_ue try_reserve(slot_point pdcch_slot, const ue_cfg_t& uecfg_, uint32_t dl_harq_bytes, uint32_t ul_harq_bytes); const uint16_t rnti; const uint32_t cc; @@ -83,25 +82,34 @@ class ue public: ue(uint16_t rnti, const ue_cfg_t& cfg, const sched_params& sched_cfg_); + void new_slot(slot_point pdcch_slot); + slot_ue try_reserve(slot_point pdcch_slot, uint32_t cc); void set_cfg(const ue_cfg_t& cfg); const ue_cfg_t& cfg() const { return ue_cfg; } - void ul_sr_info(slot_point slot_rx) { pending_sr = true; } + void rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t retx) { buffers.dl_buffer_state(lcid, newtx, retx); } void ul_bsr(uint32_t lcg, uint32_t bsr_val) { buffers.ul_bsr(lcg, bsr_val); } - - bool has_ca() const { return ue_cfg.carriers.size() > 1; } + void ul_sr_info(slot_point slot_rx) { last_sr_slot = slot_rx; } + + bool has_ca() const + { + return ue_cfg.carriers.size() > 1 and std::count_if(ue_cfg.carriers.begin() + 1, + ue_cfg.carriers.end(), + [](const ue_cc_cfg_t& cc) { return cc.active; }) > 0; + } uint32_t pcell_cc() const { return ue_cfg.carriers[0].cc; } + ue_buffer_manager buffers; std::array, SCHED_NR_MAX_CARRIERS> carriers; private: const uint16_t rnti; const sched_params& sched_cfg; - bool pending_sr = false; - ue_buffer_manager buffers; + slot_point last_sr_slot; + int ul_pending_bytes = 0, dl_pending_bytes = 0; ue_cfg_t ue_cfg; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 25c8612c2..fb739f6fd 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -39,7 +39,6 @@ public: explicit slot_cc_worker(serv_cell_manager& sched); void run(slot_point pdcch_slot, ue_map_t& ue_db_); - void finish(); bool running() const { return slot_rx.valid(); } void enqueue_cc_event(srsran::move_callback ev); @@ -102,6 +101,8 @@ public: } private: + void update_ue_db(slot_point slot_tx, bool update_ca_users); + bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res); const sched_params& cfg; diff --git a/srsenb/src/stack/mac/common/ue_buffer_manager.cc b/srsenb/src/stack/mac/common/ue_buffer_manager.cc index 775d20fb1..52593d685 100644 --- a/srsenb/src/stack/mac/common/ue_buffer_manager.cc +++ b/srsenb/src/stack/mac/common/ue_buffer_manager.cc @@ -76,6 +76,18 @@ int ue_buffer_manager::get_bsr(uint32_t lcg) const return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0; } +template +int ue_buffer_manager::get_bsr() const +{ + uint32_t count = 0; + for (uint32_t lcg = 0; is_lcg_valid(lcg); ++lcg) { + if (is_lcg_active(lcg)) { + count += lcg_bsr[lcg]; + } + } + return count; +} + template void ue_buffer_manager::ul_bsr(uint32_t lcg_id, uint32_t val) { diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index a86d6108c..721b18a66 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -151,6 +151,17 @@ void sched_nr::ul_sr_info(slot_point slot_rx, uint16_t rnti) sched_workers->enqueue_event(rnti, [this, rnti, slot_rx]() { ue_db[rnti]->ul_sr_info(slot_rx); }); } +void sched_nr::ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) +{ + sched_workers->enqueue_event(rnti, [this, rnti, lcg_id, bsr]() { ue_db[rnti]->ul_bsr(lcg_id, bsr); }); +} + +void sched_nr::dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx) +{ + sched_workers->enqueue_event(rnti, + [this, rnti, lcid, newtx, retx]() { ue_db[rnti]->rlc_buffer_state(lcid, newtx, retx); }); +} + #define VERIFY_INPUT(cond, msg, ...) \ do { \ if (not(cond)) { \ diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 6d3cf5509..f14388166 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -29,23 +29,23 @@ ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_ harq_ent(cell_params_.nof_prb()) {} -void ue_carrier::new_slot(slot_point pdcch_slot, const ue_cfg_t& uecfg_) +slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, + const ue_cfg_t& uecfg_, + uint32_t dl_pending_bytes, + uint32_t ul_pending_bytes) { + slot_point slot_rx = pdcch_slot - TX_ENB_DELAY; + + // update CC/BWP config if there were changes if (bwp_cfg.ue_cfg() != &uecfg_) { bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], uecfg_); } - harq_ent.new_slot(pdcch_slot - TX_ENB_DELAY); -} - -slot_ue ue_carrier::try_reserve(slot_point pdcch_slot) -{ - slot_point slot_rx = pdcch_slot - TX_ENB_DELAY; // copy cc-specific parameters and find available HARQs slot_ue sfu(rnti, slot_rx, cc); sfu.cfg = &bwp_cfg; - sfu.harq_ent = &harq_ent; sfu.pdcch_slot = pdcch_slot; + sfu.harq_ent = &harq_ent; const uint32_t k0 = 0; sfu.pdsch_slot = sfu.pdcch_slot + k0; uint32_t k1 = @@ -57,45 +57,81 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot) sfu.dl_cqi = dl_cqi; sfu.ul_cqi = ul_cqi; + // set UE-common parameters + sfu.dl_pending_bytes = dl_pending_bytes; + sfu.ul_pending_bytes = ul_pending_bytes; + const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { // If DL enabled sfu.h_dl = harq_ent.find_pending_dl_retx(); - if (sfu.h_dl == nullptr) { + if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) { sfu.h_dl = harq_ent.find_empty_dl_harq(); } } if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { // If UL enabled sfu.h_ul = harq_ent.find_pending_ul_retx(); - if (sfu.h_ul == nullptr) { + if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) { sfu.h_ul = harq_ent.find_empty_ul_harq(); } } - if (sfu.h_dl == nullptr and sfu.h_ul == nullptr) { - // there needs to be at least one available HARQ for newtx/retx - sfu.release(); - return sfu; - } return sfu; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : - rnti(rnti_), sched_cfg(sched_cfg_), ue_cfg(cfg), buffers(srslog::fetch_basic_logger(sched_cfg_.sched_cfg.logger_name)) + rnti(rnti_), sched_cfg(sched_cfg_), buffers(srslog::fetch_basic_logger(sched_cfg_.sched_cfg.logger_name)) { - for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { - if (cfg.carriers[cc].active) { - carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc])); - } - } + set_cfg(cfg); } void ue::set_cfg(const ue_cfg_t& cfg) { ue_cfg = cfg; + for (auto& ue_cc_cfg : cfg.carriers) { + if (ue_cc_cfg.active and carriers[ue_cc_cfg.cc] == nullptr) { + carriers[ue_cc_cfg.cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[ue_cc_cfg.cc])); + } + } +} + +void ue::new_slot(slot_point pdcch_slot) +{ + for (auto& ue_cc_cfg : ue_cfg.carriers) { + auto& cc = carriers[ue_cc_cfg.cc]; + if (cc != nullptr) { + // Update CC HARQ state + cc->harq_ent.new_slot(pdcch_slot - TX_ENB_DELAY); + } + } + + // Compute pending DL/UL bytes for {rnti, pdcch_slot} + if (sched_cfg.sched_cfg.auto_refill_buffer) { + dl_pending_bytes = 1000000; + ul_pending_bytes = 1000000; + } else { + dl_pending_bytes = buffers.get_dl_tx_total(); + ul_pending_bytes = buffers.get_bsr(); + for (auto& ue_cc_cfg : ue_cfg.carriers) { + auto& cc = carriers[ue_cc_cfg.cc]; + if (cc != nullptr) { + // Discount UL HARQ pending bytes to BSR + for (uint32_t pid = 0; pid < cc->harq_ent.nof_dl_harqs(); ++pid) { + ul_pending_bytes -= cc->harq_ent.ul_harq(pid).tbs(); + if (last_sr_slot.valid() and cc->harq_ent.ul_harq(pid).harq_slot_tx() > last_sr_slot) { + last_sr_slot.clear(); + } + } + } + } + if (ul_pending_bytes == 0 and last_sr_slot.valid()) { + // If unanswered SR is pending + ul_pending_bytes = 512; + } + } } slot_ue ue::try_reserve(slot_point pdcch_slot, uint32_t cc) @@ -103,14 +139,12 @@ slot_ue ue::try_reserve(slot_point pdcch_slot, uint32_t cc) if (carriers[cc] == nullptr) { return slot_ue(); } - slot_ue sfu = carriers[cc]->try_reserve(pdcch_slot); + + slot_ue sfu = carriers[cc]->try_reserve(pdcch_slot, cfg(), dl_pending_bytes, ul_pending_bytes); if (sfu.empty()) { return slot_ue(); } - // set UE-common parameters - sfu.pending_sr = pending_sr; - return sfu; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index afc93f6a7..f0c682c16 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -75,8 +75,6 @@ void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db) continue; } - u.carriers[cfg.cc]->new_slot(pdcch_slot, u.cfg()); - slot_ues.insert(rnti, u.try_reserve(pdcch_slot, cfg.cc)); if (slot_ues[rnti].empty()) { // Failed to generate slot UE because UE has no conditions for DL/UL tx @@ -104,11 +102,6 @@ void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db) slot_rx = {}; } -void slot_cc_worker::finish() -{ - // synchronize results -} - void slot_cc_worker::alloc_dl_ues() { if (not cfg.sched_cfg.pdsch_enabled) { @@ -151,6 +144,28 @@ void sched_worker_manager::enqueue_cc_event(uint32_t cc, srsran::move_callbackworker.enqueue_cc_event(std::move(ev)); } +/** + * Update UEs state that is non-CC specific (e.g. SRs, buffer status, UE configuration) + * @param slot_tx + * @param update_ca_users to update only UEs with CA enabled or not + */ +void sched_worker_manager::update_ue_db(slot_point slot_tx, bool update_ca_users) +{ + // process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config) + for (ue_event_t& ev : slot_events) { + if (not ue_db.contains(ev.rnti) or ue_db[ev.rnti]->has_ca() == update_ca_users) { + ev.callback(); + } + } + + // prepare UEs internal state for new slot + for (auto& u : ue_db) { + if (u.second->has_ca() == update_ca_users) { + u.second->new_slot(slot_tx); + } + } +} + void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res) { srsran::bounded_vector waiting_cvars; @@ -165,18 +180,14 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_re if (not current_slot.valid()) { /* First Worker to start slot */ - // process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config) for UEs with CA + // process non-cc specific feedback if pending for UEs with CA // NOTE: there is no parallelism in these operations slot_events.clear(); { std::lock_guard ev_lock(event_mutex); next_slot_events.swap(slot_events); } - for (ue_event_t& ev : slot_events) { - if (not ue_db.contains(ev.rnti) or ue_db[ev.rnti]->has_ca()) { - ev.callback(); - } - } + update_ue_db(slot_tx, true); // mark the start of slot. awake remaining workers if locking on the mutex current_slot = slot_tx; @@ -197,11 +208,7 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_re /* Parallel Region */ // process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config) for UEs without CA - for (ue_event_t& ev : slot_events) { - if (ue_db.contains(ev.rnti) and not ue_db[ev.rnti]->has_ca() and ue_db[ev.rnti]->pcell_cc() == cc) { - ev.callback(); - } - } + update_ue_db(slot_tx, false); // process pending feedback, generate {slot, cc} scheduling decision cc_worker_list[cc]->worker.run(slot_tx, ue_db); @@ -218,7 +225,6 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_re // All the workers of the same slot have finished. Synchronize scheduling decisions with UEs state for (auto& c : cc_worker_list) { - c->worker.finish(); if (c->waiting > 0) { waiting_cvars.push_back(&c->cvar); } diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsenb/test/mac/nr/sched_nr_rar_test.cc index e4ef8ff56..1104b914f 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsenb/test/mac/nr/sched_nr_rar_test.cc @@ -29,7 +29,11 @@ void test_single_prach() std::default_random_engine rand_gen(seed); std::default_random_engine rgen(rand_gen()); - sched_nr_interface::sched_cfg_t sched_cfg{}; + // Set scheduler configuration + sched_nr_interface::sched_cfg_t sched_cfg{}; + sched_cfg.auto_refill_buffer = std::uniform_int_distribution{0, 1}(rgen) > 0; + + // Set cells configuration std::vector cells_cfg = get_default_cells_cfg(1); sched_params schedparams{sched_cfg}; schedparams.cells.emplace_back(0, cells_cfg[0], sched_cfg); @@ -52,10 +56,14 @@ void test_single_prach() const bwp_slot_grid* result = nullptr; auto run_slot = [&alloc, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* { mac_logger.set_context(pdcch_slot.to_uint()); - u.carriers[0]->new_slot(pdcch_slot, u.cfg()); + u.new_slot(pdcch_slot); slot_ues.clear(); - slot_ues.insert(rnti, u.try_reserve(pdcch_slot, 0)); + slot_ue sfu = u.try_reserve(pdcch_slot, 0); + if (not sfu.empty()) { + slot_ues.insert(rnti, std::move(sfu)); + } alloc.new_slot(pdcch_slot, slot_ues); + rasched.run_slot(alloc); log_sched_bwp_result(mac_logger, alloc.get_pdcch_tti(), alloc.res_grid(), slot_ues); From 75cd71b794291fd6875d1b5a194f78e1f8a8611b Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 1 Sep 2021 17:30:27 +0200 Subject: [PATCH 48/56] sched,nr: fix older gcc compilation array initialization --- srsenb/hdr/stack/mac/common/ue_buffer_manager.h | 4 ++-- srsenb/src/stack/mac/common/ue_buffer_manager.cc | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/srsenb/hdr/stack/mac/common/ue_buffer_manager.h b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h index 52d62beee..8eaba18f7 100644 --- a/srsenb/hdr/stack/mac/common/ue_buffer_manager.h +++ b/srsenb/hdr/stack/mac/common/ue_buffer_manager.h @@ -36,7 +36,7 @@ protected: constexpr static uint32_t pbr_infinity = -1; public: - explicit ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_) {} + explicit ue_buffer_manager(srslog::basic_logger& logger_); // Bearer configuration void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg); @@ -88,7 +88,7 @@ protected: }; std::array channels; - std::array lcg_bsr{0}; + std::array lcg_bsr; }; } // namespace srsenb diff --git a/srsenb/src/stack/mac/common/ue_buffer_manager.cc b/srsenb/src/stack/mac/common/ue_buffer_manager.cc index 52593d685..a2cbb5198 100644 --- a/srsenb/src/stack/mac/common/ue_buffer_manager.cc +++ b/srsenb/src/stack/mac/common/ue_buffer_manager.cc @@ -17,6 +17,12 @@ namespace srsenb { +template +ue_buffer_manager::ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_) +{ + std::fill(lcg_bsr.begin(), lcg_bsr.end(), 0); +} + template void ue_buffer_manager::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg) { From 5f9aceb8b6bea0e5e616e958b74ddcb9d2d37e4c Mon Sep 17 00:00:00 2001 From: faluco Date: Thu, 2 Sep 2021 13:01:29 +0200 Subject: [PATCH 49/56] Fix alignment issue with the stdout metrics in srsue. --- srsue/src/metrics_stdout.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/srsue/src/metrics_stdout.cc b/srsue/src/metrics_stdout.cc index 74efc9cd7..ae66b3f9f 100644 --- a/srsue/src/metrics_stdout.cc +++ b/srsue/src/metrics_stdout.cc @@ -68,22 +68,22 @@ void metrics_stdout::print_table(const bool display_neighbours, const bool is_nr if (is_nr) { if (display_neighbours) { fmt::print( - "---------Signal----------|-Neighbour-|-----------------DL-----------------|-----------UL-----------\n"); + "---------Signal-----------|-Neighbour-|-----------------DL-----------------|-----------UL-----------\n"); fmt::print( - "rat pci rsrp pl cfo | pci rsrp | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); + "rat pci rsrp pl cfo | pci rsrp | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); } else { - fmt::print("---------Signal----------|-----------------DL-----------------|-----------UL-----------\n"); - fmt::print("rat pci rsrp pl cfo | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); + fmt::print("---------Signal-----------|-----------------DL-----------------|-----------UL-----------\n"); + fmt::print("rat pci rsrp pl cfo | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); } } else { if (display_neighbours) { fmt::print( - "---------Signal----------|-Neighbour-|-----------------DL-----------------|-----------UL-----------\n"); + "---------Signal-----------|-Neighbour-|-----------------DL-----------------|-----------UL-----------\n"); fmt::print( - " cc pci rsrp pl cfo | pci rsrp | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); + " cc pci rsrp pl cfo | pci rsrp | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); } else { - fmt::print("---------Signal----------|-----------------DL-----------------|-----------UL-----------\n"); - fmt::print(" cc pci rsrp pl cfo | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); + fmt::print("---------Signal-----------|-----------------DL-----------------|-----------UL-----------\n"); + fmt::print(" cc pci rsrp pl cfo | mcs snr iter brate bler ta_us | mcs buff brate bler\n"); } } table_has_neighbours = display_neighbours; @@ -111,7 +111,7 @@ void metrics_stdout::set_metrics_helper(const phy_metrics_t& phy, } fmt::print(" {:>4}", int(phy.ch[r].rsrp)); - fmt::print(" {:>2}", int(phy.ch[r].pathloss)); + fmt::print(" {:>4}", int(phy.ch[r].pathloss)); fmt::print(" {:>5.5}", float_to_eng_string(phy.sync[r].cfo, 2)); // Find strongest neighbour for this EARFCN (cells are ordered) From ebef8a4cc46f6867c6ec5bac6d6d6f6a7a5d5c8c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Sep 2021 14:13:18 +0200 Subject: [PATCH 50/56] enb_stack_lte: implement the PDCP interface for GTPU on the stack this prepares for a change in which GTPU no longer writes into PDCP directly but instead uses the stack as a wrapper. For this the interface will be changed to use the EPS bearer ID instead of the LCID The stack will know which PDCP entity (EUTRA or NR) is currently associated with the EPS bearer ID and will forward the PDU accordingly. --- srsenb/hdr/stack/enb_stack_lte.h | 5 +++++ srsenb/src/stack/enb_stack_lte.cc | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 925c64f5e..94d970b63 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -38,6 +38,7 @@ namespace srsenb { class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, public stack_interface_phy_nr, + public pdcp_interface_gtpu, public srsran::thread { public: @@ -132,6 +133,10 @@ public: } void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); } + // pdcp_interface_gtpu + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override; + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override; + private: static const int STACK_MAIN_THREAD_PRIO = 4; // thread loop diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index e936d3a79..14e231dcb 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -187,7 +187,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) gtpu_args.mme_addr = args.s1ap.mme_addr; gtpu_args.gtp_bind_addr = args.s1ap.gtp_bind_addr; gtpu_args.indirect_tunnel_timeout_msec = args.gtpu_indirect_tunnel_timeout_msec; - if (gtpu.init(gtpu_args, &pdcp) != SRSRAN_SUCCESS) { + if (gtpu.init(gtpu_args, this) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize GTPU"); return SRSRAN_ERROR; } @@ -278,4 +278,17 @@ void enb_stack_lte::run_thread() } } +void enb_stack_lte::write_sdu(uint16_t rnti, + uint32_t lcid /* to be replaced with eps_bearer_id */, + srsran::unique_byte_buffer_t sdu, + int pdcp_sn) +{ + pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); +} + +std::map enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid) +{ + return pdcp.get_buffered_pdus(rnti, lcid); +} + } // namespace srsenb From db8b71044254baf25522a31661ba3f71cacc42fc Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Sep 2021 15:58:43 +0200 Subject: [PATCH 51/56] bearer_manager: move to lib folder and extend for multiple users prepare bearer manager to be used by eNB which requires to support multiple RNTIs --- lib/include/srsran/common/bearer_manager.h | 92 ++++++++++++++ lib/src/common/CMakeLists.txt | 2 +- lib/src/common/bearer_manager.cc | 133 +++++++++++++++++++++ srsue/hdr/stack/bearer_manager.h | 73 ----------- srsue/hdr/stack/ue_stack_lte.h | 2 +- srsue/src/stack/CMakeLists.txt | 2 +- srsue/src/stack/bearer_manager.cc | 75 ------------ 7 files changed, 228 insertions(+), 151 deletions(-) create mode 100644 lib/include/srsran/common/bearer_manager.h create mode 100644 lib/src/common/bearer_manager.cc delete mode 100644 srsue/hdr/stack/bearer_manager.h delete mode 100644 srsue/src/stack/bearer_manager.cc diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h new file mode 100644 index 000000000..9a585476b --- /dev/null +++ b/lib/include/srsran/common/bearer_manager.h @@ -0,0 +1,92 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_BEARER_MANAGER_H +#define SRSRAN_BEARER_MANAGER_H + +#include "srsran/common/common.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/srslog/srslog.h" +#include +#include + +namespace srsran { + +/** + * @brief Helper class to manage the mapping between EPS bearer and radio bearer + * + * The class maps EPS bearers that are known to NAS and GW (UE) or GTPU (eNB) + * to radio bearer (RB) that are only known to RRC. + * Since the lifetime of a EPS bearer is usually longer than the lifetime of a RB, + * the GW/GTPU needs to query the Stack to check whether a + * given EPS bearer is active, i.e. a DRB is established, or not. + * + * The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both. + * + * Since the access of this class is happening from two different threads (GW+RRC/Stack) + * it's public interface is protected. + * + * The class provides two interfaces to be used with RNTI or without. The version without + * RNTI is used by the UE. The version with RNTI in the interface is intented to be + * used by the eNB. + * + */ +class bearer_manager +{ +public: + bearer_manager(); + ~bearer_manager(); + + struct radio_bearer_t { + srsran::srsran_rat_t rat; + uint32_t lcid; + }; + + /// Single user interface (for UE) + + // RRC interface + /// Registers EPS bearer with PDCP RAT type and LCID + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); + + /// Single EPS bearer is removed from map when the associated DRB is deleted + void remove_eps_bearer(uint8_t eps_bearer_id); + + /// All registered bearer are removed (e.g. after connection release) + void reset(); + + // GW interface + bool has_active_radio_bearer(uint32_t eps_bearer_id); + + // Stack interface to retrieve active RB + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); + + /// Multi-user interface (see comments above) + void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); + void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id); + void reset(uint16_t rnti); + bool has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id); + radio_bearer_t get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id); + +private: + pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads + srslog::basic_logger& logger; + + typedef std::map eps_rb_map_t; + std::map users_map; + + const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI + radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; +}; + +} // namespace srsran + +#endif // SRSRAN_BEARER_MANAGER_H \ No newline at end of file diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 12a78d129..dce6eaf2b 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -6,12 +6,12 @@ # the distribution. # - set(SOURCES arch_select.cc enb_events.cc backtrace.c byte_buffer.cc band_helper.cc + bearer_manager.cc buffer_pool.cc crash_handler.cc gen_mch_tables.c diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc new file mode 100644 index 000000000..bef2048cb --- /dev/null +++ b/lib/src/common/bearer_manager.cc @@ -0,0 +1,133 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/common/bearer_manager.h" + +namespace srsran { + +bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) +{ + pthread_rwlock_init(&rwlock, nullptr); +} + +bearer_manager::~bearer_manager() +{ + pthread_rwlock_destroy(&rwlock); +} + +void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + add_eps_bearer(default_key, eps_bearer_id, rat, lcid); +} + +void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + // add empty bearer map + users_map.emplace(rnti, eps_rb_map_t{}); + user_it = users_map.find(rnti); + } + + auto bearer_it = user_it->second.find(eps_bearer_id); + if (bearer_it != user_it->second.end()) { + logger.error("EPS bearer ID %d already registered", eps_bearer_id); + return; + } + user_it->second.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); + logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); +} + +void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) +{ + remove_eps_bearer(default_key, eps_bearer_id); +} + +void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + logger.error("No EPS bearer registered for rnti=%x", rnti); + return; + } + + auto bearer_it = user_it->second.find(eps_bearer_id); + if (bearer_it == user_it->second.end()) { + logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); + return; + } + user_it->second.erase(bearer_it); + logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); +} + +void bearer_manager::reset() +{ + reset(default_key); +} + +void bearer_manager::reset(uint16_t rnti) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + logger.error("No EPS bearer registered for rnti=%x", rnti); + return; + } + + user_it->second.clear(); + logger.info("Reset EPS bearer manager"); +} + +// GW interface +bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) +{ + return has_active_radio_bearer(default_key, eps_bearer_id); +} + +bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) +{ + srsran::rwlock_read_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + return false; + } + + return user_it->second.find(eps_bearer_id) != user_it->second.end(); +} + +// Stack interface +bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) +{ + return get_radio_bearer(default_key, eps_bearer_id); +} + +bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) +{ + srsran::rwlock_read_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + return invalid_rb; + } + + if (user_it->second.find(eps_bearer_id) != user_it->second.end()) { + return user_it->second.at(eps_bearer_id); + } + return invalid_rb; +} + +} // namespace srsue \ No newline at end of file diff --git a/srsue/hdr/stack/bearer_manager.h b/srsue/hdr/stack/bearer_manager.h deleted file mode 100644 index 7e2d3d779..000000000 --- a/srsue/hdr/stack/bearer_manager.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSUE_BEARER_MANAGER_H -#define SRSUE_BEARER_MANAGER_H - -#include "srsran/common/common.h" -#include "srsran/common/rwlock_guard.h" -#include "srsran/srslog/srslog.h" -#include -#include - -namespace srsue { - -/** - * @brief Helper class to manage the mapping between EPS bearer and radio bearer - * - * The class maps EPS bearers that are known to NAS and GW and radio bearer (RB) that - * are only known to RRC. Since the lifetime of a EPS bearer is usually longer - * than the lifetime of a RB, the GW needs to query the Stack to check whether a - * given EPS bearer is active, i.e. a DRB is established, or not. - * - * The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both. - * - * Since the access of this class is happening from two different threads (GW+RRC/Stack) - * it's public interface is protected. - * - */ -class bearer_manager -{ -public: - bearer_manager(); - ~bearer_manager(); - - // RRC interface - /// Registers EPS bearer with PDCP RAT type and LCID - void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); - - /// Single EPS bearer is removed from map when the associated DRB is deleted - void remove_eps_bearer(uint8_t eps_bearer_id); - - /// All registered bearer are removed (e.g. after connection release) - void reset(); - - // GW interface - bool has_active_radio_bearer(uint32_t eps_bearer_id); - - // Stack interface to retrieve active RB - struct radio_bearer_t { - srsran::srsran_rat_t rat; - uint32_t lcid; - }; - radio_bearer_t& get_radio_bearer(uint32_t eps_bearer_id); - -private: - pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads - srslog::basic_logger& logger; - std::map eps_rb_map; - radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; -}; - -} // namespace srsue - -#endif // SRSUE_BEARER_MANAGER_H \ No newline at end of file diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 55938bc3c..b6ed87e5f 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -31,7 +31,7 @@ #include "upper/nas.h" #include "upper/usim.h" -#include "bearer_manager.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/multiqueue.h" #include "srsran/common/string_helpers.h" diff --git a/srsue/src/stack/CMakeLists.txt b/srsue/src/stack/CMakeLists.txt index 1d2e9e1aa..c2834833e 100644 --- a/srsue/src/stack/CMakeLists.txt +++ b/srsue/src/stack/CMakeLists.txt @@ -11,7 +11,7 @@ add_subdirectory(mac) add_subdirectory(rrc) add_subdirectory(upper) -set(SOURCES ue_stack_lte.cc bearer_manager.cc) +set(SOURCES ue_stack_lte.cc) add_library(srsue_stack STATIC ${SOURCES}) add_subdirectory(mac_nr) diff --git a/srsue/src/stack/bearer_manager.cc b/srsue/src/stack/bearer_manager.cc deleted file mode 100644 index 862fd1ba5..000000000 --- a/srsue/src/stack/bearer_manager.cc +++ /dev/null @@ -1,75 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include "srsue/hdr/stack/bearer_manager.h" - -namespace srsue { - -bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) -{ - pthread_rwlock_init(&rwlock, nullptr); -} - -bearer_manager::~bearer_manager() -{ - pthread_rwlock_destroy(&rwlock); -} - -void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) -{ - srsran::rwlock_write_guard rw_lock(rwlock); - auto it = eps_rb_map.find(eps_bearer_id); - if (it != eps_rb_map.end()) { - logger.error("EPS bearer ID %d already registered", eps_bearer_id); - return; - } - eps_rb_map.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); - logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); -} - -void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) -{ - srsran::rwlock_write_guard rw_lock(rwlock); - auto it = eps_rb_map.find(eps_bearer_id); - if (it == eps_rb_map.end()) { - logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); - return; - } - eps_rb_map.erase(it); - logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); -} - -void bearer_manager::reset() -{ - srsran::rwlock_write_guard rw_lock(rwlock); - eps_rb_map.clear(); - logger.info("Reset EPS bearer manager"); -} - -// GW interface -bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) -{ - srsran::rwlock_read_guard rw_lock(rwlock); - return eps_rb_map.find(eps_bearer_id) != eps_rb_map.end(); -} - -// Stack interface -bearer_manager::radio_bearer_t& bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) -{ - srsran::rwlock_read_guard rw_lock(rwlock); - if (eps_rb_map.find(eps_bearer_id) != eps_rb_map.end()) { - return eps_rb_map.at(eps_bearer_id); - } - return invalid_rb; -} - -} // namespace srsue \ No newline at end of file From 3949a727a7ca98faa1d73959e11f2e47c9996ac3 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Sep 2021 16:31:15 +0200 Subject: [PATCH 52/56] enb_interface: add stack interface for RRC RRC uses the interface to register/deregister EPS bearer --- lib/include/srsran/interfaces/enb_interfaces.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/include/srsran/interfaces/enb_interfaces.h b/lib/include/srsran/interfaces/enb_interfaces.h index 6f959a975..715edd0bf 100644 --- a/lib/include/srsran/interfaces/enb_interfaces.h +++ b/lib/include/srsran/interfaces/enb_interfaces.h @@ -19,6 +19,14 @@ namespace srsenb { +class stack_interface_rrc +{ +public: + virtual void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0; + virtual void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) = 0; + virtual void reset_eps_bearers(uint16_t rnti) = 0; +}; + class stack_interface_phy_lte; } // namespace srsenb From b27d1d913e2e663c2689498cb5b6f400ee901831 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Sep 2021 16:32:06 +0200 Subject: [PATCH 53/56] enb_stack_lte: use bearer manager class * user common bearer manager in eNB * register/deregister bearers (LTE only so far * provide dummy stack class for RRC tests --- srsenb/hdr/stack/enb_stack_lte.h | 9 +++++++ srsenb/hdr/stack/rrc/rrc.h | 3 ++- srsenb/src/stack/enb_stack_lte.cc | 35 +++++++++++++++++++++++----- srsenb/src/stack/rrc/rrc.cc | 4 ++-- srsenb/src/stack/rrc/rrc_ue.cc | 7 ++++++ srsenb/test/rrc/erab_setup_test.cc | 3 ++- srsenb/test/rrc/rrc_mobility_test.cc | 3 ++- srsenb/test/rrc/test_helpers.h | 7 ++++++ 8 files changed, 60 insertions(+), 11 deletions(-) diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 94d970b63..53edd3ab8 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -29,6 +29,7 @@ #include "upper/rlc.h" #include "enb_stack_base.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/mac_pcap_net.h" #include "srsran/interfaces/enb_interfaces.h" #include "srsran/srslog/srslog.h" @@ -38,6 +39,7 @@ namespace srsenb { class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, public stack_interface_phy_nr, + public stack_interface_rrc, public pdcp_interface_gtpu, public srsran::thread { @@ -137,6 +139,11 @@ public: void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override; std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override; + // interface for bearer manager + void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) override; + void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) override; + void reset_eps_bearers(uint16_t rnti) override; + private: static const int STACK_MAIN_THREAD_PRIO = 4; // thread loop @@ -184,6 +191,8 @@ private: srsenb::pdcp pdcp_nr; srsenb::rrc_nr rrc_nr; + srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers + // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; phy_interface_stack_nr* phy_nr = nullptr; diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index c0aec7310..0e5245a31 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -53,7 +53,7 @@ class rrc final : public rrc_interface_pdcp, public rrc_eutra_interface_rrc_nr { public: - explicit rrc(srsran::task_sched_handle task_sched_); + explicit rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_); ~rrc(); int32_t init(const rrc_cfg_t& cfg_, @@ -166,6 +166,7 @@ public: private: // args srsran::task_sched_handle task_sched; + stack_interface_rrc* stack = nullptr; phy_interface_rrc_lte* phy = nullptr; mac_interface_rrc* mac = nullptr; rlc_interface_rrc* rlc = nullptr; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 14e231dcb..92f360b56 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -44,7 +44,7 @@ enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : rlc_nr(rlc_nr_logger), gtpu(&task_sched, gtpu_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets), - rrc(&task_sched), + rrc(this, &task_sched), rrc_nr(&task_sched), mac_pcap(), pending_stack_metrics(64) @@ -278,17 +278,40 @@ void enb_stack_lte::run_thread() } } -void enb_stack_lte::write_sdu(uint16_t rnti, - uint32_t lcid /* to be replaced with eps_bearer_id */, - srsran::unique_byte_buffer_t sdu, - int pdcp_sn) +void enb_stack_lte::write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) { - pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + auto bearer = bearers.get_radio_bearer(rnti, eps_bearer_id); + auto task = [this, rnti, eps_bearer_id, bearer, pdcp_sn](srsran::unique_byte_buffer_t& sdu) { + // route SDU to PDCP entity + if (bearer.rat == srsran_rat_t::lte) { + pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else if (bearer.rat == srsran_rat_t::nr) { + pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else { + stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); + } + }; } std::map enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid) { + // TODO: use eps_bearer_id as lookup too return pdcp.get_buffered_pdus(rnti, lcid); } +void enb_stack_lte::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + bearers.add_eps_bearer(rnti, eps_bearer_id, rat, lcid); +} + +void enb_stack_lte::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) +{ + bearers.remove_eps_bearer(rnti, eps_bearer_id); +} + +void enb_stack_lte::reset_eps_bearers(uint16_t rnti) +{ + bearers.reset(rnti); +} + } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index c74506a07..600fb1988 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -32,8 +32,8 @@ using namespace asn1::rrc; namespace srsenb { -rrc::rrc(srsran::task_sched_handle task_sched_) : - logger(srslog::fetch_basic_logger("RRC")), task_sched(task_sched_), rx_pdu_queue(128) +rrc::rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_) : + logger(srslog::fetch_basic_logger("RRC")), stack(stack_), task_sched(task_sched_), rx_pdu_queue(128) {} rrc::~rrc() {} diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 81fad3b40..f02b64a30 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1441,6 +1441,10 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) if (pending_rr_cfg.drb_to_release_list.size() > 0) { for (uint8_t drb_id : pending_rr_cfg.drb_to_release_list) { parent->rlc->del_bearer(rnti, drb_to_lcid((lte_drb)drb_id)); + + // deregister EPS bearer + uint8_t eps_bearer_id = 0; // FIXME: lookup EPS bearer ID for drb_id + parent->stack->remove_eps_bearer(rnti, eps_bearer_id); } } for (const drb_to_add_mod_s& drb : pending_rr_cfg.drb_to_add_mod_list) { @@ -1454,6 +1458,9 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) rlc_cfg.am.max_retx_thresh = parent->cfg.qci_cfg.at(erab.qos_params.qci).enb_dl_max_retx_thres; } parent->rlc->add_bearer(rnti, drb.lc_ch_id, rlc_cfg); + + // register EPS bearer over LTE PDCP + parent->stack->add_eps_bearer(rnti, drb.eps_bearer_id, srsran::srsran_rat_t::lte, drb.lc_ch_id); } } diff --git a/srsenb/test/rrc/erab_setup_test.cc b/srsenb/test/rrc/erab_setup_test.cc index 1c96eac72..b0412f1a9 100644 --- a/srsenb/test/rrc/erab_setup_test.cc +++ b/srsenb/test/rrc/erab_setup_test.cc @@ -33,7 +33,8 @@ int test_erab_setup(srsran::log_sink_spy& spy, bool qci_exists) logger.set_hex_dump_max_size(1024); logger.set_level(srslog::basic_levels::info); - srsenb::rrc rrc{&task_sched}; + test_dummies::enb_stack_dummy stack; + srsenb::rrc rrc{&stack, &task_sched}; mac_dummy mac; rlc_dummy rlc; test_dummies::pdcp_mobility_dummy pdcp; diff --git a/srsenb/test/rrc/rrc_mobility_test.cc b/srsenb/test/rrc/rrc_mobility_test.cc index 15739a1f7..6e596ceb4 100644 --- a/srsenb/test/rrc/rrc_mobility_test.cc +++ b/srsenb/test/rrc/rrc_mobility_test.cc @@ -57,7 +57,7 @@ const char* to_string(test_event event) struct mobility_tester { explicit mobility_tester(const test_event& args_) : - args(args_), logger(srslog::fetch_basic_logger("RRC")), rrc(&task_sched) + args(args_), logger(srslog::fetch_basic_logger("RRC")), rrc(&stack, &task_sched) { logger.set_level(srslog::basic_levels::info); logger.set_hex_dump_max_size(1024); @@ -93,6 +93,7 @@ struct mobility_tester { test_dummies::pdcp_mobility_dummy pdcp; test_dummies::phy_mobility_dummy phy; test_dummies::s1ap_mobility_dummy s1ap; + test_dummies::enb_stack_dummy stack; gtpu_dummy gtpu; void tic() diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index 44d652a96..5f1c2b8fb 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -201,6 +201,13 @@ public: phy_rrc_cfg_list_t last_cfg; }; +class enb_stack_dummy : public stack_interface_rrc +{ + void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) {} + void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) {} + void reset_eps_bearers(uint16_t rnti){}; +}; + } // namespace test_dummies namespace test_helpers { From 4b2f07958137e82acdc6648d342fa5e182973268 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 2 Sep 2021 11:57:09 +0200 Subject: [PATCH 54/56] gtpu: renamed lcid to eps_bearer_id as parte of the refactor of gtpu to use eps_bearer_ids --- lib/include/srsran/common/common_lte.h | 7 +- srsenb/hdr/stack/upper/gtpu.h | 51 +++++----- srsenb/src/stack/upper/gtpu.cc | 123 +++++++++++++------------ srsenb/test/upper/gtpu_test.cc | 16 ++-- 4 files changed, 104 insertions(+), 93 deletions(-) diff --git a/lib/include/srsran/common/common_lte.h b/lib/include/srsran/common/common_lte.h index 0152a692b..5b1ee9cfa 100644 --- a/lib/include/srsran/common/common_lte.h +++ b/lib/include/srsran/common/common_lte.h @@ -49,9 +49,10 @@ inline bool is_lte_cell_nof_prb(uint32_t nof_prb) enum class lte_srb { srb0, srb1, srb2, count }; const uint32_t MAX_LTE_SRB_ID = 2; enum class lte_drb { drb1 = 1, drb2, drb3, drb4, drb5, drb6, drb7, drb8, drb9, drb10, drb11, invalid }; -const uint32_t MAX_LTE_DRB_ID = 11; -const uint32_t MAX_LTE_LCID = 10; // logicalChannelIdentity 3..10 in TS 36.331 v15.3 -const uint32_t INVALID_LCID = 99; // random invalid LCID +const uint32_t MAX_LTE_DRB_ID = 11; +const uint32_t MAX_LTE_LCID = 10; // logicalChannelIdentity 3..10 in TS 36.331 v15.3 +const uint32_t INVALID_LCID = 99; // random invalid LCID +const uint32_t INVALID_EPS_BEARER_ID = 99; // random invalid eps bearer id constexpr bool is_lte_rb(uint32_t lcid) { diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 976a865b2..eff0e747d 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -53,11 +53,11 @@ public: enum class tunnel_state { pdcp_active, buffering, forward_to, forwarded_from, inactive }; struct tunnel { - uint16_t rnti = SRSRAN_INVALID_RNTI; - uint32_t lcid = srsran::INVALID_LCID; - uint32_t teid_in = 0; - uint32_t teid_out = 0; - uint32_t spgw_addr = 0; + uint16_t rnti = SRSRAN_INVALID_RNTI; + uint32_t eps_bearer_id = srsran::INVALID_EPS_BEARER_ID; + uint32_t teid_in = 0; + uint32_t teid_out = 0; + uint32_t spgw_addr = 0; tunnel_state state = tunnel_state::pdcp_active; srsran::unique_timer rx_timer; @@ -76,27 +76,30 @@ public: } }; - struct lcid_tunnel { - uint32_t lcid; + struct bearer_teid_pair { + uint32_t eps_bearer_id; uint32_t teid; - bool operator<(const lcid_tunnel& other) const + bool operator<(const bearer_teid_pair& other) const { - return lcid < other.lcid or (lcid == other.lcid and teid < other.teid); + return eps_bearer_id < other.eps_bearer_id or (eps_bearer_id == other.eps_bearer_id and teid < other.teid); + } + bool operator==(const bearer_teid_pair& other) const + { + return eps_bearer_id == other.eps_bearer_id and teid == other.teid; } - bool operator==(const lcid_tunnel& other) const { return lcid == other.lcid and teid == other.teid; } }; - using ue_lcid_tunnel_list = srsran::bounded_vector; + using ue_bearer_tunnel_list = srsran::bounded_vector; explicit gtpu_tunnel_manager(srsran::task_sched_handle task_sched_, srslog::basic_logger& logger); void init(const gtpu_args_t& gtpu_args, pdcp_interface_gtpu* pdcp_); - bool has_teid(uint32_t teid) const { return tunnels.contains(teid); } - const tunnel* find_tunnel(uint32_t teid); - ue_lcid_tunnel_list* find_rnti_tunnels(uint16_t rnti); - srsran::span find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid); + bool has_teid(uint32_t teid) const { return tunnels.contains(teid); } + const tunnel* find_tunnel(uint32_t teid); + ue_bearer_tunnel_list* find_rnti_tunnels(uint16_t rnti); + srsran::span find_rnti_bearer_tunnels(uint16_t rnti, uint32_t eps_bearer_id); - const tunnel* add_tunnel(uint16_t rnti, uint32_t lcid, uint32_t teidout, uint32_t spgw_addr); + const tunnel* add_tunnel(uint16_t rnti, uint32_t eps_bearer_id, uint32_t teidout, uint32_t spgw_addr); bool update_rnti(uint16_t old_rnti, uint16_t new_rnti); void activate_tunnel(uint32_t teid); @@ -119,8 +122,8 @@ private: pdcp_interface_gtpu* pdcp = nullptr; srslog::basic_logger& logger; - rnti_map_t ue_teidin_db; - tunnel_list_t tunnels; + rnti_map_t ue_teidin_db; + tunnel_list_t tunnels; }; using gtpu_tunnel_state = gtpu_tunnel_manager::tunnel_state; @@ -139,17 +142,17 @@ public: // gtpu_interface_rrc srsran::expected add_bearer(uint16_t rnti, - uint32_t lcid, + uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) override; void set_tunnel_status(uint32_t teidin, bool dl_active) override; - void rem_bearer(uint16_t rnti, uint32_t lcid) override; + void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override; void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override; void rem_user(uint16_t rnti) override; // gtpu_interface_pdcp - void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override; + void write_pdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t pdu) override; // stack interface void handle_gtpu_s1u_rx_packet(srsran::unique_byte_buffer_t pdu, const sockaddr_in& addr); @@ -190,9 +193,9 @@ private: std::string m1u_multiaddr; std::string m1u_if_addr; - bool initiated = false; - int m1u_sd = -1; - int lcid_counter = 0; + bool initiated = false; + int m1u_sd = -1; + int bearer_counter = 0; }; m1u_handler m1u; diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index c6a20dc41..8d8e946a5 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -48,7 +48,7 @@ const gtpu_tunnel_manager::tunnel* gtpu_tunnel_manager::find_tunnel(uint32_t tei return it != tunnels.end() ? &it->second : nullptr; } -gtpu_tunnel_manager::ue_lcid_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels(uint16_t rnti) +gtpu_tunnel_manager::ue_bearer_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels(uint16_t rnti) { if (not ue_teidin_db.contains(rnti)) { return nullptr; @@ -56,26 +56,28 @@ gtpu_tunnel_manager::ue_lcid_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels return &ue_teidin_db[rnti]; } -srsran::span gtpu_tunnel_manager::find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid) +srsran::span +gtpu_tunnel_manager::find_rnti_bearer_tunnels(uint16_t rnti, uint32_t eps_bearer_id) { - if (not is_lte_rb(lcid)) { - logger.warning("Searching for bearer with invalid lcid=%d", lcid); + if (not is_lte_rb(eps_bearer_id)) { + logger.warning("Searching for bearer with invalid eps-BearerID=%d", eps_bearer_id); return {}; } auto* ue_ptr = find_rnti_tunnels(rnti); if (ue_ptr == nullptr) { return {}; } - auto lcid_it_begin = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), lcid_tunnel{lcid, 0}); - auto lcid_it_end = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), lcid_tunnel{lcid + 1, 0}); + auto bearer_it_begin = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), bearer_teid_pair{eps_bearer_id, 0}); + auto bearer_it_end = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), bearer_teid_pair{eps_bearer_id + 1, 0}); - return srsran::span(&(*lcid_it_begin), &(*lcid_it_end)); + return srsran::span(&(*bearer_it_begin), &(*bearer_it_end)); } -const gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, uint32_t teidout, uint32_t spgw_addr) +const gtpu_tunnel* +gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t eps_bearer_id, uint32_t teidout, uint32_t spgw_addr) { - if (not is_lte_rb(lcid)) { - logger.warning("Adding TEID with invalid lcid=%d", lcid); + if (not is_lte_rb(eps_bearer_id)) { + logger.warning("Adding TEID with invalid eps-BearerID=%d", eps_bearer_id); return nullptr; } auto ret_pair = tunnels.insert(tunnel()); @@ -83,15 +85,15 @@ const gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, logger.warning("Unable to create new GTPU TEID In"); return nullptr; } - tunnel* tun = &tunnels[ret_pair.value()]; - tun->teid_in = ret_pair.value(); - tun->rnti = rnti; - tun->lcid = lcid; - tun->teid_out = teidout; - tun->spgw_addr = spgw_addr; + tunnel* tun = &tunnels[ret_pair.value()]; + tun->teid_in = ret_pair.value(); + tun->rnti = rnti; + tun->eps_bearer_id = eps_bearer_id; + tun->teid_out = teidout; + tun->spgw_addr = spgw_addr; if (not ue_teidin_db.contains(rnti)) { - auto ret = ue_teidin_db.insert(rnti, ue_lcid_tunnel_list()); + auto ret = ue_teidin_db.insert(rnti, ue_bearer_tunnel_list()); if (ret.is_error()) { logger.error("Failed to allocate rnti=0x%x", rnti); return nullptr; @@ -104,16 +106,16 @@ const gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, tunnels.erase(tun->teid_in); return nullptr; } - ue_tunnels.push_back(lcid_tunnel{lcid, tun->teid_in}); + ue_tunnels.push_back(bearer_teid_pair{eps_bearer_id, tun->teid_in}); std::sort(ue_tunnels.begin(), ue_tunnels.end()); fmt::memory_buffer str_buffer; srsran::gtpu_ntoa(str_buffer, htonl(spgw_addr)); - logger.info("New tunnel created - " TEID_IN_FMT ", " TEID_OUT_FMT ", rnti=0x%x, lcid=%d, remote addr=%s", + logger.info("New tunnel created - " TEID_IN_FMT ", " TEID_OUT_FMT ", rnti=0x%x, eps-BearerID=%d, remote addr=%s", tun->teid_in, teidout, rnti, - lcid, + eps_bearer_id, srsran::to_c_str(str_buffer)); return tun; @@ -129,22 +131,22 @@ bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti) logger.info("Modifying bearer rnti. Old rnti: 0x%x, new rnti: 0x%x", old_rnti, new_rnti); // create new RNTI and update TEIDs of old rnti to reflect new rnti - if (not ue_teidin_db.insert(new_rnti, ue_lcid_tunnel_list())) { + if (not ue_teidin_db.insert(new_rnti, ue_bearer_tunnel_list())) { logger.error("Failure to create new rnti=0x%x", new_rnti); return false; } std::swap(ue_teidin_db[new_rnti], *old_rnti_ptr); - ue_lcid_tunnel_list& new_rnti_obj = ue_teidin_db[new_rnti]; + ue_bearer_tunnel_list& new_rnti_obj = ue_teidin_db[new_rnti]; srsran::bounded_vector to_remove; - for (lcid_tunnel& bearer : new_rnti_obj) { + for (bearer_teid_pair& bearer : new_rnti_obj) { tunnels[bearer.teid].rnti = new_rnti; // Remove forwarding path if (tunnels[bearer.teid].state == tunnel_state::forward_to) { tunnels[bearer.teid].state = tunnel_state::pdcp_active; tunnels[bearer.teid].fwd_tunnel = nullptr; - logger.info("Taking down forwarding tunnel for rnti=0x%x, lcid=%d. New default " TEID_IN_FMT, + logger.info("Taking down forwarding tunnel for rnti=0x%x, eps-BearerID=%d. New default " TEID_IN_FMT, new_rnti, - bearer.lcid, + bearer.eps_bearer_id, bearer.teid); } else if (tunnels[bearer.teid].state == tunnel_state::forwarded_from) { to_remove.push_back(bearer.teid); @@ -169,12 +171,13 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin) deactivate_tunnel(teidin); // erase keeping the relative order - auto& ue = ue_teidin_db[tun.rnti]; - auto lcid_it = std::lower_bound(ue.begin(), ue.end(), lcid_tunnel{tun.lcid, tun.teid_in}); - srsran_assert(lcid_it->teid == tun.teid_in and lcid_it->lcid == tun.lcid, "TEID in undefined state"); - ue.erase(lcid_it); + auto& ue = ue_teidin_db[tun.rnti]; + auto bearer_it = std::lower_bound(ue.begin(), ue.end(), bearer_teid_pair{tun.eps_bearer_id, tun.teid_in}); + srsran_assert(bearer_it->teid == tun.teid_in and bearer_it->eps_bearer_id == tun.eps_bearer_id, + "TEID in undefined state"); + ue.erase(bearer_it); - logger.info("Removed rnti=0x%x,lcid=%d tunnel with " TEID_IN_FMT, tun.rnti, tun.lcid, teidin); + logger.info("Removed rnti=0x%x,eps-BearerID=%d tunnel with " TEID_IN_FMT, tun.rnti, tun.eps_bearer_id, teidin); tunnels.erase(teidin); return true; } @@ -216,7 +219,8 @@ void gtpu_tunnel_manager::activate_tunnel(uint32_t teid) for (auto& sdu_pair : *tun.buffer) { uint32_t pdcp_sn = sdu_pair.first; - pdcp->write_sdu(tun.rnti, tun.lcid, std::move(sdu_pair.second), pdcp_sn == undefined_pdcp_sn ? -1 : pdcp_sn); + pdcp->write_sdu( + tun.rnti, tun.eps_bearer_id, std::move(sdu_pair.second), pdcp_sn == undefined_pdcp_sn ? -1 : pdcp_sn); } tun.buffer.reset(); tun.state = tunnel_state::pdcp_active; @@ -240,9 +244,9 @@ void gtpu_tunnel_manager::deactivate_tunnel(uint32_t teid) if (tun.state == tunnel_state::forwarded_from) { // Deactivate respective MME->SeNB forwarding tunnel - for (auto lcid_tun : find_rnti_lcid_tunnels(tun.rnti, tun.lcid)) { - if (lcid_tun.teid != tun.teid_in) { - const gtpu_tunnel_manager::tunnel* mmeenb_tun = find_tunnel(lcid_tun.teid); + for (auto bearer_tun : find_rnti_bearer_tunnels(tun.rnti, tun.eps_bearer_id)) { + if (bearer_tun.teid != tun.teid_in) { + const gtpu_tunnel_manager::tunnel* mmeenb_tun = find_tunnel(bearer_tun.teid); if (mmeenb_tun->state == gtpu_tunnel_manager::tunnel_state::forward_to and mmeenb_tun->fwd_tunnel == &tun) { deactivate_tunnel(mmeenb_tun->teid_in); } @@ -334,8 +338,10 @@ void gtpu_tunnel_manager::setup_forwarding(uint32_t rx_teid, uint32_t tx_teid) fmt::format_to(addrbuf, ":0x{:x} > ", rx_tun.teid_out); srsran::gtpu_ntoa(addrbuf, htonl(tx_tun.spgw_addr)); fmt::format_to(addrbuf, ":0x{:x}", tx_tun.teid_out); - logger.info( - "Created forwarding tunnel for rnti=0x%x, lcid=%d, %s", rx_tun.rnti, rx_tun.lcid, srsran::to_c_str(addrbuf)); + logger.info("Created forwarding tunnel for rnti=0x%x, eps-BearerID=%d, %s", + rx_tun.rnti, + rx_tun.eps_bearer_id, + srsran::to_c_str(addrbuf)); } /******************** @@ -423,11 +429,11 @@ void gtpu::stop() } // gtpu_interface_pdcp -void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) +void gtpu::write_pdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t pdu) { - srsran::span teids = tunnels.find_rnti_lcid_tunnels(rnti, lcid); + srsran::span teids = tunnels.find_rnti_bearer_tunnels(rnti, eps_bearer_id); if (teids.empty()) { - logger.warning("The rnti=0x%x,lcid=%d does not have any pdcp_active tunnel", rnti, lcid); + logger.warning("The rnti=0x%x,eps-BearerID=%d does not have any pdcp_active tunnel", rnti, eps_bearer_id); return; } const gtpu_tunnel& tx_tun = *tunnels.find_tunnel(teids[0].teid); @@ -475,10 +481,10 @@ void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buf } srsran::expected -gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) +gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, const bearer_props* props) { // Allocate a TEID for the incoming tunnel - const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, lcid, teid_out, addr); + const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, eps_bearer_id, teid_out, addr); if (new_tun == nullptr) { return default_error_t(); } @@ -519,17 +525,18 @@ void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active) } } -void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) +void gtpu::rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) { - srsran::span lcid_tuns = tunnels.find_rnti_lcid_tunnels(rnti, lcid); - if (lcid_tuns.empty()) { - logger.info("Removing bearer rnti=0x%x,lcid=%d without any active tunnels", rnti, lcid); + srsran::span bearer_tuns = + tunnels.find_rnti_bearer_tunnels(rnti, eps_bearer_id); + if (bearer_tuns.empty()) { + logger.info("Removing bearer rnti=0x%x,eps-BearerID=%d without any active tunnels", rnti, eps_bearer_id); return; } do { - rem_tunnel(lcid_tuns.front().teid); - lcid_tuns = tunnels.find_rnti_lcid_tunnels(rnti, lcid); - } while (not lcid_tuns.empty()); + rem_tunnel(bearer_tuns.front().teid); + bearer_tuns = tunnels.find_rnti_bearer_tunnels(rnti, eps_bearer_id); + } while (not bearer_tuns.empty()); } void gtpu::mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) @@ -558,7 +565,7 @@ void gtpu::rem_tunnel(uint32_t teidin) void gtpu::rem_user(uint16_t rnti) { - const gtpu_tunnel_manager::ue_lcid_tunnel_list* tun_lst = tunnels.find_rnti_tunnels(rnti); + const gtpu_tunnel_manager::ue_bearer_tunnel_list* tun_lst = tunnels.find_rnti_tunnels(rnti); if (tun_lst == nullptr) { logger.info("Removing user - rnti=0x%x not found.", rnti); return; @@ -650,8 +657,8 @@ void gtpu::handle_msg_data_pdu(const gtpu_header_t& header, pdcp_sn = (header.ext_buffer[1] << 8U) + header.ext_buffer[2]; } - uint16_t rnti = rx_tunnel.rnti; - uint16_t lcid = rx_tunnel.lcid; + uint16_t rnti = rx_tunnel.rnti; + uint16_t eps_bearer_id = rx_tunnel.eps_bearer_id; log_message(rx_tunnel, true, srsran::make_span(pdu)); @@ -668,7 +675,7 @@ void gtpu::handle_msg_data_pdu(const gtpu_header_t& header, break; } case gtpu_tunnel_manager::tunnel_state::pdcp_active: { - pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn == undefined_pdcp_sn ? -1 : (int)pdcp_sn); + pdcp->write_sdu(rnti, eps_bearer_id, std::move(pdu), pdcp_sn == undefined_pdcp_sn ? -1 : (int)pdcp_sn); break; } case gtpu_tunnel_manager::tunnel_state::forwarded_from: @@ -696,7 +703,7 @@ int gtpu::create_dl_fwd_tunnel(uint32_t rx_teid_in, uint32_t tx_teid_in) tunnels.setup_forwarding(rx_teid_in, tx_teid_in); // Get all buffered PDCP PDUs, and forward them through tx tunnel - std::map pdus = pdcp->get_buffered_pdus(rx_tun->rnti, rx_tun->lcid); + std::map pdus = pdcp->get_buffered_pdus(rx_tun->rnti, rx_tun->eps_bearer_id); for (auto& pdu_pair : pdus) { uint32_t pdcp_sn = pdu_pair.first; log_message(*tx_tun, false, srsran::make_span(pdu_pair.second), pdcp_sn); @@ -861,11 +868,11 @@ void gtpu::log_message(const gtpu_tunnel& tun, bool is_rx, srsran::span fmt::format_to(strbuf2, "> {}:0x{:0x}, ", srsran::to_c_str(addrbuf), tun.teid_in); } fmt::format_to(strbuf, - "{} S1-U SDU, {}rnti=0x{:0x}, lcid={}, n_bytes={}, IPv{}", + "{} S1-U SDU, {}rnti=0x{:0x}, eps-BearerID={}, n_bytes={}, IPv{}", dir, fmt::to_string(strbuf2), tun.rnti, - tun.lcid, + tun.eps_bearer_id, pdu.size(), (int)ip_pkt->version); if (ip_pkt->version == 4) { @@ -927,8 +934,8 @@ bool gtpu::m1u_handler::init(std::string m1u_multiaddr_, std::string m1u_if_addr } logger.info("M1-U initialized"); - initiated = true; - lcid_counter = 1; + initiated = true; + bearer_counter = 1; // Assign a handler to rx M1U packets auto rx_callback = [this](srsran::unique_byte_buffer_t pdu, const sockaddr_in& from) { @@ -946,7 +953,7 @@ void gtpu::m1u_handler::handle_rx_packet(srsran::unique_byte_buffer_t pdu, const gtpu_header_t header; gtpu_read_header(pdu.get(), &header, logger); - pdcp->write_sdu(SRSRAN_MRNTI, lcid_counter, std::move(pdu)); + pdcp->write_sdu(SRSRAN_MRNTI, bearer_counter, std::move(pdu)); } } // namespace srsenb diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index b6b1d6fba..6d37df47f 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -161,7 +161,7 @@ void test_gtpu_tunnel_manager() gtpu_tunnel_manager tunnels(&task_sched, srslog::fetch_basic_logger("GTPU")); tunnels.init(gtpu_args, nullptr); TESTASSERT(tunnels.find_tunnel(0) == nullptr); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).empty()); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); TESTASSERT(tunnels.find_rnti_tunnels(0x46) == nullptr); // Creation of tunnels for different users and lcids @@ -174,19 +174,19 @@ void test_gtpu_tunnel_manager() tun2 = tunnels.add_tunnel(0x47, drb1_lcid + 1, 7, sgw_addr); TESTASSERT(tun2 != nullptr); TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).size() == 1); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x47, drb1_lcid).size() == 1); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x47, drb1_lcid + 1).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid + 1).size() == 1); // TEST: Creation/Removal of indirect tunnel const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr); TESTASSERT(fwd_tun != nullptr); TESTASSERT(tunnels.find_tunnel(fwd_tun->teid_in) == fwd_tun); tunnels.setup_forwarding(tun->teid_in, fwd_tun->teid_in); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).size() == 2); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); // Removing a tunnel also clears any associated forwarding tunnel TESTASSERT(tunnels.remove_tunnel(tun->teid_in)); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).empty()); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); // TEST: Prioritization of one TEID over another const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_lcid, 7, sgw_addr); @@ -200,9 +200,9 @@ void test_gtpu_tunnel_manager() tunnels.handle_rx_pdcp_sdu(before_tun->teid_in); } // Removing active TEID, will automatically switch TEID paths - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).size() == 2); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); tunnels.remove_tunnel(before_tun->teid_in); - TESTASSERT(tunnels.find_rnti_lcid_tunnels(0x46, drb1_lcid).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active); } From 2ade4628ca1ad77648ca9cec6048d7469fac5ce4 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 2 Sep 2021 14:49:02 +0200 Subject: [PATCH 55/56] stack lte: create an gtpu-pdcp adapter class that correctly converts lcids to eps bearers and vice-versa --- lib/include/srsran/common/bearer_manager.h | 12 ++- .../srsran/interfaces/enb_gtpu_interfaces.h | 17 ++-- lib/src/common/bearer_manager.cc | 48 +++++++---- srsenb/hdr/stack/enb_stack_lte.h | 10 ++- srsenb/src/stack/enb_stack_lte.cc | 40 +++++++--- srsenb/src/stack/rrc/rrc_bearer_cfg.cc | 4 +- srsenb/test/upper/gtpu_test.cc | 80 +++++++++---------- 7 files changed, 132 insertions(+), 79 deletions(-) diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h index 9a585476b..4691c4962 100644 --- a/lib/include/srsran/common/bearer_manager.h +++ b/lib/include/srsran/common/bearer_manager.h @@ -49,6 +49,8 @@ public: struct radio_bearer_t { srsran::srsran_rat_t rat; uint32_t lcid; + uint32_t eps_bearer_id; + bool is_valid() const { return rat != srsran_rat_t::nulltype; } }; /// Single user interface (for UE) @@ -69,6 +71,8 @@ public: // Stack interface to retrieve active RB radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); + radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid); + /// Multi-user interface (see comments above) void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id); @@ -81,10 +85,14 @@ private: srslog::basic_logger& logger; typedef std::map eps_rb_map_t; - std::map users_map; + struct user_bearers { + eps_rb_map_t bearers; + std::map lcid_to_eps_bearer_id; + }; + std::map users_map; const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI - radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; + radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0, 0}; }; } // namespace srsran diff --git a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h index c88edac4d..bc6aebda0 100644 --- a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h +++ b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h @@ -31,7 +31,7 @@ struct gtpu_args_t { class gtpu_interface_pdcp { public: - virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0; + virtual void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu) = 0; }; // GTPU interface for RRC @@ -45,12 +45,15 @@ public: uint32_t flush_before_teidin = 0; }; - virtual srsran::expected - add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0; - virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; - virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0; - virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0; - virtual void rem_user(uint16_t rnti) = 0; + virtual srsran::expected add_bearer(uint16_t rnti, + uint32_t eps_bearer_id, + uint32_t addr, + uint32_t teid_out, + const bearer_props* props = nullptr) = 0; + virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; + virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0; + virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0; + virtual void rem_user(uint16_t rnti) = 0; }; } // namespace srsenb diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index bef2048cb..dd098a7fc 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -32,19 +32,20 @@ void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { srsran::rwlock_write_guard rw_lock(rwlock); - auto user_it = users_map.find(rnti); + auto user_it = users_map.find(rnti); if (user_it == users_map.end()) { // add empty bearer map - users_map.emplace(rnti, eps_rb_map_t{}); - user_it = users_map.find(rnti); + auto p = users_map.emplace(rnti, user_bearers{}); + user_it = p.first; } - auto bearer_it = user_it->second.find(eps_bearer_id); - if (bearer_it != user_it->second.end()) { + auto bearer_it = user_it->second.bearers.find(eps_bearer_id); + if (bearer_it != user_it->second.bearers.end()) { logger.error("EPS bearer ID %d already registered", eps_bearer_id); return; } - user_it->second.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); + user_it->second.bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id}); + user_it->second.lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id); logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); } @@ -63,12 +64,14 @@ void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) return; } - auto bearer_it = user_it->second.find(eps_bearer_id); - if (bearer_it == user_it->second.end()) { + auto bearer_it = user_it->second.bearers.find(eps_bearer_id); + if (bearer_it == user_it->second.bearers.end()) { logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); return; } - user_it->second.erase(bearer_it); + uint32_t lcid = bearer_it->second.lcid; + user_it->second.bearers.erase(bearer_it); + user_it->second.lcid_to_eps_bearer_id.erase(lcid); logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); } @@ -87,7 +90,8 @@ void bearer_manager::reset(uint16_t rnti) return; } - user_it->second.clear(); + user_it->second.lcid_to_eps_bearer_id.clear(); + user_it->second.bearers.clear(); logger.info("Reset EPS bearer manager"); } @@ -106,7 +110,7 @@ bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_ return false; } - return user_it->second.find(eps_bearer_id) != user_it->second.end(); + return user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end(); } // Stack interface @@ -115,6 +119,22 @@ bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bea return get_radio_bearer(default_key, eps_bearer_id); } +bearer_manager::radio_bearer_t bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid) +{ + srsran::rwlock_read_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + return invalid_rb; + } + + auto lcid_it = user_it->second.lcid_to_eps_bearer_id.find(lcid); + if (lcid_it != user_it->second.lcid_to_eps_bearer_id.end()) { + return user_it->second.bearers.at(lcid_it->second); + } + return invalid_rb; +} + bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) { srsran::rwlock_read_guard rw_lock(rwlock); @@ -124,10 +144,10 @@ bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, u return invalid_rb; } - if (user_it->second.find(eps_bearer_id) != user_it->second.end()) { - return user_it->second.at(eps_bearer_id); + if (user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end()) { + return user_it->second.bearers.at(eps_bearer_id); } return invalid_rb; } -} // namespace srsue \ No newline at end of file +} // namespace srsran \ No newline at end of file diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 53edd3ab8..58bc5b3a8 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -36,6 +36,8 @@ namespace srsenb { +class gtpu_pdcp_adapter; + class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, public stack_interface_phy_nr, @@ -178,6 +180,10 @@ private: srsran::task_scheduler task_sched; srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue; + // bearer management + srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers + std::unique_ptr gtpu_adapter; + srsenb::mac mac; srsenb::rlc rlc; srsenb::pdcp pdcp; @@ -191,10 +197,8 @@ private: srsenb::pdcp pdcp_nr; srsenb::rrc_nr rrc_nr; - srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers - // RAT-specific interfaces - phy_interface_stack_lte* phy = nullptr; + phy_interface_stack_lte* phy = nullptr; phy_interface_stack_nr* phy_nr = nullptr; // state diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 92f360b56..c4cf734f6 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -22,6 +22,23 @@ using namespace srsran; namespace srsenb { +class gtpu_pdcp_adapter : public gtpu_interface_pdcp +{ +public: + gtpu_pdcp_adapter(gtpu* gtpu_, srsran::bearer_manager& bearers_) : gtpu_obj(gtpu_), bearers(&bearers_) {} + + /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU + void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) + { + auto bearer = bearers->get_lcid_bearer(rnti, lcid); + gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); + } + +private: + gtpu* gtpu_obj = nullptr; + srsran::bearer_manager* bearers = nullptr; +}; + enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), @@ -145,13 +162,16 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // add sync queue sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); + // setup bearer managers + gtpu_adapter.reset(new gtpu_pdcp_adapter(>pu, bearers)); + // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { stack_logger.error("Couldn't initialize MAC"); return SRSRAN_ERROR; } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); - pdcp.init(&rlc, &rrc, >pu); + pdcp.init(&rlc, &rrc, gtpu_adapter.get()); if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_nr) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; @@ -281,16 +301,14 @@ void enb_stack_lte::run_thread() void enb_stack_lte::write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) { auto bearer = bearers.get_radio_bearer(rnti, eps_bearer_id); - auto task = [this, rnti, eps_bearer_id, bearer, pdcp_sn](srsran::unique_byte_buffer_t& sdu) { - // route SDU to PDCP entity - if (bearer.rat == srsran_rat_t::lte) { - pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else { - stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); - } - }; + // route SDU to PDCP entity + if (bearer.rat == srsran_rat_t::lte) { + pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else if (bearer.rat == srsran_rat_t::nr) { + pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else { + stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); + } } std::map enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid) diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index cdaec977f..0fac1d0c9 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -394,7 +394,7 @@ srsran::expected bearer_cfg_handler::add_gtpu_bearer(uint32_t erab_t::gtpu_tunnel bearer; bearer.teid_out = teid_out; bearer.addr = addr; - srsran::expected teidin = gtpu->add_bearer(rnti, erab.lcid, addr, teid_out, props); + srsran::expected teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, props); if (teidin.is_error()) { logger->error("Adding erab_id=%d to GTPU", erab_id); return srsran::default_error_t(); @@ -411,7 +411,7 @@ void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id) logger->warning("Removing erab_id=%d from GTPU", erab_id); return; } - gtpu->rem_bearer(rnti, it->second.lcid); + gtpu->rem_bearer(rnti, it->second.id); } void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 6d37df47f..4220de0a6 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -29,35 +29,35 @@ static const size_t PDU_HEADER_SIZE = 20; class pdcp_tester : public pdcp_dummy { public: - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override + void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override { - last_sdu = std::move(sdu); - last_pdcp_sn = pdcp_sn; - last_rnti = rnti; - last_lcid = lcid; + last_sdu = std::move(sdu); + last_pdcp_sn = pdcp_sn; + last_rnti = rnti; + last_eps_bearer_id = eps_bearer_id; } - std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override + std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override { return std::move(buffered_pdus); } void send_status_report(uint16_t rnti) override {} - void send_status_report(uint16_t rnti, uint32_t lcid) override {} + void send_status_report(uint16_t rnti, uint32_t eps_bearer_id) override {} void push_buffered_pdu(uint32_t sn, srsran::unique_byte_buffer_t pdu) { buffered_pdus[sn] = std::move(pdu); } void clear() { - last_sdu = nullptr; - last_pdcp_sn = -1; - last_lcid = 0; - last_rnti = SRSRAN_INVALID_RNTI; + last_sdu = nullptr; + last_pdcp_sn = -1; + last_eps_bearer_id = 0; + last_rnti = SRSRAN_INVALID_RNTI; } std::map buffered_pdus; srsran::unique_byte_buffer_t last_sdu; - int last_pdcp_sn = -1; - uint16_t last_rnti = SRSRAN_INVALID_RNTI; - uint32_t last_lcid = 0; + int last_pdcp_sn = -1; + uint16_t last_rnti = SRSRAN_INVALID_RNTI; + uint32_t last_eps_bearer_id = 0; }; struct dummy_socket_manager : public srsran::socket_manager_itf { @@ -153,44 +153,44 @@ void test_gtpu_tunnel_manager() const char* sgw_addr_str = "127.0.0.1"; struct sockaddr_in sgw_sockaddr = {}; srsran::net_utils::set_sockaddr(&sgw_sockaddr, sgw_addr_str, GTPU_PORT); - uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr); - const uint32_t drb1_lcid = 3; + uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr); + const uint32_t drb1_eps_bearer_id = 5; srsran::task_scheduler task_sched; gtpu_args_t gtpu_args = {}; gtpu_tunnel_manager tunnels(&task_sched, srslog::fetch_basic_logger("GTPU")); tunnels.init(gtpu_args, nullptr); TESTASSERT(tunnels.find_tunnel(0) == nullptr); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty()); TESTASSERT(tunnels.find_rnti_tunnels(0x46) == nullptr); - // Creation of tunnels for different users and lcids - const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_lcid, 5, sgw_addr); + // Creation of tunnels for different users and bearers + const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 5, sgw_addr); TESTASSERT(tun != nullptr); TESTASSERT(tunnels.find_tunnel(tun->teid_in) == tun); - const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_lcid, 6, sgw_addr); + const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id, 6, sgw_addr); TESTASSERT(tun2 != nullptr); TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2); - tun2 = tunnels.add_tunnel(0x47, drb1_lcid + 1, 7, sgw_addr); + tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id + 1, 7, sgw_addr); TESTASSERT(tun2 != nullptr); TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid).size() == 1); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid + 1).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id + 1).size() == 1); // TEST: Creation/Removal of indirect tunnel - const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr); + const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr); TESTASSERT(fwd_tun != nullptr); TESTASSERT(tunnels.find_tunnel(fwd_tun->teid_in) == fwd_tun); tunnels.setup_forwarding(tun->teid_in, fwd_tun->teid_in); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2); // Removing a tunnel also clears any associated forwarding tunnel TESTASSERT(tunnels.remove_tunnel(tun->teid_in)); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty()); // TEST: Prioritization of one TEID over another - const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_lcid, 7, sgw_addr); - const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr); + const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 7, sgw_addr); + const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr); TESTASSERT(before_tun != nullptr and after_tun != nullptr); tunnels.set_tunnel_priority(before_tun->teid_in, after_tun->teid_in); for (uint32_t i = 0; i < 1000; ++i) { @@ -200,9 +200,9 @@ void test_gtpu_tunnel_manager() tunnels.handle_rx_pdcp_sdu(before_tun->teid_in); } // Removing active TEID, will automatically switch TEID paths - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2); tunnels.remove_tunnel(before_tun->teid_in); - TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); + TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1); TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active); } @@ -215,7 +215,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST"); logger.info("\n\n**** Test GTPU Direct Tunneling ****\n"); uint16_t rnti = 0x46, rnti2 = 0x50; - uint32_t drb1 = 3; + uint32_t drb1_bearer_id = 5; uint32_t sgw_teidout1 = 1, sgw_teidout2 = 2; const char * sgw_addr_str = "127.0.0.1", *senb_addr_str = "127.0.1.1", *tenb_addr_str = "127.0.1.2"; struct sockaddr_in senb_sockaddr = {}, sgw_sockaddr = {}, tenb_sockaddr = {}; @@ -246,8 +246,8 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) tenb_gtpu.init(gtpu_args, &tenb_pdcp); // create tunnels MME-SeNB and MME-TeNB - uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, sgw_addr, sgw_teidout1).value(); - uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, sgw_addr, sgw_teidout2).value(); + uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1).value(); + uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2).value(); // Buffer PDUs in SeNB PDCP for (size_t sn = 6; sn < 10; ++sn) { @@ -260,11 +260,11 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) gtpu::bearer_props props; props.flush_before_teidin_present = true; props.flush_before_teidin = tenb_teid_in; - uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, senb_addr, 0, &props).value(); + uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, &props).value(); props = {}; props.forward_from_teidin_present = true; props.forward_from_teidin = senb_teid_in; - senb_gtpu.add_bearer(rnti, drb1, tenb_addr, dl_tenb_teid_in, &props); + senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, &props); std::vector data_vec(10); std::iota(data_vec.begin(), data_vec.end(), 0); @@ -280,7 +280,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) pdu_view = srsran::make_span(tenb_pdcp.last_sdu); TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), 7) == 10); TESTASSERT(tenb_pdcp.last_rnti == rnti2); - TESTASSERT(tenb_pdcp.last_lcid == drb1); + TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id); TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)7); // TEST: verify that PDCP buffered SNs have been forwarded through SeNB->TeNB tunnel @@ -289,7 +289,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) pdu_view = srsran::make_span(tenb_pdcp.last_sdu); TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), sn) == 10); TESTASSERT(tenb_pdcp.last_rnti == rnti2); - TESTASSERT(tenb_pdcp.last_lcid == drb1); + TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id); TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)sn); } @@ -302,7 +302,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) pdu_view = srsran::make_span(tenb_pdcp.last_sdu); TESTASSERT(pdu_view.size() == encoded_data.size() and std::equal(pdu_view.begin(), pdu_view.end(), encoded_data.begin())); - TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_lcid == drb1); + TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_eps_bearer_id == drb1_bearer_id); // TEST: verify that MME->TeNB packets are buffered until SeNB->TeNB tunnel is closed tenb_pdcp.clear(); @@ -361,7 +361,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) if (event != tunnel_test_event::ue_removal_no_marker) { // The User is removed in SeNB in case it hasn't and there was no reestablishment if (std::uniform_int_distribution{0, 1}(g) > 0) { - senb_gtpu.rem_bearer(0x46, 3); + senb_gtpu.rem_bearer(0x46, drb1_bearer_id); } senb_gtpu.rem_user(0x46); } From 296949b5f951a93dba8f29344f3751b8b6c40940 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 2 Sep 2021 15:07:36 +0200 Subject: [PATCH 56/56] stack lte: use adapter for pdcp->gtpu write_pdu interface that converts lcid to eps bearer id --- srsenb/hdr/stack/enb_stack_lte.h | 5 --- srsenb/src/stack/enb_stack_lte.cc | 72 +++++++++++++++++++------------ 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 58bc5b3a8..1c94ef9d9 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -42,7 +42,6 @@ class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, public stack_interface_phy_nr, public stack_interface_rrc, - public pdcp_interface_gtpu, public srsran::thread { public: @@ -137,10 +136,6 @@ public: } void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); } - // pdcp_interface_gtpu - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override; - std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override; - // interface for bearer manager void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) override; void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) override; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index c4cf734f6..41c75722d 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -22,21 +22,58 @@ using namespace srsran; namespace srsenb { -class gtpu_pdcp_adapter : public gtpu_interface_pdcp +class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interface_gtpu { public: - gtpu_pdcp_adapter(gtpu* gtpu_, srsran::bearer_manager& bearers_) : gtpu_obj(gtpu_), bearers(&bearers_) {} + gtpu_pdcp_adapter(srslog::basic_logger& logger_, + pdcp* pdcp_lte, + pdcp* pdcp_nr, + gtpu* gtpu_, + srsran::bearer_manager& bearers_) : + logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) + {} /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU - void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) + void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override { auto bearer = bearers->get_lcid_bearer(rnti, lcid); + if (not bearer.is_valid()) { + logger.error("Bearer rnti=0x%x, lcid=%d not found", rnti, lcid); + return; + } gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); } + void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + if (bearer.rat == srsran_rat_t::lte) { + pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else if (bearer.rat == srsran_rat_t::nr) { + pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else { + logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); + } + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + if (bearer.rat == srsran_rat_t::lte) { + return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); + } else if (bearer.rat == srsran_rat_t::nr) { + return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid); + } + logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); + return {}; + } private: - gtpu* gtpu_obj = nullptr; - srsran::bearer_manager* bearers = nullptr; + srslog::basic_logger& logger; + gtpu* gtpu_obj = nullptr; + pdcp* pdcp_obj = nullptr; + pdcp* pdcp_nr_obj = nullptr; + srsran::bearer_manager* bearers = nullptr; }; enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : @@ -163,7 +200,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); // setup bearer managers - gtpu_adapter.reset(new gtpu_pdcp_adapter(>pu, bearers)); + gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, >pu, bearers)); // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { @@ -198,7 +235,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) return SRSRAN_ERROR; } rlc_nr.init(&pdcp_nr, &rrc_nr, &mac_nr, task_sched.get_timer_handler()); - pdcp_nr.init(&rlc_nr, &rrc_nr, >pu); + pdcp_nr.init(&rlc_nr, &rrc_nr, gtpu_adapter.get()); gtpu_args_t gtpu_args; gtpu_args.embms_enable = args.embms.enable; @@ -207,7 +244,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) gtpu_args.mme_addr = args.s1ap.mme_addr; gtpu_args.gtp_bind_addr = args.s1ap.gtp_bind_addr; gtpu_args.indirect_tunnel_timeout_msec = args.gtpu_indirect_tunnel_timeout_msec; - if (gtpu.init(gtpu_args, this) != SRSRAN_SUCCESS) { + if (gtpu.init(gtpu_args, gtpu_adapter.get()) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize GTPU"); return SRSRAN_ERROR; } @@ -298,25 +335,6 @@ void enb_stack_lte::run_thread() } } -void enb_stack_lte::write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) -{ - auto bearer = bearers.get_radio_bearer(rnti, eps_bearer_id); - // route SDU to PDCP entity - if (bearer.rat == srsran_rat_t::lte) { - pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else { - stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); - } -} - -std::map enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid) -{ - // TODO: use eps_bearer_id as lookup too - return pdcp.get_buffered_pdus(rnti, lcid); -} - void enb_stack_lte::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { bearers.add_eps_bearer(rnti, eps_bearer_id, rat, lcid);