diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a458c217eb..8285b915ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -85,7 +85,6 @@ trigger builder: - if: $ON_MR changes: paths: - - .gitlab/ci/src_cache.yml - .gitlab/ci/builders.yml - .gitlab/ci/builders/**/* - docker/scripts/**/* @@ -115,36 +114,76 @@ trigger docker: variables: PY_DIR: docker/metrics_server -helm: +matlab nightly: stage: ci rules: - - if: $CI_DESCRIPTION =~ /Weekly/ + - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ variables: - CI_DESCRIPTION: Synchronization with srsGNB + ON_SCHEDULE: "true" + CI_DESCRIPTION: Nightly + SRSRAN_COMMIT: $CI_COMMIT_SHA NOTIFY_SLACK: "true" + when: delayed + start_in: 3 hours inherit: - variables: false + variables: false trigger: - project: softwareradiosystems/ci/srsgnb_k8s - branch: main - needs: - - job: trigger docker - artifacts: false + project: softwareradiosystems/srsgnb_matlab + branch: master -enterprise: +enterprise nightly: stage: ci rules: - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ variables: + ON_SCHEDULE: "true" CI_DESCRIPTION: Nightly SRSRAN_COMMIT: $CI_COMMIT_SHA NOTIFY_SLACK: "true" + when: delayed + start_in: 3 hours inherit: variables: false trigger: project: softwareradiosystems/srsran_5g_enterprise branch: main +matlab weekly: + stage: ci + rules: + - if: $CI_DESCRIPTION =~ /Weekly/ + variables: + ON_SCHEDULE: "true" + CI_DESCRIPTION: Nightly + SRSRAN_COMMIT: $CI_COMMIT_SHA + NOTIFY_SLACK: "true" + when: delayed + start_in: 20 hours + inherit: + variables: false + trigger: + project: softwareradiosystems/srsgnb_matlab + branch: master + +helm weekly: + stage: ci + rules: + - if: $CI_DESCRIPTION =~ /Weekly/ + variables: + ON_SCHEDULE: "true" + CI_DESCRIPTION: Synchronization with srsGNB + NOTIFY_SLACK: "true" + when: delayed + start_in: 20 hours + inherit: + variables: false + trigger: + project: softwareradiosystems/ci/srsgnb_k8s + branch: main + needs: + - job: trigger docker + artifacts: false + ################################################################################ ## Static ################################################################################ @@ -184,7 +223,7 @@ full-code-format: image: ${CR_REGISTRY_URI}/srsgnb/codechecker:${DOCKER_BUILDER_VERSION} stage: static tags: - - ${AMD64_TAG} + - amd64 needs: - job: builder version optional: false @@ -298,7 +337,7 @@ clangsa: KUBERNETES_MEMORY_REQUEST: 12Gi KUBERNETES_MEMORY_LIMIT: 12Gi tags: - - ${AMD64_TAG} + - amd64 interruptible: false timeout: 2 hours script: @@ -400,10 +439,10 @@ unit coverage: - | export metric_prefix="" if [[ $ON_MR == "true" ]]; then metric_prefix="_pr"; fi - echo "coverage${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${coverage_value}" >> build_time_metrics.txt + echo "coverage${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${coverage_value}" >> build/build_time_metrics.txt - | influx write --host $INFLUXDB_URL --token $INFLUXDB_TOKEN --org $INFLUXDB_ORG \ - --bucket ci --file build_time_metrics.txt + --bucket ci --file build/build_time_metrics.txt coverage: /^\s*Line coverage:\s*\d+.\d+\%/ artifacts: &unit_coverage_artifacts paths: diff --git a/.gitlab/ci-shared/build.yml b/.gitlab/ci-shared/build.yml new file mode 100644 index 0000000000..ed621e4fd1 --- /dev/null +++ b/.gitlab/ci-shared/build.yml @@ -0,0 +1,102 @@ +variables: + INFRASTRUCTURE_TAG: + description: Computer architecture and supported instruction sets + options: + - amd64 + - amd64-avx2 + - amd64-avx2-avx512 + - arm64 + - on-prem-amd64 + - on-prem-arm64 + - aws-spot-amd64 + - aws-spot-arm64 + value: "amd64-avx2" + OS: + description: Operating system + options: + - "ubuntu-24.10" + - "ubuntu-24.04" + - "ubuntu-23.10" + - "ubuntu-22.04" + - "debian-12" + - "debian-11" + - "archlinux-latest" + - "rhel-8" + value: "ubuntu-24.04" + COMPILER: + description: Compiler to use + options: + - "gcc" + - "clang" + value: "gcc" + BUILD_ARGS: + description: It will be passed to cmake + value: "" + MAKE_ARGS: + description: It will be passed to make + value: "" + UHD_VERSION: + description: must be one version supported in the specified OS + value: "" + DPDK_VERSION: + description: must be one version supported in the specified OS + value: "" + +.build_and_unit_template: + image: ${CR_REGISTRY_URI}/srsgnb/builder-${OS}:${DOCKER_BUILDER_VERSION} + variables: + # TEST + TEST_EXECUTION_TIMEOUT: 0 + # CI + KUBERNETES_CPU_REQUEST: 6 + KUBERNETES_CPU_LIMIT: 6 + KUBERNETES_MEMORY_REQUEST: 12Gi + KUBERNETES_MEMORY_LIMIT: 12Gi + tags: + - ${INFRASTRUCTURE_TAG} + before_script: + - | + BUILD_CMD="${BUILD_ARGS}" + if [ -n "${DPDK_VERSION}" ]; then + BUILD_CMD="-d ${DPDK_VERSION} ${BUILD_CMD}" + export LD_LIBRARY_PATH=/opt/dpdk/${DPDK_VERSION}/lib/x86_64-linux-gnu/:/opt/dpdk/${DPDK_VERSION}/lib/aarch64-linux-gnu/:${LD_LIBRARY_PATH} + fi + if [ -n "${UHD_VERSION}" ]; then + BUILD_CMD="-u ${UHD_VERSION} ${BUILD_CMD}" + export LD_LIBRARY_PATH=/opt/uhd/${UHD_VERSION}/lib:${LD_LIBRARY_PATH} + fi + if [ -n "${COMPILER}" ]; then + BUILD_CMD="-c ${COMPILER} ${BUILD_CMD}" + fi + - | + build_srsran() { + target="$1" + shift + set -x + builder.sh -m "-j${KUBERNETES_CPU_REQUEST} ${target}" ${BUILD_CMD} "$@" ${SRSRANDIR} + { set +x; } 2>/dev/null + } + - | + build_plugin() { + target="$1" + shift + set -x + builder.sh -m "-j${KUBERNETES_CPU_REQUEST} ${target}" ${BUILD_CMD} "$@" ${CI_PROJECT_DIR} + { set +x; } 2>/dev/null + } + - | + launch_tests_srsran() { + cd ${SRSRANDIR}/build + echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" + set -x + ctest -j${KUBERNETES_CPU_REQUEST} --schedule-random --output-on-failure --output-junit xunit.xml "$@" + { set +x; } 2>/dev/null + } + - | + launch_tests_plugin() { + cd ${CI_PROJECT_DIR}/build + echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" + set -x + ctest -j${KUBERNETES_CPU_REQUEST} --schedule-random --output-on-failure --output-junit xunit.xml "$@" + { set +x; } 2>/dev/null + } diff --git a/.gitlab/ci-shared/e2e.yml b/.gitlab/ci-shared/e2e.yml new file mode 100644 index 0000000000..2336f3231e --- /dev/null +++ b/.gitlab/ci-shared/e2e.yml @@ -0,0 +1,161 @@ +variables: + TESTBED: + description: Retina Testbed Description + options: + - "zmq" + - "zmq_uesim" + - "zmq_deb" + - "zmq_srsue" + - "zmq_cudu" + - "rf_b200" + - "rf_hp" + - "android_b200" + - "android_x300" + - "viavi" + - "none" + value: "zmq" + MARKERS: + description: Selected pytest marker (label / tag). Tests with that mark will run. + value: "" + KEYWORDS: + description: Select tests by keyword expressions. This will run tests which contain names that match the given string expression (case-insensitive), which can include Python operators that use filenames, class names and function names as variables + value: "" + PYTEST_ARGS: + description: Extra pytest args for the e2e suite to run + value: "" + RETINA_PARAM_ARGS: + description: Extra retina args for the e2e suite to run + value: "" + RETINA_LAUNCHER_ARGS: + description: Extra launcher args + value: "" + E2E_LOG_LEVEL: + description: Log level to set for software under test in the e2e tests + options: + - debug + - info + - warning + - error + value: "info" + +.load retina variables: + stage: ci + script: + - cat ${SRSRANDIR}/.gitlab/ci/e2e/.env + artifacts: + reports: + dotenv: ${SRSRANDIR}/.gitlab/ci/e2e/.env + +.prepare_test: + variables: + KUBECONFIG_VAR_NAME: "RETINA_NAMESPACE_KUBECONFIG" + KUBECONFIG_VAR_NAME_EXTRA: "RETINA_NAMESPACE_KUBECONFIG_EXTRA" + before_script: &setup_kube_config + - | + export FORCE_COLOR=1 + eval K_PATH="\$$KUBECONFIG_VAR_NAME" + export KUBECONFIG=$K_PATH + + eval K_PATH_EXTRA="\$$KUBECONFIG_VAR_NAME_EXTRA" + export KUBECONFIG_EXTRA=$K_PATH_EXTRA + +.e2e-run-template: + resource_group: e2e-${GROUP} + timeout: 3 hours + image: + name: ${RETINA_REGISTRY_PREFIX}/launcher:${RETINA_VERSION} + entrypoint: ["/bin/sh", "-c"] + variables: + ARTIFACT_COMPRESSION_LEVEL: "slowest" + KUBERNETES_CPU_REQUEST: 2 + KUBERNETES_CPU_LIMIT: 2 + KUBERNETES_MEMORY_REQUEST: 2Gi + KUBERNETES_MEMORY_LIMIT: 2Gi + KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "20G" + KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "20G" + KUBECONFIG_VAR_NAME: "RETINA_NAMESPACE_KUBECONFIG" + KUBECONFIG_VAR_NAME_EXTRA: "RETINA_NAMESPACE_KUBECONFIG_EXTRA" + GROUP: zmq + tags: + - "${RETINA_TAG}" + extends: + - .prepare_test + artifacts: + paths: + - ${SRSRANDIR}/tests/e2e/log + when: always + expire_in: 1 week + reports: + junit: ${SRSRANDIR}/tests/e2e/out.xml + script: + - | + # Print E2E parameters + echo "GROUP=${GROUP}" + echo "TESTBED=${TESTBED}" + echo "MARKERS=${MARKERS}" + echo "KEYWORDS=${KEYWORDS}" + echo "PYTEST_ARGS=${PYTEST_ARGS}" + echo "RETINA_PARAM_ARGS=${RETINA_PARAM_ARGS}" + echo "RETINA_LAUNCHER_ARGS=${RETINA_LAUNCHER_ARGS}" + echo "E2E_LOG_LEVEL=${E2E_LOG_LEVEL}" + - cd ${SRSRANDIR} + # Clean LFS files + - | + while read -r line; do + git rm --cached "$line" >/dev/null + done < <(git lfs ls-files | sed -r 's/^.{13}//') + echo "srsGNB sources+build size is" $(du -hs .) + # Remove any existing retina resource for this group + - retina-delete-orchestration-network --user-name ci_${GROUP} + # Add extra config env variables to the .env file + - | + echo "" >> .gitlab/ci/e2e/.env + cat $RETINA_CONFIG_ENV >> .gitlab/ci/e2e/.env + # Modify request to shared the complete folder with the gnb container + - | + yq -i '(.[] | select(.type == "gnb") | .shared_files) += [{"local_path": "../../", "remote_path": env(SRSRANDIR), "is_executable": false}]' ${SRSRANDIR}/.gitlab/ci/e2e/retina_request_${TESTBED}.yml + # Set username for retina + - | + cd tests/e2e + export LOGNAME=ci_${GROUP} + # Run Retina + - | + E2E_CMD="retina-launcher ${RETINA_LAUNCHER_ARGS} --retina-request=${SRSRANDIR}/.gitlab/ci/e2e/retina_request_${TESTBED}.yml ${PYTEST_ARGS} -k '${KEYWORDS}' -m '${MARKERS}' --register-parameter ue.all.log_level=$E2E_LOG_LEVEL gnb.all.log_level=$E2E_LOG_LEVEL ${RETINA_PARAM_ARGS}" + echo "${E2E_CMD}" + eval $E2E_CMD + after_script: + # Remove any existing retina resource for this group + - *setup_kube_config + - retina-delete-orchestration-network --user-name ci_${GROUP} + # Push test metrics + - | + find . -iname "test_metrics.csv" -exec \ + influx write --host $INFLUXDB_URL --token $INFLUXDB_TOKEN --org $INFLUXDB_ORG \ + --bucket ci --file {} \; + # Artifact size + - echo -e "\e[0Ksection_start:`date +%s`:e2e_folder_section[collapsed=true]\r\e[0KLog folder's tree" + - | + print_tree() { + local dir="$1" + local prefix="$2" + + # List directories first + find "$dir" -mindepth 1 -maxdepth 1 -type d | while read -r subdir; do + local size=$(du -sh "$subdir" | awk '{print $1}') + echo "${prefix}├── $(basename "$subdir") [$size]" + print_tree "$subdir" "$prefix│ " + done + + # List files afterwards + find "$dir" -mindepth 1 -maxdepth 1 -type f | while read -r file; do + local size=$(du -sh "$file" | awk '{print $1}') + echo "${prefix}├── $(basename "$file") [$size]" + done + } + print_tree "${SRSRANDIR}/tests/e2e/log/" "" + - echo -e "\e[0Ksection_end:`date +%s`:e2e_folder_section\r\e[0K" + - | + subpath=$(echo "$SRSRANDIR" | sed "s|^$CI_PROJECT_DIR||") + echo "*******************************************************************************************************************************" + echo "Test report ---> https://softwareradiosystems.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts${subpath}/tests/e2e/log/report.html" + echo "*******************************************************************************************************************************" diff --git a/.gitlab/ci-shared/plugin.yml b/.gitlab/ci-shared/plugin.yml new file mode 100644 index 0000000000..039c1d33c5 --- /dev/null +++ b/.gitlab/ci-shared/plugin.yml @@ -0,0 +1,253 @@ +include: + - project: softwareradiosystems/ci/tools + ref: "20" + file: .gitlab/ci-shared/setup/all.yml + - project: softwareradiosystems/ci/tools + ref: "20" + file: .gitlab/ci-shared/features/all.yml + - local: .gitlab/ci-shared/e2e.yml + - local: .gitlab/ci-shared/build.yml + - local: .gitlab/ci/builders/version.yml + +variables: + # CI + SLACK_CHANNEL_OK: "#ci_gnb" + SLACK_CHANNEL_FAIL: "#ci_gnb" + SLACK_CHANNEL_INFO_MSG: "#ci_gnb_verbose" + # srsRAN references + SRSRANDIR: &srsran_dir ${CI_PROJECT_DIR}/srsgnb + SRSRAN_REPO_URL: https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/softwareradiosystems/srsgnb.git + + INFRASTRUCTURE_TAG: + description: Computer architecture and supported instruction sets + options: + - amd64 + - amd64-avx2 + - amd64-avx2-avx512 + - arm64 + value: "amd64-avx2" + OS: + description: Operating system + options: + - "ubuntu-24.10" + - "ubuntu-24.04" + - "ubuntu-23.10" + - "ubuntu-22.04" + - "debian-12" + - "debian-11" + - "archlinux-latest" + - "rhel-8" + value: "ubuntu-24.04" + COMPILER: + description: Compiler to use + options: + - "gcc" + - "clang" + value: "gcc" + BUILD_ARGS: + description: It will be passed to cmake + value: "" + MAKE_ARGS: + description: It will be passed to make + value: "" + UHD_VERSION: + description: must be one version supported in the specified OS + value: "" + DPDK_VERSION: + description: must be one version supported in the specified OS + value: "" + +###### +# CI # +###### +is using latest: + image: ubuntu:24.04 + stage: ci + rules: + - if: $ON_MR + script: + - DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y --no-install-recommends git git-lfs apt-transport-https ca-certificates && git lfs install + - mkdir -p ${SRSRANDIR} + - git clone --depth 1 ${SRSRAN_REPO_URL} ${SRSRANDIR} + - cd ${SRSRANDIR} + - SRSRAN_LATEST_COMMIT=$(git rev-parse HEAD) + - COMMIT_USED_IN_PIPELINE=$(git rev-parse $SRSRAN_COMMIT) + - | + if [[ $COMMIT_USED_IN_PIPELINE != $SRSRAN_LATEST_COMMIT ]]; then + echo "Please update to latest srsRAN commit: $SRSRAN_LATEST_COMMIT" + exit 1 + fi + allow_failure: true + +download srsran: + image: ubuntu:22.04 + stage: ci + rules: + - if: $ON_MR + - if: $ON_WEB + - if: $ON_API + - if: $ON_SCHEDULE + - if: $CI_DESCRIPTION + script: + - DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y --no-install-recommends git git-lfs apt-transport-https ca-certificates && git lfs install + - | + mkdir -p ${SRSRANDIR} + cd ${SRSRANDIR} + - | + git init + git remote add origin ${SRSRAN_REPO_URL} + git fetch --depth=1 origin ${SRSRAN_COMMIT} + git reset --hard FETCH_HEAD + - git config --global --add safe.directory ${SRSRANDIR} + artifacts: + paths: + - $SRSRANDIR + needs: [] + +builder version: + extends: .builder version + rules: + - if: $ON_MR + - if: $ON_WEB + - if: $ON_API + - if: $ON_SCHEDULE + - if: $CI_DESCRIPTION + variables: + SRSRANDIR: *srsran_dir + needs: + - job: download srsran + +load retina variables: + extends: .load retina variables + rules: + - if: $ON_MR + - if: $ON_WEB + - if: $ON_API + - if: $ON_SCHEDULE + - if: $CI_DESCRIPTION + variables: + SRSRANDIR: *srsran_dir + needs: + - job: download srsran + +################## +# Build template # +################## +.cache_set: + cache: + - key: ${OS}-${COMPILER}-${BUILD_ARGS} + paths: + - ${CI_PROJECT_DIR}/ccache + - ${SRSRANDIR}/ccache + policy: push + +.cache_get: + cache: + - key: ${OS}-${COMPILER}-${BUILD_ARGS} + paths: + - ${CI_PROJECT_DIR}/ccache + - ${SRSRANDIR}/ccache + policy: pull-push + +.build_and_unit: + extends: .build_and_unit_template + after_script: + - mv ${CI_PROJECT_DIR}/build/coverage.xml ${CI_PROJECT_DIR}/${CI_JOB_ID}_coverage.xml || true + - | + mv ${SRSRANDIR}/build/apps/gnb/gnb /tmp/gnb + mv ${SRSRANDIR}/build/apps/cu/srscu /tmp/srscu + mv ${SRSRANDIR}/build/apps/du/srsdu /tmp/srsdu + cd ${SRSRANDIR}/build + make clean + mv /tmp/gnb ${SRSRANDIR}/build/apps/gnb/gnb + mv /tmp/srscu ${SRSRANDIR}/build/apps/cu/srscu + mv /tmp/srsdu ${SRSRANDIR}/build/apps/du/srsdu + artifacts: + when: always + reports: + coverage_report: + coverage_format: cobertura + path: ${CI_JOB_ID}_coverage.xml + paths: + - ${CI_JOB_ID}_coverage.xml + - ${SRSRANDIR}/build/ + timeout: 1h + needs: + - job: download srsran + - job: builder version + +######################## +# Codechecker template # +######################## +.codechecker: + extends: .build_and_unit + image: ${CR_REGISTRY_URI}/srsgnb/codechecker:${DOCKER_BUILDER_VERSION} + stage: static + variables: + ANALYZER: "" + ANALYZER_ARGS: "" + ARTIFACT_EXTRA_PATH: "" + CHECK_PER_FILE_TIMEOUT: 600 + COMPILER: clang + before_script: + - | + export CC=/usr/bin/clang + export CXX=/usr/bin/clang++ + - | + cd ${SRSRANDIR} + mkdir -p build + cd build || exit + - cmake -DENABLE_EXPORT=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTS=False .. + - make -j${KUBERNETES_CPU_LIMIT} srsran_exported_libs + - | + echo " + -/usr/lib + -*tests/unittests + -*tests/integrationtests + -*tests/benchmarks + -*benchmarks + -*apps/examples + -*external" >/tmp/codechecker_skip + - | + cd ${CI_PROJECT_DIR} + mkdir -p build + cd build || exit + - cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTS=False -DSRSRAN_PATH=${SRSRANDIR} .. + - | + monitor_child_process() { + while true; do + ps -eo comm,pid,etimes | grep ${ANALYZER} | while read comm pid etimes; do + if [ $etimes -gt $CHECK_PER_FILE_TIMEOUT ]; then + echo "Killing child analysis process" + kill $pid + fi + done + sleep 30 + done + } + export -f monitor_child_process + script: + - nohup bash -c monitor_child_process & + - static-analyzer.sh -i /tmp/codechecker_skip --jobs ${KUBERNETES_CPU_REQUEST} --analyzers ${ANALYZER} ${ANALYZER_ARGS} $CI_PROJECT_DIR + after_script: + - mv codechecker_html codechecker-${ANALYZER}-html + artifacts: + reports: + codequality: code-quality-report.json + paths: + - codechecker-${ANALYZER}-html${ARTIFACT_EXTRA_PATH} + when: always + expire_in: 1 day + cache: [] + +################ +# E2E template # +################ +.e2e-run: + extends: .e2e-run-template + stage: e2e + variables: + SRSRANDIR: *srsran_dir + needs: + - job: download srsran + - job: load retina variables diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 551fac19a0..b324890280 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -10,44 +10,9 @@ include: - project: softwareradiosystems/ci/srsran_project_packaging ref: "7" file: .gitlab/ci-shared/package.yml - - local: .gitlab/ci/src_cache.yml + - local: .gitlab/ci-shared/build.yml variables: - AMD64_TAG: amd64 - AMD64_AVX2_TAG: amd64-avx2 - AMD64_AVX512_TAG: amd64-avx2-avx512 - ARM64_TAG: arm64 - - INFRASTRUCTURE_TAG: - description: Computer architecture and supported instruction sets - options: - - amd64 - - amd64-avx2 - - amd64-avx2-avx512 - - arm64 - - on-prem-amd64 - - on-prem-arm64 - - aws-spot-amd64 - - aws-spot-arm64 - value: "amd64-avx2" - OS: - description: Operating system - options: - - "ubuntu-24.10" - - "ubuntu-24.04" - - "ubuntu-23.10" - - "ubuntu-22.04" - - "debian-12" - - "debian-11" - - "archlinux-latest" - - "rhel-8" - value: "ubuntu-24.04" - COMPILER: - description: Compiler to use - options: - - "gcc" - - "clang" - value: "gcc" TEST_MODE: description: What tests to run. None won't run any test at all. options: @@ -57,18 +22,7 @@ variables: - "valgrind" - "none" value: "default" - BUILD_ARGS: - description: It will be passed to cmake - value: "" - MAKE_ARGS: - description: It will be passed to make - value: "" - UHD_VERSION: - description: must be one version supported in the specified OS - value: "" - DPDK_VERSION: - description: must be one version supported in the specified OS - value: "" + SRSRANDIR: ${CI_PROJECT_DIR} ################ # Build caches # @@ -91,14 +45,9 @@ variables: # Base job .build_and_unit: - image: ${CR_REGISTRY_URI}/srsgnb/builder-${OS}:${DOCKER_BUILDER_VERSION} - tags: ["${AMD64_TAG}"] + extends: .build_and_unit_template stage: build and unit tests variables: - # Setup - UHD_VERSION: "" # Default for OS - DPDK_VERSION: "" # None - # Build BUILD_TYPE: "" # Empty for cmake default ASSERT_LEVEL: "" # Empty for cmake default ENABLE_EXPORT: "" # Empty for cmake default @@ -113,26 +62,71 @@ variables: FORCE_DEBUG_INFO: "" # Empty for cmake default MARCH: "" MTUNE: "" - # TEST - TEST_EXECUTION_TIMEOUT: 0 - # CI - KUBERNETES_CPU_REQUEST: 6 - KUBERNETES_CPU_LIMIT: 6 - KUBERNETES_MEMORY_REQUEST: 12Gi - KUBERNETES_MEMORY_LIMIT: 12Gi - MAKE_ARGS: "-j${KUBERNETES_CPU_REQUEST}" - GIT_STRATEGY: none needs: - - !reference [.fetch_src_cache, needs] - job: builder version optional: false artifacts: true - job: trigger builder optional: true artifacts: false - before_script: - - !reference [.fetch_src_cache, script] - - | + script: + - &srs_functions | + CMAKE_FLAGS_CMD="" + if [ -n "${BUILD_TYPE}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}" + fi + if [ -n "${ASSERT_LEVEL}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DASSERT_LEVEL=${ASSERT_LEVEL}" + fi + if [ -n "${ENABLE_EXPORT}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_EXPORT=${ENABLE_EXPORT}" + fi + if [ -n "${ENABLE_FFTW}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_FFTW=${ENABLE_FFTW}" + fi + if [ -n "${ENABLE_UHD}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_UHD=${ENABLE_UHD}" + fi + if [ -n "${ENABLE_DPDK}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_DPDK=${ENABLE_DPDK}" + fi + if [ -n "${ENABLE_ZEROMQ}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_ZEROMQ=${ENABLE_ZEROMQ}" + fi + if [ -n "${ENABLE_ASAN}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_ASAN=${ENABLE_ASAN}" + fi + if [ -n "${ENABLE_TSAN}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_TSAN=${ENABLE_TSAN}" + fi + if [ -n "${ENABLE_GCOV}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_GCOV=${ENABLE_GCOV}" + fi + if [ -n "${MARCH}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DMARCH=${MARCH}" + fi + if [ -n "${MTUNE}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DTUNE=${MTUNE}" + fi + if [ -n "${ENABLE_WERROR}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DENABLE_WERROR=${ENABLE_WERROR}" + fi + if [ -n "${FORCE_DEBUG_INFO}" ]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DFORCE_DEBUG_INFO=${FORCE_DEBUG_INFO}" + fi + if [[ $TEST_MODE = "none" ]]; then + CMAKE_FLAGS_CMD="${CMAKE_FLAGS_CMD} -DBUILD_TESTS=False" + fi + + echo "INFRASTRUCTURE_TAG=${INFRASTRUCTURE_TAG}" + echo "OS=${OS}" + echo "COMPILER=${COMPILER}" + echo "TEST_MODE=${TEST_MODE}" + echo "BUILD_ARGS=${CMAKE_FLAGS_CMD} ${BUILD_ARGS}" + echo "MAKE_ARGS=${MAKE_ARGS}" + echo "UHD_VERSION=${UHD_VERSION}" + echo "DPDK_VERSION=${DPDK_VERSION}" + build_srsgnb() { start_time=$(date +%s) if [ -e "/usr/local/bin/ram_reporter.py" ]; then @@ -140,88 +134,7 @@ variables: ram_reporter_pid=$! fi - BUILD_CMD="" - if [ -n "${BUILD_TYPE}" ]; then - BUILD_CMD="${BUILD_CMD} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}" - fi - if [ -n "${ASSERT_LEVEL}" ]; then - BUILD_CMD="${BUILD_CMD} -DASSERT_LEVEL=${ASSERT_LEVEL}" - fi - if [ -n "${ENABLE_EXPORT}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_EXPORT=${ENABLE_EXPORT}" - fi - if [ -n "${ENABLE_FFTW}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_FFTW=${ENABLE_FFTW}" - fi - if [ -n "${ENABLE_UHD}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_UHD=${ENABLE_UHD}" - fi - if [ -n "${ENABLE_DPDK}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_DPDK=${ENABLE_DPDK}" - fi - if [ -n "${ENABLE_ZEROMQ}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_ZEROMQ=${ENABLE_ZEROMQ}" - fi - if [ -n "${ENABLE_ASAN}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_ASAN=${ENABLE_ASAN}" - fi - if [ -n "${ENABLE_TSAN}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_TSAN=${ENABLE_TSAN}" - fi - if [ -n "${ENABLE_GCOV}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_GCOV=${ENABLE_GCOV}" - fi - if [ -n "${MARCH}" ]; then - BUILD_CMD="${BUILD_CMD} -DMARCH=${MARCH}" - fi - if [ -n "${MTUNE}" ]; then - BUILD_CMD="${BUILD_CMD} -DTUNE=${MTUNE}" - fi - if [ -n "${ENABLE_WERROR}" ]; then - BUILD_CMD="${BUILD_CMD} -DENABLE_WERROR=${ENABLE_WERROR}" - fi - if [ -n "${FORCE_DEBUG_INFO}" ]; then - BUILD_CMD="${BUILD_CMD} -DFORCE_DEBUG_INFO=${FORCE_DEBUG_INFO}" - fi - if [[ $TEST_MODE = "none" ]]; then - BUILD_CMD="${BUILD_CMD} -DBUILD_TESTS=False" - fi - if [ -n "${BUILD_ARGS}" ]; then - BUILD_CMD="${BUILD_CMD} ${BUILD_ARGS}" - fi - - echo "INFRASTRUCTURE_TAG=${INFRASTRUCTURE_TAG}" - echo "OS=${OS}" - echo "COMPILER=${COMPILER}" - echo "TEST_MODE=${TEST_MODE}" - echo "BUILD_ARGS=${BUILD_CMD}" - echo "MAKE_ARGS=${MAKE_ARGS}" - echo "UHD_VERSION=${UHD_VERSION}" - echo "DPDK_VERSION=${DPDK_VERSION}" - - if [ -n "${DPDK_VERSION}" ]; then - BUILD_CMD="-d ${DPDK_VERSION} ${BUILD_CMD}" - export LD_LIBRARY_PATH=/opt/dpdk/${DPDK_VERSION}/lib/x86_64-linux-gnu/:/opt/dpdk/${DPDK_VERSION}/lib/aarch64-linux-gnu/:${LD_LIBRARY_PATH} - fi - if [ -n "${UHD_VERSION}" ]; then - BUILD_CMD="-u ${UHD_VERSION} ${BUILD_CMD}" - export LD_LIBRARY_PATH=/opt/uhd/${UHD_VERSION}/lib:${LD_LIBRARY_PATH} - fi - if [ -n "${CLEAN_BUILD}" ]; then - BUILD_CMD="-r ${CLEAN_BUILD} ${BUILD_CMD}" - fi - if [ -n "${MAKE_ARGS}" ]; then - BUILD_CMD="-m ${MAKE_ARGS} ${BUILD_CMD}" - fi - if [ -n "${COMPILER}" ]; then - BUILD_CMD="-c ${COMPILER} ${BUILD_CMD}" - fi - BUILD_CMD="builder.sh ${BUILD_CMD} ." - - echo "${BUILD_CMD}" - echo "=============================================================================================" - $BUILD_CMD - + build_srsran "" ${CMAKE_FLAGS_CMD} if [[ -n "$OUTPUT_FINGERPRINT" ]]; then echo "Storing fingerprints of all executables to $OUTPUT_FINGERPRINT" cd build @@ -240,11 +153,11 @@ variables: ram_usage=$(cat ${CI_PROJECT_DIR}/ram_usage.txt) echo "RAM usage is: $ram_usage GB" kill $ram_reporter_pid - echo "ram_usage${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${ram_usage}" >> build_time_metrics.txt + echo "ram_usage${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${ram_usage}" >> ${CI_PROJECT_DIR}/build/build_time_metrics.txt fi - echo "build_time${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${execution_time}" >> build_time_metrics.txt + echo "build_time${metric_prefix},pipeline=${CI_PIPELINE_ID},os=${OS} value=${execution_time}" >> ${CI_PROJECT_DIR}/build/build_time_metrics.txt } - - | + launch_tests() { cd ${CI_PROJECT_DIR}/build case $TEST_MODE in @@ -277,12 +190,11 @@ variables: fi echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" CTEST_CMD="ctest -j${KUBERNETES_CPU_REQUEST} ${CTEST_SUBSET_CMD} $ctest_extra --schedule-random --output-on-failure --output-junit xunit.xml" - echo "${CTEST_CMD}" - echo "=============================================================================================" + echo "+ ${CTEST_CMD}" status_file=$(mktemp) timeout ${TEST_EXECUTION_TIMEOUT} \ - bash -c "${CTEST_CMD} && echo 0 > ${status_file} || echo 1 > ${status_file}" \ + bash -c "${CTEST_CMD}; echo \$? > ${status_file}" \ && ret=$(cat ${status_file}) || ret=124 if [[ $TEST_MODE = "coverage" ]]; then @@ -319,12 +231,9 @@ variables: exit $ret } - script: - build_srsgnb - launch_tests timeout: 6h - cache: - - !reference [.fetch_src_cache, cache] .build_artifacts: after_script: &build_after_script @@ -362,7 +271,7 @@ variables: TEST_MODE: coverage ENABLE_GCOV: "True" MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke relwithdeb: extends: .build_and_unit @@ -373,7 +282,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke tsan: extends: .build_and_unit @@ -385,7 +294,7 @@ variables: ENABLE_TSAN: "True" TEST_MODE: tsan MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke rhel: extends: .build_and_unit @@ -396,7 +305,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke archlinux: extends: .build_and_unit @@ -408,7 +317,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke dpdk: extends: .build_and_unit @@ -422,7 +331,7 @@ variables: ASSERT_LEVEL: PARANOID DPDK_VERSION: "23.11.1_avx2" MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke valgrind: extends: .build_and_unit @@ -433,7 +342,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: valgrind MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] .smoke avx512: extends: .build_and_unit @@ -444,7 +353,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: x86-64-v4 - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] .smoke arm: extends: .build_and_unit @@ -455,7 +364,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: armv8-a - tags: ["${ARM64_TAG}"] + tags: ["arm64"] .smoke arm neon: extends: .build_and_unit @@ -466,7 +375,7 @@ variables: ASSERT_LEVEL: PARANOID TEST_MODE: default MARCH: armv8.2-a+crypto+fp16+dotprod - tags: ["${ARM64_TAG}"] + tags: ["arm64"] # Combinations to use in schedules matrix @@ -493,7 +402,6 @@ smoke relwithdeb cached: artifacts: <<: *build_artifacts cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke tsan cached: @@ -508,7 +416,6 @@ smoke tsan cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke rhel cached: @@ -523,7 +430,6 @@ smoke rhel cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke archlinux cached: @@ -538,7 +444,6 @@ smoke archlinux cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke dpdk cached: @@ -553,7 +458,6 @@ smoke dpdk cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get .infra_path_changes: @@ -579,7 +483,6 @@ smoke avx512 cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke arm cached: @@ -598,7 +501,6 @@ smoke arm cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke arm neon cached: @@ -617,7 +519,6 @@ smoke arm neon cached: when: manual allow_failure: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get smoke relwithdeb clean: @@ -680,6 +581,7 @@ intermediate commits cached: - if: $ON_MR timeout: 2 hour script: + - *srs_functions - git config advice.detachedHead false - git fetch origin --depth=20 $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME - | @@ -697,7 +599,6 @@ intermediate commits cached: artifacts: <<: *build_artifacts cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get valgrind changed tests: @@ -717,6 +618,7 @@ valgrind changed tests: FINGERPRINT: "fingerprints.csv" TEST_EXECUTION_TIMEOUT: 20m script: + - *srs_functions - git config advice.detachedHead false - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME --depth 40 - | @@ -737,15 +639,12 @@ valgrind changed tests: - echo "This test execution has a timeout of ${TEST_EXECUTION_TIMEOUT}. If the execution excess that timer, the job will be marked as allowed_to_fail. This will avoid the job to have a huge duration in a MR pipeline." - launch_tests cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get intermediate commits clean: extends: intermediate commits cached rules: - if: $CI_MERGE_REQUEST_LABELS =~ /no-cache/ - cache: - - !reference [.fetch_src_cache, cache] ################# # Build Nightly # @@ -774,7 +673,6 @@ smoke release update cache: after_script: - *build_after_script cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set artifacts: <<: *build_artifacts @@ -789,7 +687,6 @@ smoke relwithdeb update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke tsan update cache: @@ -801,7 +698,6 @@ smoke tsan update cache: interruptible: false retry: 2 cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke rhel update cache: @@ -813,7 +709,6 @@ smoke rhel update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke archlinux update cache: @@ -825,7 +720,6 @@ smoke archlinux update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke dpdk update cache: @@ -837,7 +731,6 @@ smoke dpdk update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke valgrind update cache: @@ -849,7 +742,6 @@ smoke valgrind update cache: interruptible: false retry: 2 cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke avx512 update cache: @@ -861,7 +753,6 @@ smoke avx512 update cache: interruptible: false retry: 2 cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke arm update cache: @@ -873,7 +764,6 @@ smoke arm update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke arm neon update cache: @@ -885,7 +775,6 @@ smoke arm neon update cache: retry: 2 interruptible: false cache: - - !reference [.fetch_src_cache, cache] - *cache_build_set smoke asan: @@ -904,7 +793,7 @@ smoke asan: ENABLE_ASAN: "True" TEST_MODE: asan MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] # Packaging @@ -925,7 +814,7 @@ package: DEB_BUILD_OPTIONS: parallel=${KUBERNETES_CPU_LIMIT} MAKEFLAGS: -j${KUBERNETES_CPU_LIMIT} extraopts: -DMARCH=x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS_VERSION: "22.04" @@ -942,7 +831,7 @@ install-package: variables: PROJECT_NAME: srsran-project RELEASE_VERSION: "99.9" - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] script: - gnb --version parallel: @@ -973,7 +862,7 @@ export on amd64: COMPILER: gcc TEST_MODE: none ENABLE_EXPORT: "True" - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: [ubuntu-24.10, ubuntu-24.04, ubuntu-23.10, ubuntu-22.04] @@ -982,7 +871,7 @@ export on amd64: export on amd64 avx512: extends: export on amd64 - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: [ubuntu-24.10, ubuntu-24.04, ubuntu-23.10, ubuntu-22.04] @@ -997,7 +886,7 @@ ubuntu-24.10 amd64 avx2: when: delayed start_in: 210 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.10 @@ -1011,7 +900,7 @@ ubuntu-24.04 amd64 avx2: when: delayed start_in: 120 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.04 @@ -1025,7 +914,7 @@ ubuntu-24.04 amd64 avx512: when: delayed start_in: 120 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-24.04 @@ -1039,7 +928,7 @@ ubuntu-23.10 amd64 avx2: when: delayed start_in: 150 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-23.10 @@ -1053,7 +942,7 @@ ubuntu-23.10 amd64 avx512: when: delayed start_in: 150 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-23.10 @@ -1067,7 +956,7 @@ ubuntu-22.04 amd64 avx2: when: delayed start_in: 180 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-22.04 @@ -1081,7 +970,7 @@ rhel-8 amd64 avx2: when: delayed start_in: 240 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: rhel-8 @@ -1097,7 +986,7 @@ ubuntu-24.04 arm neon: when: delayed start_in: 60 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-24.04 @@ -1111,7 +1000,7 @@ ubuntu-23.10 arm neon: when: delayed start_in: 90 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-23.10 @@ -1133,7 +1022,7 @@ ubuntu dpdk: ENABLE_DPDK: "True" ASSERT_LEVEL: PARANOID MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.10 @@ -1157,7 +1046,7 @@ archlinux amd64 native: rules: - if: $CI_DESCRIPTION =~ /Alternative OSs/ interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: archlinux-latest @@ -1171,7 +1060,7 @@ archlinux amd64 avx2: when: delayed start_in: 30 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: archlinux-latest @@ -1184,7 +1073,7 @@ archlinux amd64 avx512: rules: - if: $CI_DESCRIPTION =~ /Alternative OSs/ interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: archlinux-latest @@ -1199,7 +1088,7 @@ debian 12 amd64 native: when: delayed start_in: 60 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: debian-12 @@ -1213,7 +1102,7 @@ debian 12 amd64 avx2: when: delayed start_in: 90 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: debian-12 @@ -1228,7 +1117,7 @@ debian 12 amd64 avx512: when: delayed start_in: 30 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: debian-12 @@ -1275,7 +1164,7 @@ debian 12 amd64 avx512: sanitizers amd64 native: extends: .weekly sanitizers - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: # ubuntu-22.04 disabled due to https://github.com/google/sanitizers/issues/1259#issuecomment-642312392 @@ -1300,7 +1189,7 @@ sanitizers amd64 avx2: extends: .weekly sanitizers variables: MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: # ubuntu-22.04 disabled due to https://github.com/google/sanitizers/issues/1259#issuecomment-642312392 @@ -1328,7 +1217,7 @@ sanitizers amd64 avx512: extends: .weekly sanitizers variables: MARCH: x86-64-v4 - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: # ubuntu-22.04 disabled due to https://github.com/google/sanitizers/issues/1259#issuecomment-642312392 @@ -1351,13 +1240,13 @@ sanitizers amd64 avx512: sanitizers arm native: extends: .weekly sanitizers - tags: ["${ARM64_TAG}"] + tags: ["arm64"] sanitizers arm neon: extends: .weekly sanitizers variables: MARCH: armv8.2-a+crypto+fp16+dotprod - tags: ["${ARM64_TAG}"] + tags: ["arm64"] # UHD Alternatives @@ -1370,7 +1259,7 @@ build uhd alt: TEST_MODE: none ASSERT_LEVEL: PARANOID MARCH: x86-64-v3 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.10 @@ -1395,7 +1284,7 @@ ubuntu-24.10 amd64 native: when: delayed start_in: 90 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: ubuntu-24.10 @@ -1408,7 +1297,7 @@ ubuntu-24.10 amd64 avx512: when: delayed start_in: 90 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-24.10 @@ -1422,7 +1311,7 @@ ubuntu-24.10 arm native: when: delayed start_in: 90 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-24.10 @@ -1435,7 +1324,7 @@ ubuntu-24.10 arm neon: when: delayed start_in: 90 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-24.10 @@ -1449,7 +1338,7 @@ ubuntu-24.04 amd64 native: when: delayed start_in: 30 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: ubuntu-24.04 @@ -1462,7 +1351,7 @@ ubuntu-24.04 arm native: when: delayed start_in: 30 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-24.04 @@ -1475,7 +1364,7 @@ ubuntu-23.10 amd64 native: when: delayed start_in: 30 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: ubuntu-23.10 @@ -1488,7 +1377,7 @@ ubuntu-23.10 arm native: when: delayed start_in: 30 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-23.10 @@ -1501,7 +1390,7 @@ ubuntu-22.04 amd64 native: when: delayed start_in: 60 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: ubuntu-22.04 @@ -1514,7 +1403,7 @@ ubuntu-22.04 amd64 avx512: when: delayed start_in: 60 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-22.04 @@ -1528,7 +1417,7 @@ ubuntu-22.04 arm native: when: delayed start_in: 60 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-22.04 @@ -1541,7 +1430,7 @@ ubuntu-22.04 arm neon: when: delayed start_in: 60 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: ubuntu-22.04 @@ -1555,7 +1444,7 @@ rhel-8 amd64 native: when: delayed start_in: 120 minutes interruptible: false - tags: ["${AMD64_TAG}"] + tags: ["amd64"] parallel: matrix: - OS: rhel-8 @@ -1568,7 +1457,7 @@ rhel-8 amd64 avx512: when: delayed start_in: 120 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: rhel-8 @@ -1582,7 +1471,7 @@ rhel-8 arm native: when: delayed start_in: 120 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: rhel-8 @@ -1595,7 +1484,7 @@ rhel-8 arm neon: when: delayed start_in: 120 minutes interruptible: false - tags: ["${ARM64_TAG}"] + tags: ["arm64"] parallel: matrix: - OS: rhel-8 @@ -1618,7 +1507,7 @@ ubuntu-22.04 amd64 avx2 dpdk: when: delayed start_in: 240 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-22.04 @@ -1633,7 +1522,7 @@ ubuntu-22.04 amd64 avx512 dpdk: when: delayed start_in: 270 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-22.04 @@ -1648,7 +1537,7 @@ ubuntu-23.10 amd64 avx2 dpdk: when: delayed start_in: 300 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-23.10 @@ -1663,7 +1552,7 @@ ubuntu-23.10 amd64 avx512 dpdk: when: delayed start_in: 330 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-23.10 @@ -1678,7 +1567,7 @@ ubuntu-24.04 amd64 avx2 dpdk: when: delayed start_in: 360 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.04 @@ -1693,7 +1582,7 @@ ubuntu-24.04 amd64 avx512 dpdk: when: delayed start_in: 390 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-24.04 @@ -1708,7 +1597,7 @@ ubuntu-24.10 amd64 avx2 dpdk: when: delayed start_in: 420 minutes interruptible: false - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] parallel: matrix: - OS: ubuntu-24.10 @@ -1723,7 +1612,7 @@ ubuntu-24.10 amd64 avx512 dpdk: when: delayed start_in: 450 minutes interruptible: false - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] parallel: matrix: - OS: ubuntu-24.10 @@ -1737,7 +1626,7 @@ ubuntu-24.10 amd64 avx512 dpdk: check-affinity-manager-nocpu: image: ${CR_REGISTRY_URI}/srsgnb/builder-ubuntu-24.04:${DOCKER_BUILDER_VERSION} - tags: ["${AMD64_TAG}"] + tags: ["amd64"] stage: build and unit tests needs: - job: "smoke release update cache" @@ -1799,7 +1688,7 @@ basic package: variables: <<: *package_variables OS_VERSION: "24.04" - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] needs: [] basic tsan: @@ -1826,7 +1715,7 @@ basic asan: TEST_MODE: none MARCH: x86-64-v3 BUILD_ARGS: -DEXIT_TIMEOUT=60 - tags: ["${AMD64_AVX2_TAG}"] + tags: ["amd64-avx2"] after_script: - *build_after_script artifacts: @@ -1866,7 +1755,7 @@ basic avx512 dpdk: MARCH: x86-64-v4 FORCE_DEBUG_INFO: "True" ASSERT_LEVEL: AUTO - tags: ["${AMD64_AVX512_TAG}"] + tags: ["amd64-avx2-avx512"] after_script: - *build_after_script artifacts: @@ -1876,7 +1765,7 @@ basic avx512 dpdk: basic avx512 dpdk withassert: extends: basic avx512 dpdk rules: - - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ + - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ variables: ASSERT_LEVEL: PARANOID @@ -1898,5 +1787,4 @@ custom build: <<: *build_artifacts expire_in: 4 hours cache: - - !reference [.fetch_src_cache, cache] - *cache_build_get diff --git a/.gitlab/ci/builders.yml b/.gitlab/ci/builders.yml index 25695fcd1d..cc1a366cf0 100644 --- a/.gitlab/ci/builders.yml +++ b/.gitlab/ci/builders.yml @@ -17,7 +17,6 @@ include: ref: "20" file: .gitlab/ci-shared/tools/python.yml - local: .gitlab/ci/builders/version.yml - - local: .gitlab/ci/src_cache.yml ################################################################################ # Stages @@ -288,8 +287,6 @@ ubuntu-dpdk-builder arm64: rules: - if: $ON_MR before_script: - - !reference [.fetch_src_cache, before_script] - - !reference [.fetch_src_cache, script] - | export NAME=builder-$OS_NAME-$OS_VERSION export VERSION=${DOCKER_BUILDER_VERSION}-${PLATFORM} @@ -304,8 +301,6 @@ ubuntu-dpdk-builder arm64: ls -lah $CONTEXT/uhd $CONTEXT/dpdk needs: - builder version - cache: - - !reference [.fetch_src_cache, cache] .alternative-tag: extends: .docker copy @@ -348,8 +343,6 @@ image-build-publish [codechecker]: rules: - if: $ON_MR before_script: - - !reference [.fetch_src_cache, before_script] - - !reference [.fetch_src_cache, script] - | export NAME=codechecker export VERSION=$DOCKER_BUILDER_VERSION @@ -360,8 +353,6 @@ image-build-publish [codechecker]: cp -r ${CI_PROJECT_DIR}/docker/scripts/. ${CI_PROJECT_DIR}/${CONTEXT} needs: - builder version - cache: - - !reference [.fetch_src_cache, cache] alternative-tag [codechecker]: extends: .docker copy diff --git a/.gitlab/ci/builders/version.yml b/.gitlab/ci/builders/version.yml index 0c5eedd916..2892ad9b4e 100644 --- a/.gitlab/ci/builders/version.yml +++ b/.gitlab/ci/builders/version.yml @@ -6,37 +6,50 @@ # the distribution. # -builder version: +.builder version: stage: ci image: ubuntu:22.04 - rules: - - if: $ON_MR - - if: $ON_WEB - - if: $ON_API - - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ - - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ - - if: $CI_DESCRIPTION =~ /Weekly/ - - if: $CI_DESCRIPTION =~ /Alternative OSs/ script: - | hash_multiple() { - # Create a temporary tar archive of the folders - temp_archive=$(mktemp) - - # Create a tar archive with the provided folders - tar -cf "$temp_archive" --directory="${CI_PROJECT_DIR}" --mtime='1970-01-01' --sort=name "$@" + # Create a temporary tar archive of the folders + temp_archive=$(mktemp) + + # Create a tar archive with the provided folders + tar -cf "$temp_archive" \ + --directory="${SRSRANDIR}" \ + --mtime='1970-01-01' \ + --sort=name \ + --owner=0 --group=0 --numeric-owner \ + --mode=go+rwX \ + "$@" - # Generate the hash of the archive using sha256sum - hash=$(sha256sum "$temp_archive" | cut -c 1-32) - echo "$hash" + # Generate the hash of the archive using sha256sum + hash=$(sha256sum "$temp_archive" | cut -c 1-32) + echo "$hash" - # Clean up the temporary archive - rm "$temp_archive" + # Clean up the temporary archive + rm "$temp_archive" } + - echo ${SRSRANDIR} + - ls -lah ${SRSRANDIR} - DOCKER_BUILDER_VERSION=$(hash_multiple .gitlab/ci/builders docker/scripts) - echo "DOCKER_BUILDER_VERSION=$DOCKER_BUILDER_VERSION" >> builder.env - echo ${DOCKER_BUILDER_VERSION} artifacts: reports: dotenv: builder.env + +builder version: + extends: .builder version + rules: + - if: $ON_MR + - if: $ON_WEB + - if: $ON_API + - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ + - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ + - if: $CI_DESCRIPTION =~ /Weekly/ + - if: $CI_DESCRIPTION =~ /Alternative OSs/ + variables: + SRSRANDIR: $CI_PROJECT_DIR needs: [] diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 333164d62a..e542f551c2 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -10,46 +10,7 @@ include: - project: softwareradiosystems/ci/tools ref: "20" file: .gitlab/ci-shared/setup/all.yml - -variables: - TESTBED: - description: Retina Testbed Description - options: - - "zmq" - - "zmq_uesim" - - "zmq_deb" - - "zmq_srsue" - - "zmq_cudu" - - "rf_b200" - - "rf_hp" - - "android_b200" - - "android_x300" - - "viavi" - - "none" - value: "zmq" - MARKERS: - description: Selected pytest marker (label / tag). Tests with that mark will run. - value: "" - KEYWORDS: - description: Select tests by keyword expressions. This will run tests which contain names that match the given string expression (case-insensitive), which can include Python operators that use filenames, class names and function names as variables - value: "" - PYTEST_ARGS: - description: Extra pytest args for the e2e suite to run - value: "" - RETINA_PARAM_ARGS: - description: Extra retina args for the e2e suite to run - value: "" - RETINA_LAUNCHER_ARGS: - description: Extra launcher args - value: "" - E2E_LOG_LEVEL: - description: Log level to set for software under test in the e2e tests - options: - - debug - - info - - warning - - error - value: "info" + - local: .gitlab/ci-shared/e2e.yml .txrx-lib: &txrx-lib - job: "build trx driver" @@ -60,7 +21,7 @@ variables: artifacts: true load retina variables: - stage: ci + extends: .load retina variables rules: - if: $TESTBED == "none" when: never @@ -69,24 +30,8 @@ load retina variables: - if: $ON_WEB - if: $ON_API - if: $CI_DESCRIPTION =~ /Weekly/ - script: - - cat .gitlab/ci/e2e/.env - artifacts: - reports: - dotenv: .gitlab/ci/e2e/.env - -.prepare_test: variables: - KUBECONFIG_VAR_NAME: "RETINA_NAMESPACE_KUBECONFIG" - KUBECONFIG_VAR_NAME_EXTRA: "RETINA_NAMESPACE_KUBECONFIG_EXTRA" - before_script: &setup_kube_config - - | - export FORCE_COLOR=1 - eval K_PATH="\$$KUBECONFIG_VAR_NAME" - export KUBECONFIG=$K_PATH - - eval K_PATH_EXTRA="\$$KUBECONFIG_VAR_NAME_EXTRA" - export KUBECONFIG_EXTRA=$K_PATH_EXTRA + SRSRANDIR: $CI_PROJECT_DIR e2e request and config validation: stage: static @@ -113,106 +58,11 @@ e2e request and config validation: artifacts: true .e2e-run: - resource_group: e2e-${GROUP} - timeout: 3 hours - image: - name: ${RETINA_REGISTRY_PREFIX}/launcher:${RETINA_VERSION} - entrypoint: ["/bin/sh", "-c"] - interruptible: false - variables: - ARTIFACT_COMPRESSION_LEVEL: "slowest" - KUBERNETES_CPU_REQUEST: 2 - KUBERNETES_CPU_LIMIT: 2 - KUBERNETES_MEMORY_REQUEST: 2Gi - KUBERNETES_MEMORY_LIMIT: 2Gi - KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "20G" - KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "20G" - KUBECONFIG_VAR_NAME: "RETINA_NAMESPACE_KUBECONFIG" - KUBECONFIG_VAR_NAME_EXTRA: "RETINA_NAMESPACE_KUBECONFIG_EXTRA" - GROUP: zmq - tags: - - "${RETINA_TAG}" - extends: - - .prepare_test + extends: .e2e-run-template rules: - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ - artifacts: - paths: - - tests/e2e/log - when: always - expire_in: 1 week - reports: - junit: tests/e2e/out.xml - script: - - | - # Print E2E parameters - echo "GROUP=${GROUP}" - echo "TESTBED=${TESTBED}" - echo "MARKERS=${MARKERS}" - echo "KEYWORDS=${KEYWORDS}" - echo "PYTEST_ARGS=${PYTEST_ARGS}" - echo "RETINA_PARAM_ARGS=${RETINA_PARAM_ARGS}" - echo "RETINA_LAUNCHER_ARGS=${RETINA_LAUNCHER_ARGS}" - echo "E2E_LOG_LEVEL=${E2E_LOG_LEVEL}" - # Clean LFS files - - | - while read -r line; do - git rm --cached "$line" >/dev/null - done < <(git lfs ls-files | sed -r 's/^.{13}//') - echo "srsGNB sources+build size is" $(du -hs .) - # Remove any existing retina resource for this group - - retina-delete-orchestration-network --user-name ^ci_${GROUP} --regex - # Add extra config env variables to the .env file - - | - echo "" >> .gitlab/ci/e2e/.env - cat $RETINA_CONFIG_ENV >> .gitlab/ci/e2e/.env - # Modify request to shared the complete folder with the gnb container - - | - yq -i '(.[] | select(.type == "gnb") | .shared_files) += [{"local_path": "../../", "remote_path": env(CI_PROJECT_DIR), "is_executable": false}]' ${CI_PROJECT_DIR}/.gitlab/ci/e2e/retina_request_${TESTBED}.yml - # Set username for retina - - | - cd tests/e2e - export LOGNAME=ci_${GROUP}_${GITLAB_USER_LOGIN} - # Run Retina - - | - E2E_CMD="retina-launcher ${RETINA_LAUNCHER_ARGS} --retina-request=${CI_PROJECT_DIR}/.gitlab/ci/e2e/retina_request_${TESTBED}.yml ${PYTEST_ARGS} -k '${KEYWORDS}' -m '${MARKERS}' --register-parameter ue.all.log_level=$E2E_LOG_LEVEL gnb.all.log_level=$E2E_LOG_LEVEL ${RETINA_PARAM_ARGS}" - echo "${E2E_CMD}" - eval $E2E_CMD - after_script: - # Remove any existing retina resource for this group - - *setup_kube_config - - retina-delete-orchestration-network --user-name ^ci_${GROUP} --regex - # Push test metrics - - | - find . -iname "test_metrics.csv" -exec \ - influx write --host $INFLUXDB_URL --token $INFLUXDB_TOKEN --org $INFLUXDB_ORG \ - --bucket ci --file {} \; - # Artifact size - - echo -e "\e[0Ksection_start:`date +%s`:e2e_folder_section[collapsed=true]\r\e[0KLog folder's tree" - - | - print_tree() { - local dir="$1" - local prefix="$2" - - # List directories first - find "$dir" -mindepth 1 -maxdepth 1 -type d | while read -r subdir; do - local size=$(du -sh "$subdir" | awk '{print $1}') - echo "${prefix}├── $(basename "$subdir") [$size]" - print_tree "$subdir" "$prefix│ " - done - - # List files afterwards - find "$dir" -mindepth 1 -maxdepth 1 -type f | while read -r file; do - local size=$(du -sh "$file" | awk '{print $1}') - echo "${prefix}├── $(basename "$file") [$size]" - done - } - print_tree "tests/e2e/log/" "" - - echo -e "\e[0Ksection_end:`date +%s`:e2e_folder_section\r\e[0K" - - | - echo "*******************************************************************************************************************************" - echo "Test report ---> https://softwareradiosystems.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/tests/e2e/log//report.html" - echo "*******************************************************************************************************************************" + variables: + SRSRANDIR: $CI_PROJECT_DIR needs: - *retina-needs @@ -407,7 +257,7 @@ amari 32UE [ping]: variables: MARKERS: "zmq and not smoke" RETINA_PARAM_ARGS: "gnb.all.pcap=True gnb.all.rlc_enable=False gnb.all.enable_integrity_protection=True" - KEYWORDS: ping + KEYWORDS: "ping and 32" amari 32UE 2x2 mimo: extends: .zmq-uesim @@ -433,7 +283,15 @@ cudu amari 32UE: RETINA_PARAM_ARGS: "gnb.all.pcap=True gnb.all.rlc_enable=False gnb.all.enable_integrity_protection=True" parallel: matrix: - - KEYWORDS: ["ping", "iperf and tcp and not band:3 and bandwidth:50"] + - KEYWORDS: ["iperf and tcp and not band:3 and bandwidth:50"] + +cudu amari 64UE: + extends: .zmq + variables: + TESTBED: zmq_cudu + MARKERS: "zmq and not smoke" + RETINA_PARAM_ARGS: "gnb.all.pcap=True gnb.all.rlc_enable=False gnb.all.enable_integrity_protection=True" + KEYWORDS: "ping and 64" ################################################################################ # TEST MODE @@ -450,7 +308,6 @@ test mode ue: needs: - job: "basic relwithdeb" artifacts: true - - *txrx-lib - *retina-needs test mode ue asan: @@ -458,7 +315,6 @@ test mode ue asan: needs: - job: "basic asan" artifacts: true - - *txrx-lib - *retina-needs test mode ue memcheck: @@ -466,7 +322,6 @@ test mode ue memcheck: needs: - job: "basic memcheck" artifacts: true - - *txrx-lib - *retina-needs test mode ru: @@ -494,6 +349,7 @@ test mode ru tsan: artifacts: true - *txrx-lib - *retina-needs + allow_failure: true test mode ru asan: extends: test mode ru @@ -565,7 +421,6 @@ android b200: - job: "basic relwithdeb" artifacts: true - *retina-needs - allow_failure: true android IMS: stage: rf @@ -598,7 +453,6 @@ android x300: - job: "basic relwithdeb" artifacts: true - *retina-needs - allow_failure: true ################################################################################ # VIAVI diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 7a0e9fa4e2..7f7a57ae01 100644 --- a/.gitlab/ci/e2e/.env +++ b/.gitlab/ci/e2e/.env @@ -1,6 +1,6 @@ SRSGNB_REGISTRY_URI=registry.gitlab.com/softwareradiosystems/srsgnb RETINA_REGISTRY_PREFIX=registry.gitlab.com/softwareradiosystems/ci/retina -RETINA_VERSION=0.53.0 +RETINA_VERSION=0.53.5 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 diff --git a/.gitlab/ci/e2e/retina_request_viavi.yml b/.gitlab/ci/e2e/retina_request_viavi.yml index e62f767a89..51276c0746 100644 --- a/.gitlab/ci/e2e/retina_request_viavi.yml +++ b/.gitlab/ci/e2e/retina_request_viavi.yml @@ -29,7 +29,7 @@ - type: emulator model: viavi - type: ru - model: viavi + model: viavi-ru environment: - PATH: ${PATH}:/builds/softwareradiosystems/srsgnb/build/apps/gnb - LD_LIBRARY_PATH: /opt/dpdk/${DPDK_VERSION}/lib/x86_64-linux-gnu/ diff --git a/.gitlab/ci/e2e/retina_request_zmq.yml b/.gitlab/ci/e2e/retina_request_zmq.yml index 0130c4ef12..3695b2bb00 100644 --- a/.gitlab/ci/e2e/retina_request_zmq.yml +++ b/.gitlab/ci/e2e/retina_request_zmq.yml @@ -11,7 +11,7 @@ image: ${RETINA_REGISTRY_PREFIX}/amarisoftue:${AMARISOFT_VERSION}_${RETINA_VERSION} labels: - ${ZMQ_HOSTLABEL_0} - nof_ports: 32 + nof_ports: 64 requirements: arch: amd64 cpu: diff --git a/.gitlab/ci/e2e/retina_request_zmq_cudu.yml b/.gitlab/ci/e2e/retina_request_zmq_cudu.yml index e8a292e3ec..8aa9318a95 100644 --- a/.gitlab/ci/e2e/retina_request_zmq_cudu.yml +++ b/.gitlab/ci/e2e/retina_request_zmq_cudu.yml @@ -11,7 +11,7 @@ image: ${RETINA_REGISTRY_PREFIX}/amarisoftue:${AMARISOFT_VERSION}_${RETINA_VERSION} labels: - ${ZMQ_HOSTLABEL_0} - nof_ports: 32 + nof_ports: 64 requirements: arch: amd64 cpu: diff --git a/.gitlab/ci/src_cache.yml b/.gitlab/ci/src_cache.yml deleted file mode 100644 index c25ea2e05d..0000000000 --- a/.gitlab/ci/src_cache.yml +++ /dev/null @@ -1,100 +0,0 @@ -# -# Copyright 2013-2024 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. -# - -############################### -# Cache related code to reuse # -############################### - -.cache_src_set: &cache_src_set - - key: srsgnb-src - paths: [$CI_PROJECT_DIR] - untracked: false - policy: push - when: on_success - -.cache_src_get: &cache_src_get - - key: srsgnb-src - paths: [$CI_PROJECT_DIR] - policy: pull - -############################# -# Git source downloader job # -############################# - -push_src_cache amd: - stage: .pre - rules: - - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ - allow_failure: true - interruptible: false - script: - - echo "Saving git repo in cache" - cache: - - *cache_src_set - tags: ["${AMD64_TAG}"] - -push_src_cache arm: - extends: push_src_cache amd - tags: ["${ARM64_TAG}"] - -pull_src_cache amd: - stage: .pre - rules: - - if: $CI_DESCRIPTION =~ /Nightly Build Unit Tests/ - allow_failure: true - interruptible: false - variables: - GIT_STRATEGY: none - needs: - - job: push_src_cache amd - artifacts: false - optional: true - script: - - echo "Reading git repo in cache" - cache: - - *cache_src_get - tags: ["${AMD64_TAG}"] - -pull_src_cache arm: - extends: pull_src_cache amd - tags: ["${ARM64_TAG}"] - needs: - - job: push_src_cache arm - artifacts: false - optional: true - -######################################### -# Template to fetch src code from cache # -######################################### - -.fetch_src_cache: - variables: - GIT_STRATEGY: none - before_script: - - | - . /etc/os-release - case "$ID" in - debian | ubuntu) apt-get update && apt-get install -y --no-install-recommends git ;; - arch) pacman -Syu --noconfirm git ;; - rhel) yum install -y git ;; - alpine) apk add git ;; - *) echo 'Unsupported OS' && exit 1 ;; - esac - script: - - git remote set-url origin https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git - - git fetch --depth=1 origin $CI_COMMIT_SHA - - git reset --hard $CI_COMMIT_SHA - needs: - - job: pull_src_cache amd - artifacts: false - optional: true - - job: pull_src_cache arm - artifacts: false - optional: true - cache: - - *cache_src_get diff --git a/apps/cu/CMakeLists.txt b/apps/cu/CMakeLists.txt index 87c5ffd73c..4e87d02117 100644 --- a/apps/cu/CMakeLists.txt +++ b/apps/cu/CMakeLists.txt @@ -23,6 +23,8 @@ add_executable(srscu cu_appconfig_cli11_schema.cpp cu_appconfig_validator.cpp cu_appconfig_yaml_writer.cpp + ../gnb/gnb_appconfig_translators.cpp + ../gnb/adapters/e2_gateway_remote_connector.cpp # TODO: Delete ) install(TARGETS srscu @@ -36,7 +38,8 @@ target_link_libraries(srscu srsran_cu_up_app_unit srsran_ngap srsran_f1c_gateway - srsran_e1_gateway + srsran_e1_gateway + srsran_e2 srsgnb_app_f1u_cu_up_split_connector srsran_pcap ngap_asn1 diff --git a/apps/cu/cu.cpp b/apps/cu/cu.cpp index aaf8e9d2a9..9424db9d4c 100644 --- a/apps/cu/cu.cpp +++ b/apps/cu/cu.cpp @@ -327,7 +327,11 @@ int main(int argc, char** argv) cu_cp_dependencies.timers = cu_timers; cu_cp_dependencies.ngap_pcap = cu_cp_dlt_pcaps.ngap.get(); cu_cp_dependencies.broker = epoll_broker.get(); - + // E2AP configuration. + srsran::sctp_network_connector_config e2_cu_nw_config = generate_e2ap_nw_config(cu_cfg.e2_cfg, E2_CP_PPID); + // Create E2AP GW remote connector. + e2_gateway_remote_connector e2_gw_cu{*epoll_broker, e2_cu_nw_config, *cu_cp_dlt_pcaps.e2ap}; + cu_cp_dependencies.e2_gw = &e2_gw_cu; // create CU-CP. auto cu_cp_obj_and_cmds = cu_cp_app_unit->create_cu_cp(cu_cp_dependencies); srs_cu_cp::cu_cp& cu_cp_obj = *cu_cp_obj_and_cmds.unit; diff --git a/apps/cu/cu_appconfig.h b/apps/cu/cu_appconfig.h index 83ca506c61..cd6e53a097 100644 --- a/apps/cu/cu_appconfig.h +++ b/apps/cu/cu_appconfig.h @@ -66,6 +66,8 @@ struct cu_appconfig { /// Buffer pool configuration. buffer_pool_appconfig buffer_pool_config; + /// E2 configuration. + e2_appconfig e2_cfg; /// TODO fill in the rest of the configuration }; diff --git a/apps/du/du.cpp b/apps/du/du.cpp index c05e0cfb2f..6839ace51e 100644 --- a/apps/du/du.cpp +++ b/apps/du/du.cpp @@ -45,7 +45,7 @@ #include "apps/units/flexible_du/split_dynamic/dynamic_du_factory.h" #include "apps/gnb/adapters/e2_gateway_remote_connector.h" -#include "apps/services/e2_metric_connector_manager.h" +#include "apps/services/e2/e2_metric_connector_manager.h" // Include ThreadSanitizer (TSAN) options if thread sanitization is enabled. // This include is not unused - it helps prevent false alarms from the thread sanitizer. @@ -300,29 +300,25 @@ int main(int argc, char** argv) srslog::sink& json_sink = srslog::fetch_udp_sink(du_cfg.metrics_cfg.addr, du_cfg.metrics_cfg.port, srslog::create_json_formatter()); - e2_metric_connector_manager e2_metric_connectors(du_app_unit->get_du_high_unit_config().cells_cfg.size()); - // E2AP configuration. - srsran::sctp_network_connector_config e2_du_nw_config = generate_e2ap_nw_config(du_cfg, E2_DU_PPID); + srsran::sctp_network_connector_config e2_du_nw_config = generate_e2ap_nw_config(du_cfg.e2_cfg, E2_DU_PPID); // Create E2AP GW remote connector. e2_gateway_remote_connector e2_gw{*epoll_broker, e2_du_nw_config, *du_pcaps.e2ap}; app_services::metrics_notifier_proxy_impl metrics_notifier_forwarder; du_unit_dependencies du_dependencies; - du_dependencies.workers = &workers; - du_dependencies.f1c_client_handler = f1c_gw.get(); - du_dependencies.f1u_gw = du_f1u_conn.get(); - du_dependencies.timer_mng = &app_timers; - du_dependencies.mac_p = du_pcaps.mac.get(); - du_dependencies.rlc_p = du_pcaps.rlc.get(); - du_dependencies.e2_client_handler = &e2_gw; - du_dependencies.e2_metric_connectors = &e2_metric_connectors; - du_dependencies.json_sink = &json_sink; - du_dependencies.metrics_notifier = &metrics_notifier_forwarder; + du_dependencies.workers = &workers; + du_dependencies.f1c_client_handler = f1c_gw.get(); + du_dependencies.f1u_gw = du_f1u_conn.get(); + du_dependencies.timer_mng = &app_timers; + du_dependencies.mac_p = du_pcaps.mac.get(); + du_dependencies.rlc_p = du_pcaps.rlc.get(); + du_dependencies.e2_client_handler = &e2_gw; + du_dependencies.json_sink = &json_sink; + du_dependencies.metrics_notifier = &metrics_notifier_forwarder; auto du_inst_and_cmds = du_app_unit->create_flexible_du_unit(du_dependencies); - // Only DU has metrics now. app_services::metrics_manager metrics_mngr( srslog::fetch_basic_logger("GNB"), *workers.metrics_hub_exec, du_inst_and_cmds.metrics); diff --git a/apps/du/du_appconfig.h b/apps/du/du_appconfig.h index c302256ae7..5693532260 100644 --- a/apps/du/du_appconfig.h +++ b/apps/du/du_appconfig.h @@ -49,12 +49,8 @@ struct nru_appconfig { /// Metrics report configuration. struct metrics_appconfig { - /// JSON metrics reporting. - bool enable_json_metrics = false; - std::string addr = "127.0.0.1"; - uint16_t port = 55555; - bool autostart_stdout_metrics = false; - unsigned stdout_metrics_period = 1000; // Statistics report period in milliseconds + std::string addr = "127.0.0.1"; + uint16_t port = 55555; }; } // namespace srs_du diff --git a/apps/du/du_appconfig_cli11_schema.cpp b/apps/du/du_appconfig_cli11_schema.cpp index b5dca17851..e26d966576 100644 --- a/apps/du/du_appconfig_cli11_schema.cpp +++ b/apps/du/du_appconfig_cli11_schema.cpp @@ -43,23 +43,10 @@ static expected parse_int(const std::string& value) static void configure_cli11_metrics_args(CLI::App& app, srs_du::metrics_appconfig& metrics_params) { - add_option(app, "--enable_json_metrics", metrics_params.enable_json_metrics, "Enable JSON metrics reporting") - ->always_capture_default(); - app.add_option("--addr", metrics_params.addr, "Metrics address.")->capture_default_str()->check(CLI::ValidIPV4); app.add_option("--port", metrics_params.port, "Metrics UDP port.") ->capture_default_str() ->check(CLI::Range(0, 65535)); - - app.add_option( - "--autostart_stdout_metrics", metrics_params.autostart_stdout_metrics, "Autostart stdout metrics reporting") - ->capture_default_str(); - - add_option(app, - "--stdout_metrics_period", - metrics_params.stdout_metrics_period, - "DU statistics report period in milliseconds. This metrics sets the console output period.") - ->capture_default_str(); } static void configure_cli11_e2_args(CLI::App& app, e2_appconfig& e2_params) diff --git a/apps/du/du_appconfig_translators.cpp b/apps/du/du_appconfig_translators.cpp index 507b900d53..933aab3bd4 100644 --- a/apps/du/du_appconfig_translators.cpp +++ b/apps/du/du_appconfig_translators.cpp @@ -28,30 +28,30 @@ using namespace srsran; using namespace std::chrono_literals; // TODO: refactor. -srsran::sctp_network_connector_config srsran::generate_e2ap_nw_config(const du_appconfig& config, int ppid) +srsran::sctp_network_connector_config srsran::generate_e2ap_nw_config(const e2_appconfig& config, int ppid) { srsran::sctp_network_connector_config out_cfg; out_cfg.dest_name = "NearRT-RIC"; out_cfg.if_name = "E2"; - out_cfg.connect_address = config.e2_cfg.ip_addr; - out_cfg.connect_port = config.e2_cfg.port; - out_cfg.bind_address = config.e2_cfg.bind_addr; + out_cfg.connect_address = config.ip_addr; + out_cfg.connect_port = config.port; + out_cfg.bind_address = config.bind_addr; out_cfg.ppid = ppid; - if (config.e2_cfg.sctp_rto_initial >= 0) { - out_cfg.rto_initial = config.e2_cfg.sctp_rto_initial; + if (config.sctp_rto_initial >= 0) { + out_cfg.rto_initial = config.sctp_rto_initial; } - if (config.e2_cfg.sctp_rto_min >= 0) { - out_cfg.rto_min = config.e2_cfg.sctp_rto_min; + if (config.sctp_rto_min >= 0) { + out_cfg.rto_min = config.sctp_rto_min; } - if (config.e2_cfg.sctp_rto_max >= 0) { - out_cfg.rto_max = config.e2_cfg.sctp_rto_max; + if (config.sctp_rto_max >= 0) { + out_cfg.rto_max = config.sctp_rto_max; } - if (config.e2_cfg.sctp_init_max_attempts >= 0) { - out_cfg.init_max_attempts = config.e2_cfg.sctp_init_max_attempts; + if (config.sctp_init_max_attempts >= 0) { + out_cfg.init_max_attempts = config.sctp_init_max_attempts; } - if (config.e2_cfg.sctp_max_init_timeo >= 0) { - out_cfg.max_init_timeo = config.e2_cfg.sctp_max_init_timeo; + if (config.sctp_max_init_timeo >= 0) { + out_cfg.max_init_timeo = config.sctp_max_init_timeo; } return out_cfg; diff --git a/apps/du/du_appconfig_translators.h b/apps/du/du_appconfig_translators.h index 7e3e4e4857..d05400f28a 100644 --- a/apps/du/du_appconfig_translators.h +++ b/apps/du/du_appconfig_translators.h @@ -29,11 +29,12 @@ namespace srsran { struct du_appconfig; struct worker_manager_config; +struct e2_appconfig; /// Converts and returns the given gnb application configuration to a E2AP Network Gateway configuration. -sctp_network_connector_config generate_e2ap_nw_config(const du_appconfig& config, int ppid); +sctp_network_connector_config generate_e2ap_nw_config(const e2_appconfig& config, int ppid); /// Fills the DU worker manager parameters of the given worker manager configuration. void fill_du_worker_manager_config(worker_manager_config& config, const du_appconfig& unit_cfg); -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/apps/du/du_appconfig_yaml_writer.cpp b/apps/du/du_appconfig_yaml_writer.cpp index eecb85c81a..8c4ee0215b 100644 --- a/apps/du/du_appconfig_yaml_writer.cpp +++ b/apps/du/du_appconfig_yaml_writer.cpp @@ -28,11 +28,8 @@ using namespace srsran; static void fill_du_appconfig_metrics_section(YAML::Node node, const srs_du::metrics_appconfig& config) { - node["enable_json_metrics"] = config.enable_json_metrics; - node["addr"] = config.addr; - node["port"] = config.port; - node["autostart_stdout_metrics"] = config.autostart_stdout_metrics; - node["stdout_metrics_period"] = config.stdout_metrics_period; + node["addr"] = config.addr; + node["port"] = config.port; } static void fill_du_appconfig_e2_section(YAML::Node node, const e2_appconfig& config) diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 18bf1a7d29..0f68694fc1 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -47,13 +47,14 @@ #include "apps/services/application_tracer.h" #include "apps/services/buffer_pool/buffer_pool_manager.h" #include "apps/services/core_isolation_manager.h" -#include "apps/services/e2_metric_connector_manager.h" +#include "apps/services/e2/e2_metric_connector_manager.h" #include "apps/services/metrics/metrics_manager.h" #include "apps/services/metrics/metrics_notifier_proxy.h" #include "apps/services/stdin_command_dispatcher.h" #include "apps/services/worker_manager.h" #include "apps/gnb/adapters/e2_gateway_remote_connector.h" +#include "apps/services/e2/e2_metric_connector_manager.h" // Include ThreadSanitizer (TSAN) options if thread sanitization is enabled. // This include is not unused - it helps prevent false alarms from the thread sanitizer. @@ -370,8 +371,6 @@ int main(int argc, char** argv) srslog::sink& json_sink = srslog::fetch_udp_sink(gnb_cfg.metrics_cfg.addr, gnb_cfg.metrics_cfg.port, srslog::create_json_formatter()); - e2_metric_connector_manager e2_metric_connectors(du_app_unit->get_du_high_unit_config().cells_cfg.size()); - // Load CU-CP plugins if enabled std::optional ng_handover_plugin = cu_cp_app_unit->get_cu_cp_unit_config().load_plugins @@ -418,10 +417,17 @@ int main(int argc, char** argv) cu_cp_dependencies.ngap_pcap = cu_cp_dlt_pcaps.ngap.get(); cu_cp_dependencies.broker = epoll_broker.get(); - // create CU-CP. - auto cu_cp_obj_and_cmds = cu_cp_app_unit->create_cu_cp(cu_cp_dependencies); + // E2AP configuration. + srsran::sctp_network_connector_config e2_du_nw_config = generate_e2ap_nw_config(gnb_cfg.e2_cfg, E2_DU_PPID); + srsran::sctp_network_connector_config e2_cu_nw_config = generate_e2ap_nw_config(gnb_cfg.e2_cfg, E2_CP_PPID); - srs_cu_cp::cu_cp& cu_cp_obj = *cu_cp_obj_and_cmds.unit; + // Create E2AP GW remote connector. + e2_gateway_remote_connector e2_gw_du{*epoll_broker, e2_du_nw_config, *du_pcaps.e2ap}; + e2_gateway_remote_connector e2_gw_cu{*epoll_broker, e2_cu_nw_config, *cu_cp_dlt_pcaps.e2ap}; + cu_cp_dependencies.e2_gw = &e2_gw_cu; + // create CU-CP. + auto cu_cp_obj_and_cmds = cu_cp_app_unit->create_cu_cp(cu_cp_dependencies); + srs_cu_cp::cu_cp& cu_cp_obj = *cu_cp_obj_and_cmds.unit; // Create and start CU-UP cu_up_unit_dependencies cu_up_unit_deps; @@ -434,25 +440,18 @@ int main(int argc, char** argv) std::unique_ptr cu_up_obj = cu_up_app_unit->create_cu_up_unit(cu_up_unit_deps); - // E2AP configuration. - sctp_network_connector_config e2_du_nw_config = generate_e2ap_nw_config(gnb_cfg, E2_DU_PPID); - - // Create E2AP GW remote connector. - e2_gateway_remote_connector e2_gw{*epoll_broker, e2_du_nw_config, *du_pcaps.e2ap}; - // Instantiate one DU. app_services::metrics_notifier_proxy_impl metrics_notifier_forwarder; du_unit_dependencies du_dependencies; - du_dependencies.workers = &workers; - du_dependencies.f1c_client_handler = f1c_gw.get(); - du_dependencies.f1u_gw = f1u_conn->get_f1u_du_gateway(); - du_dependencies.timer_mng = &app_timers; - du_dependencies.mac_p = du_pcaps.mac.get(); - du_dependencies.rlc_p = du_pcaps.rlc.get(); - du_dependencies.e2_client_handler = &e2_gw; - du_dependencies.e2_metric_connectors = &e2_metric_connectors; - du_dependencies.json_sink = &json_sink; - du_dependencies.metrics_notifier = &metrics_notifier_forwarder; + du_dependencies.workers = &workers; + du_dependencies.f1c_client_handler = f1c_gw.get(); + du_dependencies.f1u_gw = f1u_conn->get_f1u_du_gateway(); + du_dependencies.timer_mng = &app_timers; + du_dependencies.mac_p = du_pcaps.mac.get(); + du_dependencies.rlc_p = du_pcaps.rlc.get(); + du_dependencies.e2_client_handler = &e2_gw_du; + du_dependencies.json_sink = &json_sink; + du_dependencies.metrics_notifier = &metrics_notifier_forwarder; auto du_inst_and_cmds = du_app_unit->create_flexible_du_unit(du_dependencies); @@ -512,8 +511,13 @@ int main(int argc, char** argv) cu_cp_obj.stop(); if (gnb_cfg.e2_cfg.enable_du_e2) { - gnb_logger.info("Closing E2 network connections..."); - e2_gw.close(); + gnb_logger.info("Closing E2 DU network connections..."); + e2_gw_du.close(); + gnb_logger.info("E2 Network connections closed successfully"); + } + if (gnb_cfg.e2_cfg.enable_cu_e2) { + gnb_logger.info("Closing E2 CU network connections..."); + e2_gw_cu.close(); gnb_logger.info("E2 Network connections closed successfully"); } diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 431555e3fe..3e7b858206 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -23,6 +23,7 @@ #pragma once #include "apps/services/buffer_pool/buffer_pool_appconfig.h" +#include "apps/services/e2/e2_appconfig.h" #include "apps/services/logger/logger_appconfig.h" #include "apps/services/os_sched_affinity_manager.h" #include "srsran/ran/gnb_id.h" @@ -31,21 +32,6 @@ namespace srsran { -/// E2 Agent configuration -struct e2_appconfig { - bool enable_du_e2 = false; ///< Whether to enable DU E2 agent - std::string ip_addr = "127.0.0.1"; ///< RIC IP address - uint16_t port = 36421; ///< RIC port - std::string bind_addr = "127.0.0.1"; ///< Local IP address to bind for RIC connection - int sctp_rto_initial = 120; ///< SCTP initial RTO value for RIC connection - int sctp_rto_min = 120; ///< SCTP RTO min for RIC connection - int sctp_rto_max = 500; ///< SCTP RTO max for RIC connection - int sctp_init_max_attempts = 3; ///< SCTP init max attempts for RIC connection - int sctp_max_init_timeo = 500; ///< SCTP max init timeout for RIC connection - bool e2sm_kpm_enabled = false; ///< Whether to enable KPM service module - bool e2sm_rc_enabled = false; ///< Whether to enable RC service module -}; - struct cu_up_appconfig { unsigned gtpu_queue_size = 2048; unsigned gtpu_reordering_timer_ms = 0; @@ -54,15 +40,8 @@ struct cu_up_appconfig { /// Metrics report configuration. struct metrics_appconfig { - struct pdcp_metrics { - unsigned report_period = 0; // PDCP report period in ms - } pdcp; - /// JSON metrics reporting. - bool enable_json_metrics = false; - std::string addr = "127.0.0.1"; - uint16_t port = 55555; - bool autostart_stdout_metrics = false; - unsigned stdout_metrics_period = 1000; // Statistics report period in milliseconds + std::string addr = "127.0.0.1"; + uint16_t port = 55555; }; /// CPU affinities configuration for the gNB app. diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 260ec97cfb..d9a1cadee0 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -45,31 +45,16 @@ static expected parse_int(const std::string& value) static void configure_cli11_metrics_args(CLI::App& app, metrics_appconfig& metrics_params) { - app.add_option("--pdcp_report_period", metrics_params.pdcp.report_period, "PDCP metrics report period") - ->capture_default_str(); - - add_option(app, "--enable_json_metrics", metrics_params.enable_json_metrics, "Enable JSON metrics reporting") - ->always_capture_default(); - app.add_option("--addr", metrics_params.addr, "Metrics address.")->capture_default_str(); app.add_option("--port", metrics_params.port, "Metrics UDP port.") ->capture_default_str() ->check(CLI::Range(0, 65535)); - - add_option( - app, "--autostart_stdout_metrics", metrics_params.autostart_stdout_metrics, "Autostart stdout metrics reporting") - ->capture_default_str(); - - add_option(app, - "--stdout_metrics_period", - metrics_params.stdout_metrics_period, - "DU statistics report period in milliseconds. This metrics sets the console output period.") - ->capture_default_str(); } static void configure_cli11_e2_args(CLI::App& app, e2_appconfig& e2_params) { add_option(app, "--enable_du_e2", e2_params.enable_du_e2, "Enable DU E2 agent")->capture_default_str(); + add_option(app, "--enable_cu_e2", e2_params.enable_cu_e2, "Enable CU E2 agent")->capture_default_str(); add_option(app, "--addr", e2_params.ip_addr, "RIC IP address")->capture_default_str(); add_option(app, "--port", e2_params.port, "RIC port")->check(CLI::Range(20000, 40000))->capture_default_str(); add_option(app, "--bind_addr", e2_params.bind_addr, "Local IP address to bind for RIC connection") diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 1a9b6aa13a..da0356db61 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -29,30 +29,30 @@ using namespace srsran; using namespace std::chrono_literals; -srsran::sctp_network_connector_config srsran::generate_e2ap_nw_config(const gnb_appconfig& config, int ppid) +srsran::sctp_network_connector_config srsran::generate_e2ap_nw_config(const e2_appconfig& config, int ppid) { srsran::sctp_network_connector_config out_cfg; out_cfg.dest_name = "NearRT-RIC"; out_cfg.if_name = "E2"; - out_cfg.connect_address = config.e2_cfg.ip_addr; - out_cfg.connect_port = config.e2_cfg.port; - out_cfg.bind_address = config.e2_cfg.bind_addr; + out_cfg.connect_address = config.ip_addr; + out_cfg.connect_port = config.port; + out_cfg.bind_address = config.bind_addr; out_cfg.ppid = ppid; - if (config.e2_cfg.sctp_rto_initial >= 0) { - out_cfg.rto_initial = config.e2_cfg.sctp_rto_initial; + if (config.sctp_rto_initial >= 0) { + out_cfg.rto_initial = config.sctp_rto_initial; } - if (config.e2_cfg.sctp_rto_min >= 0) { - out_cfg.rto_min = config.e2_cfg.sctp_rto_min; + if (config.sctp_rto_min >= 0) { + out_cfg.rto_min = config.sctp_rto_min; } - if (config.e2_cfg.sctp_rto_max >= 0) { - out_cfg.rto_max = config.e2_cfg.sctp_rto_max; + if (config.sctp_rto_max >= 0) { + out_cfg.rto_max = config.sctp_rto_max; } - if (config.e2_cfg.sctp_init_max_attempts >= 0) { - out_cfg.init_max_attempts = config.e2_cfg.sctp_init_max_attempts; + if (config.sctp_init_max_attempts >= 0) { + out_cfg.init_max_attempts = config.sctp_init_max_attempts; } - if (config.e2_cfg.sctp_max_init_timeo >= 0) { - out_cfg.max_init_timeo = config.e2_cfg.sctp_max_init_timeo; + if (config.sctp_max_init_timeo >= 0) { + out_cfg.max_init_timeo = config.sctp_max_init_timeo; } return out_cfg; diff --git a/apps/gnb/gnb_appconfig_translators.h b/apps/gnb/gnb_appconfig_translators.h index 862a3e50a9..7073d4ad3c 100644 --- a/apps/gnb/gnb_appconfig_translators.h +++ b/apps/gnb/gnb_appconfig_translators.h @@ -22,12 +22,12 @@ #pragma once +#include "apps/services/e2/e2_appconfig.h" #include "srsran/cu_cp/cu_cp_configuration.h" #include "srsran/cu_up/cu_up_configuration.h" #include "srsran/du/du_cell_config.h" #include "srsran/du/du_high/du_qos_config.h" #include "srsran/du/du_high/du_srb_config.h" -#include "srsran/e2/e2ap_configuration.h" #include "srsran/gateways/sctp_network_gateway.h" #include "srsran/mac/mac_config.h" #include "srsran/phy/upper/upper_phy_factories.h" @@ -53,7 +53,7 @@ struct worker_manager_config; subcarrier_spacing generate_subcarrier_spacing(unsigned sc_spacing); /// Converts and returns the given gnb application configuration to a E2AP Network Gateway configuration. -srsran::sctp_network_connector_config generate_e2ap_nw_config(const gnb_appconfig& config, int ppid); +srsran::sctp_network_connector_config generate_e2ap_nw_config(const e2_appconfig& config, int ppid); /// Fills the gNB worker manager parameters of the given worker manager configuration. void fill_gnb_worker_manager_config(worker_manager_config& config, const gnb_appconfig& unit_cfg); diff --git a/apps/gnb/gnb_appconfig_yaml_writer.cpp b/apps/gnb/gnb_appconfig_yaml_writer.cpp index ebe675468a..55a9c56d11 100644 --- a/apps/gnb/gnb_appconfig_yaml_writer.cpp +++ b/apps/gnb/gnb_appconfig_yaml_writer.cpp @@ -28,12 +28,8 @@ using namespace srsran; static void fill_gnb_appconfig_metrics_section(YAML::Node node, const metrics_appconfig& config) { - node["pdcp_report_period"] = config.pdcp.report_period; - node["enable_json_metrics"] = config.enable_json_metrics; - node["addr"] = config.addr; - node["port"] = config.port; - node["autostart_stdout_metrics"] = config.autostart_stdout_metrics; - node["stdout_metrics_period"] = config.stdout_metrics_period; + node["addr"] = config.addr; + node["port"] = config.port; } static void fill_gnb_appconfig_e2_section(YAML::Node node, const e2_appconfig& config) diff --git a/apps/services/CMakeLists.txt b/apps/services/CMakeLists.txt index f9bdec72f7..dea22f91c3 100644 --- a/apps/services/CMakeLists.txt +++ b/apps/services/CMakeLists.txt @@ -22,7 +22,6 @@ add_subdirectory(buffer_pool) add_subdirectory(logger) set(SOURCES - e2_metric_connector_manager.cpp stdin_command_dispatcher.cpp worker_manager.cpp) diff --git a/apps/services/e2/e2_appconfig.h b/apps/services/e2/e2_appconfig.h new file mode 100644 index 0000000000..88eb52dff6 --- /dev/null +++ b/apps/services/e2/e2_appconfig.h @@ -0,0 +1,45 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include +#include + +namespace srsran { +/// E2 Agent configuration +struct e2_appconfig { + bool enable_du_e2 = false; ///< Whether to enable DU E2 agent + bool enable_cu_e2 = false; ///< Whether to enable CU E2 agent + std::string ip_addr = "127.0.0.1"; ///< RIC IP address + uint16_t port = 36421; ///< RIC port + std::string bind_addr = "127.0.0.1"; ///< Local IP address to bind for RIC connection + int sctp_rto_initial = 120; ///< SCTP initial RTO value for RIC connection + int sctp_rto_min = 120; ///< SCTP RTO min for RIC connection + int sctp_rto_max = 500; ///< SCTP RTO max for RIC connection + int sctp_init_max_attempts = 3; ///< SCTP init max attempts for RIC connection + int sctp_max_init_timeo = 500; ///< SCTP max init timeout for RIC connection + bool e2sm_kpm_enabled = false; ///< Whether to enable KPM service module + bool e2sm_rc_enabled = false; ///< Whether to enable RC service module +}; + +} // namespace srsran diff --git a/apps/services/e2/e2_metric_connector_manager.h b/apps/services/e2/e2_metric_connector_manager.h new file mode 100644 index 0000000000..0a963bb793 --- /dev/null +++ b/apps/services/e2/e2_metric_connector_manager.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include +#include +#include + +namespace srsran { + +/// Manages the E2 metric connectors of the app. +template +class e2_metric_connector_manager +{ +public: + e2_metric_connector_manager(unsigned nof_cells = 1) + { + for (unsigned i = 0, e = nof_cells; i != e; ++i) { + e2_metric_connectors.push_back(std::make_shared()); + } + } + + e2_metric_connector_manager(e2_metric_connector_manager&& other) noexcept : + e2_metric_connectors(std::move(other.e2_metric_connectors)) + { + } + + NotifierType& get_e2_metric_notifier(unsigned index) + { + assert(index < e2_metric_connectors.size() && "Invalid index"); + return *(e2_metric_connectors[index]); + } + InterfaceType& get_e2_metrics_interface(unsigned index) + { + assert(index < e2_metric_connectors.size() && "Invalid index"); + return *(e2_metric_connectors[index]); + } + +private: + std::vector> e2_metric_connectors; +}; + +} // namespace srsran diff --git a/apps/units/cu_cp/CMakeLists.txt b/apps/units/cu_cp/CMakeLists.txt index ebf140dacf..31180cbad4 100644 --- a/apps/units/cu_cp/CMakeLists.txt +++ b/apps/units/cu_cp/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES cu_cp_application_unit_impl.cpp cu_cp_builder.cpp + cu_cp_wrapper.cpp cu_cp_unit_config_cli11_schema.cpp cu_cp_config_translators.cpp cu_cp_unit_config_validator.cpp diff --git a/apps/units/cu_cp/cu_cp_builder.cpp b/apps/units/cu_cp/cu_cp_builder.cpp index e92cb8a2a7..7edf3cb5a9 100644 --- a/apps/units/cu_cp/cu_cp_builder.cpp +++ b/apps/units/cu_cp/cu_cp_builder.cpp @@ -21,11 +21,13 @@ */ #include "cu_cp_builder.h" +#include "apps/units/cu_cp/cu_cp_unit_config.h" #include "cu_cp_commands.h" #include "cu_cp_config_translators.h" #include "cu_cp_unit_config.h" #include "cu_cp_wrapper.h" #include "srsran/cu_cp/cu_cp_factory.h" +#include "srsran/e2/e2_cu_metrics_connector.h" using namespace srsran; @@ -33,7 +35,6 @@ cu_cp_unit srsran::build_cu_cp(const cu_cp_unit_config& cu_cp_unit_cfg, cu_cp_bu { srsran_assert(dependencies.cu_cp_executor, "Invalid CU-CP executor"); srsran_assert(dependencies.cu_cp_e2_exec, "Invalid E2 executor"); - srsran_assert(dependencies.cu_cp_e2_exec, "Invalid E2 executor"); srsran_assert(dependencies.ngap_pcap, "Invalid NGAP PCAP"); srsran_assert(dependencies.broker, "Invalid IO broker"); @@ -58,9 +59,17 @@ cu_cp_unit srsran::build_cu_cp(const cu_cp_unit_config& cu_cp_unit_cfg, cu_cp_bu for (unsigned pos = 0; pos < n2_clients.size(); pos++) { cu_cp_cfg.ngaps[pos].n2_gw = n2_clients[pos].get(); } + auto e2_metric_connectors = std::make_unique(); + + if (cu_cp_unit_cfg.e2_cfg.enable_unit_e2) { + cu_cp_cfg.e2_client = dependencies.e2_gw; + cu_cp_cfg.e2ap_config = generate_e2_config(cu_cp_unit_cfg); + cu_cp_cfg.e2_cu_metric_iface = &(*e2_metric_connectors).get_e2_metrics_interface(0); + } cu_cp_unit cu_cmd_wrapper; - cu_cmd_wrapper.unit = std::make_unique(std::move(n2_clients), create_cu_cp(cu_cp_cfg)); + cu_cmd_wrapper.unit = + std::make_unique(std::move(n2_clients), std::move(e2_metric_connectors), create_cu_cp(cu_cp_cfg)); // Add the commands; cu_cmd_wrapper.commands.push_back(std::make_unique(cu_cmd_wrapper.unit->get_command_handler())); diff --git a/apps/units/cu_cp/cu_cp_builder.h b/apps/units/cu_cp/cu_cp_builder.h index 7d5e70941a..9643318b89 100644 --- a/apps/units/cu_cp/cu_cp_builder.h +++ b/apps/units/cu_cp/cu_cp_builder.h @@ -23,7 +23,10 @@ #pragma once #include "apps/services/application_command.h" +#include "apps/services/e2/e2_metric_connector_manager.h" +#include "cu_cp_wrapper.h" #include "srsran/cu_cp/cu_cp.h" +#include "srsran/e2/e2_cu_metrics_connector.h" namespace srsran { @@ -36,18 +39,24 @@ namespace srs_cu_cp { class n2_connection_client; } +template +class e2_metric_connector_manager; +class e2_connection_client; +class e2_gateway_remote_connector; + /// CU-CP build dependencies. struct cu_cp_build_dependencies { - task_executor* cu_cp_executor = nullptr; - task_executor* cu_cp_e2_exec = nullptr; - timer_manager* timers = nullptr; - dlt_pcap* ngap_pcap = nullptr; - io_broker* broker = nullptr; + task_executor* cu_cp_executor = nullptr; + task_executor* cu_cp_e2_exec = nullptr; + timer_manager* timers = nullptr; + dlt_pcap* ngap_pcap = nullptr; + io_broker* broker = nullptr; + e2_connection_client* e2_gw = nullptr; }; /// Wraps the CU-CP and its supported application commands. struct cu_cp_unit { - std::unique_ptr unit; + std::unique_ptr unit; std::vector> commands; }; diff --git a/apps/units/cu_cp/cu_cp_config_translators.cpp b/apps/units/cu_cp/cu_cp_config_translators.cpp index ea18421a84..2d1179a281 100644 --- a/apps/units/cu_cp/cu_cp_config_translators.cpp +++ b/apps/units/cu_cp/cu_cp_config_translators.cpp @@ -466,6 +466,15 @@ srs_cu_cp::cu_cp_configuration srsran::generate_cu_cp_config(const cu_cp_unit_co return out_cfg; } +e2ap_configuration srsran::generate_e2_config(const cu_cp_unit_config& cu_cp) +{ + e2ap_configuration out_cfg = srsran::config_helpers::make_default_e2ap_config(); + out_cfg.gnb_id = cu_cp.gnb_id; + out_cfg.e2sm_kpm_enabled = cu_cp.e2_cfg.e2sm_kpm_enabled; + out_cfg.e2sm_rc_enabled = cu_cp.e2_cfg.e2sm_rc_enabled; + return out_cfg; +} + srs_cu_cp::n2_connection_client_config srsran::generate_n2_client_config(bool no_core, const cu_cp_unit_amf_config_item& amf_cfg, dlt_pcap& pcap_writer, diff --git a/apps/units/cu_cp/cu_cp_config_translators.h b/apps/units/cu_cp/cu_cp_config_translators.h index 6e9810f38d..afa6c4e749 100644 --- a/apps/units/cu_cp/cu_cp_config_translators.h +++ b/apps/units/cu_cp/cu_cp_config_translators.h @@ -23,6 +23,7 @@ #pragma once #include "srsran/cu_cp/cu_cp_configuration.h" +#include "srsran/e2/e2ap_configuration_helpers.h" #include "srsran/ngap/gateways/n2_connection_client_factory.h" namespace srsran { @@ -34,6 +35,9 @@ struct worker_manager_config; /// Converts and returns the given gnb application configuration to a CU-CP configuration. srs_cu_cp::cu_cp_configuration generate_cu_cp_config(const cu_cp_unit_config& cu_cfg); +/// Converts and returns the given gnb application configuration to a E2 configuration. +e2ap_configuration generate_e2_config(const cu_cp_unit_config& cu_cp); + /// Converts CU-CP configuration into N2 connection client. srs_cu_cp::n2_connection_client_config generate_n2_client_config(bool no_core, const cu_cp_unit_amf_config_item& amf_cfg, diff --git a/apps/units/cu_cp/cu_cp_unit_config.h b/apps/units/cu_cp/cu_cp_unit_config.h index fd7fbde417..c58d73abb5 100644 --- a/apps/units/cu_cp/cu_cp_unit_config.h +++ b/apps/units/cu_cp/cu_cp_unit_config.h @@ -24,6 +24,7 @@ #include "apps/units/cu_cp/cu_cp_unit_pcap_config.h" #include "cu_cp_unit_logger_config.h" +#include "srsran/e2/e2ap_configuration.h" #include "srsran/ran/nr_band.h" #include "srsran/ran/nr_cell_identity.h" #include "srsran/ran/pci.h" @@ -308,6 +309,8 @@ struct cu_cp_unit_config { std::vector qos_cfg; /// Network slice configuration. std::vector slice_cfg = {s_nssai_t{1}}; + /// E2 configuration. + e2_config e2_cfg; }; } // namespace srsran diff --git a/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp b/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp index 2a342a25b6..7fc2816890 100644 --- a/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp +++ b/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp @@ -48,6 +48,8 @@ static void configure_cli11_log_args(CLI::App& app, cu_cp_unit_logger_config& lo static void configure_cli11_pcap_args(CLI::App& app, cu_cp_unit_pcap_config& pcap_params) { + add_option(app, "--e2ap_filename", pcap_params.e2ap.filename, "E2AP PCAP file output path")->capture_default_str(); + add_option(app, "--e2ap_enable", pcap_params.e2ap.enabled, "Enable E2AP packet capture")->always_capture_default(); add_option(app, "--ngap_filename", pcap_params.ngap.filename, "N3 GTP-U PCAP file output path") ->capture_default_str(); add_option(app, "--ngap_enable", pcap_params.ngap.enabled, "Enable N3 GTP-U packet capture") @@ -539,6 +541,25 @@ static void configure_cli11_metrics_args(CLI::App& app, cu_cp_unit_metrics_confi ->capture_default_str(); } +static void configure_cli11_e2_args(CLI::App& app, e2_config& e2_params) +{ + add_option(app, "--enable_cu_e2", e2_params.enable_unit_e2, "Enable DU E2 agent")->capture_default_str(); + add_option(app, "--addr", e2_params.ip_addr, "RIC IP address")->capture_default_str(); + add_option(app, "--port", e2_params.port, "RIC port")->capture_default_str()->check(CLI::Range(20000, 40000)); + add_option(app, "--bind_addr", e2_params.bind_addr, "Local IP address to bind for RIC connection") + ->capture_default_str() + ->check(CLI::ValidIPV4); + add_option(app, "--sctp_rto_initial", e2_params.sctp_rto_initial, "SCTP initial RTO value")->capture_default_str(); + add_option(app, "--sctp_rto_min", e2_params.sctp_rto_min, "SCTP RTO min")->capture_default_str(); + add_option(app, "--sctp_rto_max", e2_params.sctp_rto_max, "SCTP RTO max")->capture_default_str(); + add_option(app, "--sctp_init_max_attempts", e2_params.sctp_init_max_attempts, "SCTP init max attempts") + ->capture_default_str(); + add_option(app, "--sctp_max_init_timeo", e2_params.sctp_max_init_timeo, "SCTP max init timeout") + ->capture_default_str(); + add_option(app, "--e2sm_kpm_enabled", e2_params.e2sm_kpm_enabled, "Enable KPM service module")->capture_default_str(); + add_option(app, "--e2sm_rc_enabled", e2_params.e2sm_rc_enabled, "Enable RC service module")->capture_default_str(); +} + void srsran::configure_cli11_with_cu_cp_unit_config_schema(CLI::App& app, cu_cp_unit_config& unit_cfg) { add_option(app, "--gnb_id", unit_cfg.gnb_id.id, "gNodeB identifier")->capture_default_str(); @@ -563,6 +584,10 @@ void srsran::configure_cli11_with_cu_cp_unit_config_schema(CLI::App& app, cu_cp_ CLI::App* metrics_subcmd = add_subcommand(app, "metrics", "Metrics configuration")->configurable(); configure_cli11_metrics_args(*metrics_subcmd, unit_cfg.metrics); + // E2 section. + CLI::App* e2_subcmd = add_subcommand(app, "e2", "E2 parameters")->configurable(); + configure_cli11_e2_args(*e2_subcmd, unit_cfg.e2_cfg); + // QoS section. auto qos_lambda = [&unit_cfg](const std::vector& values) { // Prepare the radio bearers diff --git a/apps/units/cu_cp/cu_cp_unit_config_validator.cpp b/apps/units/cu_cp/cu_cp_unit_config_validator.cpp index c47eace100..02b3eb28c0 100644 --- a/apps/units/cu_cp/cu_cp_unit_config_validator.cpp +++ b/apps/units/cu_cp/cu_cp_unit_config_validator.cpp @@ -57,6 +57,7 @@ static bool validate_mobility_appconfig(gnb_id_t gnb_id, const cu_cp_unit_mobili !report_cfg.meas_trigger_quantity_threshold_db.has_value() or !report_cfg.hysteresis_db.has_value() or !report_cfg.time_to_trigger_ms.has_value()) { fmt::print("Invalid event A1/A2/A4 measurement report configuration.\n"); + return false; } } if (report_cfg.event_triggered_report_type.value() == "a3" or @@ -64,6 +65,7 @@ static bool validate_mobility_appconfig(gnb_id_t gnb_id, const cu_cp_unit_mobili if (!report_cfg.meas_trigger_quantity.has_value() or !report_cfg.meas_trigger_quantity_offset_db.has_value() or !report_cfg.hysteresis_db.has_value() or !report_cfg.time_to_trigger_ms.has_value()) { fmt::print("Invalid event A3/A6 measurement report configuration.\n"); + return false; } } if (report_cfg.event_triggered_report_type.value() == "a5") { @@ -72,6 +74,7 @@ static bool validate_mobility_appconfig(gnb_id_t gnb_id, const cu_cp_unit_mobili !report_cfg.meas_trigger_quantity_threshold_2_db.has_value() or !report_cfg.hysteresis_db.has_value() or !report_cfg.time_to_trigger_ms.has_value()) { fmt::print("Invalid event A5 measurement report configuration.\n"); + return false; } } } diff --git a/apps/units/cu_cp/cu_cp_unit_pcap_config.h b/apps/units/cu_cp/cu_cp_unit_pcap_config.h index 93e5ee25db..1785fe042e 100644 --- a/apps/units/cu_cp/cu_cp_unit_pcap_config.h +++ b/apps/units/cu_cp/cu_cp_unit_pcap_config.h @@ -36,6 +36,10 @@ struct cu_cp_unit_pcap_config { std::string filename = "/tmp/cu_e1ap.pcap"; bool enabled = false; } e1ap; + struct { + std::string filename = "/tmp/cu_e2ap.pcap"; + bool enabled = false; + } e2ap; struct { std::string filename = "/tmp/cu_f1ap.pcap"; bool enabled = false; diff --git a/apps/units/cu_cp/cu_cp_wrapper.cpp b/apps/units/cu_cp/cu_cp_wrapper.cpp index 848e480e60..187f767013 100644 --- a/apps/units/cu_cp/cu_cp_wrapper.cpp +++ b/apps/units/cu_cp/cu_cp_wrapper.cpp @@ -26,8 +26,9 @@ using namespace srsran; using namespace srs_cu_cp; cu_cp_wrapper::cu_cp_wrapper(std::vector> n2_clients_, + std::unique_ptr e2_metric_connector_, std::unique_ptr cu_cp_) : - n2_clients(std::move(n2_clients_)), cu_cp(std::move(cu_cp_)) + n2_clients(std::move(n2_clients_)), e2_metric_connector(std::move(e2_metric_connector_)), cu_cp(std::move(cu_cp_)) { srsran_assert(cu_cp, "Invalid CU-CP object"); } diff --git a/apps/units/cu_cp/cu_cp_wrapper.h b/apps/units/cu_cp/cu_cp_wrapper.h index 88fedc796a..060b60f8b6 100644 --- a/apps/units/cu_cp/cu_cp_wrapper.h +++ b/apps/units/cu_cp/cu_cp_wrapper.h @@ -22,11 +22,17 @@ #pragma once +#include "apps/services/e2/e2_metric_connector_manager.h" #include "srsran/cu_cp/cu_cp.h" +#include "srsran/e2/e2_cu_metrics_connector.h" + #include "srsran/ngap/gateways/n2_connection_client.h" namespace srsran { +using e2_cu_metrics_connector_manager = + e2_metric_connector_manager; + /// \brief CU-CP wrapper implementation. /// /// The purpose of this wrapper is to keep the life cycle of the objects related only to the CU-CP. @@ -34,6 +40,7 @@ class cu_cp_wrapper : public srs_cu_cp::cu_cp { public: cu_cp_wrapper(std::vector> n2_clients_, + std::unique_ptr e2_metric_connector_, std::unique_ptr cu_cp_); // See interface for documentation. @@ -53,6 +60,7 @@ class cu_cp_wrapper : public srs_cu_cp::cu_cp private: std::vector> n2_clients; + std::unique_ptr e2_metric_connector; std::unique_ptr cu_cp; }; diff --git a/apps/units/cu_cp/pcap_factory.h b/apps/units/cu_cp/pcap_factory.h index 44d9a1eeb8..a362b4433b 100644 --- a/apps/units/cu_cp/pcap_factory.h +++ b/apps/units/cu_cp/pcap_factory.h @@ -32,12 +32,14 @@ struct cu_cp_dlt_pcaps { std::unique_ptr ngap; std::unique_ptr f1ap; std::unique_ptr e1ap; + std::unique_ptr e2ap; void close() { ngap.reset(); f1ap.reset(); e1ap.reset(); + e2ap.reset(); } }; @@ -52,6 +54,8 @@ inline cu_cp_dlt_pcaps create_cu_cp_dlt_pcap(const cu_cp_unit_pcap_config& pca : create_null_dlt_pcap(); pcaps.e1ap = pcap_cfg.e1ap.enabled ? create_e1ap_pcap(pcap_cfg.e1ap.filename, exec_getter.get_executor("pcap_exec")) : create_null_dlt_pcap(); + pcaps.e2ap = pcap_cfg.e2ap.enabled ? create_e2ap_pcap(pcap_cfg.e2ap.filename, exec_getter.get_executor("pcap_exec")) + : create_null_dlt_pcap(); return pcaps; } diff --git a/apps/units/flexible_du/du_high/du_high_config.h b/apps/units/flexible_du/du_high/du_high_config.h index d7ed9cbbb2..34cd361193 100644 --- a/apps/units/flexible_du/du_high/du_high_config.h +++ b/apps/units/flexible_du/du_high/du_high_config.h @@ -24,6 +24,7 @@ #include "apps/services/os_sched_affinity_manager.h" #include "srsran/adt/optional.h" +#include "srsran/e2/e2ap_configuration.h" #include "srsran/ran/band_helper.h" #include "srsran/ran/bs_channel_bandwidth.h" #include "srsran/ran/direct_current_offset.h" @@ -298,13 +299,35 @@ struct du_high_unit_pucch_config { struct du_high_unit_srs_config { /// If set, enables periodic Sound Reference Signals (SRS) for the UEs within this cell. If not present, SRS are - /// aperiodic. - /// Values: {1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}. - std::optional srs_period = std::nullopt; - /// \brief Defines the maximum number of symbols dedicated to the cell SRS resources in a slot. Values: {1,...,6}. + /// aperiodic. The given value is the SRS period in milliseconds. + /// The available values are a subset of the values in \c SRS-PeriodicityAndOffset, \c SRS-Resource \c SRS-Config, + /// TS 38.331, converted to millisecond. + /// Values: {1, 2, 2.5, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}. + std::optional srs_period_ms = std::nullopt; + /// \brief Defines the maximum number of symbols dedicated to (all) the cell SRS resources in a slot. /// This is the space that the GNB reserves for all the cell SRS resources in the UL slots, not to be confused with - /// the symbols per SRS resource configured in the UE dedicated configuration. - unsigned max_nof_symbols_per_slot = 2U; + /// the symbols per SRS resource configured in the UE dedicated configuration. Values: {1,...,6}. + unsigned max_nof_symbols_per_slot = 2; + /// Defines the number of symbols per SRS resource as per \c nrofSymbols, \c resourceMapping, \c SRS-Resource \c + /// SRS-Config, TS 38.331. Values: {1, 2, 4}. + unsigned nof_symbols = 1; + /// \c Transmission comb number, \c transmissionComb, \c SRS-Resource \c SRS-Config, TS 38.331. Values: {2, 4}. + unsigned tx_comb = 4; + /// Defines the Cyclic Shift (CS) reuse factor for the SRS resources. + /// \remark With 2 or 4 antenna ports, different cyclic shifts are used by the different antennas. This parameter + /// defines how many UEs can be multiplexed in the same symbols and RBs by exploiting different cyclic shifts. + /// Values: {no_cyclic_shift, two, four} for 2 UL antenna ports and tx_comb == 2. + /// Values: {no_cyclic_shift, two, three, four, six} for 2 UL antenna ports and tx_comb == 4. + /// Values: {no_cyclic_shift, two} for 4 UL antenna ports and tx_comb == 2. + /// Values: {no_cyclic_shift, three} for 4 UL antenna ports and tx_comb == 4. + /// Refer to Section 6.4.1.4.2, TS 38.211 for the definition of "Cyclic Shift". + unsigned cyclic_shift_reuse_factor = 1; + /// Defines the reuse of the SRS sequence ID for different UEs within the same cell. + /// \remark The goal of the SRS sequence ID would be to reduce the inter-cell interference. However, if the cell is + /// not in a dense multi-cell environment, we can reuse different sequence ID for different cell UEs. + /// Values: {1, 2, 3, 5, 6, 10, 15, 30}. + /// Refer to Section 6.4.1.4.2, TS 38.211 for the definition of "sequenceId". + unsigned sequence_id_reuse_factor = 1; }; /// Parameters that are used to initialize or build the \c PhysicalCellGroupConfig, TS 38.331. @@ -798,32 +821,6 @@ struct du_high_unit_qos_config { du_high_unit_mac_lc_config mac; }; -/// E2 Agent configuration. -struct du_high_unit_e2_config { - /// Whether to enable DU E2 agent. - bool enable_du_e2 = false; - /// RIC IP address. - std::string ip_addr = "127.0.0.1"; - /// RIC port. - uint16_t port = 36421; - /// Local IP address to bind for RIC connection. - std::string bind_addr = "127.0.0.1"; - /// SCTP initial RTO value for RIC connection. - int sctp_rto_initial = 120; - /// SCTP RTO min for RIC connection. - int sctp_rto_min = 120; - /// SCTP RTO max for RIC connection. - int sctp_rto_max = 500; - /// SCTP init max attempts for RIC connection. - int sctp_init_max_attempts = 3; - /// SCTP max init timeout for RIC connection. - int sctp_max_init_timeo = 500; - /// Whether to enable KPM service module. - bool e2sm_kpm_enabled = false; - /// Whether to enable RC service module. - bool e2sm_rc_enabled = false; -}; - /// DU high configuration. struct du_high_unit_config { bool warn_on_drop = false; @@ -852,7 +849,7 @@ struct du_high_unit_config { /// SRB configuration. std::map srb_cfg; /// E2 configuration. - du_high_unit_e2_config e2_cfg; + e2_config e2_cfg; /// Returns true if testmode is enabled, false otherwise. bool is_testmode_enabled() const { return test_mode_cfg.test_ue.rnti != rnti_t::INVALID_RNTI; } diff --git a/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp b/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp index 6c3d267eac..58f571f51a 100644 --- a/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp @@ -910,6 +910,57 @@ static void configure_cli11_pucch_args(CLI::App& app, du_high_unit_pucch_config& ->capture_default_str(); } +static void configure_cli11_srs_args(CLI::App& app, du_high_unit_srs_config& srs_params) +{ + add_option(app, + "--srs_period_ms", + srs_params.srs_period_ms, + "Enable periodic SRS with period in ms. The SRS period needs to be compatible with the subcarrier spacing") + ->capture_default_str() + ->check(CLI::IsMember({1.0F, + 2.0F, + 2.5F, + 4.0F, + 5.0F, + 8.0F, + 10.0F, + 16.0F, + 20.0F, + 32.0F, + 40.0F, + 64.0F, + 80.0F, + 160.0F, + 320.0F, + 640.0F, + 1280.0F, + 2560.0F})); + add_option(app, + "--srs_max_nof_sym_per_slot", + srs_params.max_nof_symbols_per_slot, + "Number of symbols for UL slot that are reserved for the SRS cell resources") + ->capture_default_str() + ->check(CLI::Range(1, 6)); + add_option(app, "--srs_nof_sym_per_resource", srs_params.nof_symbols, "Number of symbols per SRS resource") + ->capture_default_str() + ->check(CLI::IsMember({1, 2, 4})); + add_option(app, "--srs_tx_comb", srs_params.tx_comb, "SRS TX comb size") + ->capture_default_str() + ->check(CLI::IsMember({2, 4})); + add_option(app, + "--srs_cyclic_shift_reuse", + srs_params.cyclic_shift_reuse_factor, + "SRS cyclic shift reuse factor. It needs to be compatible with the TX comb and number of UL antenna ports") + ->capture_default_str() + ->check(CLI::IsMember({1, 2, 3, 4, 6})); + add_option(app, + "--srs_sequence_id_reuse", + srs_params.sequence_id_reuse_factor, + "Enable the reuse of SRS sequence id with the set reuse factor") + ->capture_default_str() + ->check(CLI::IsMember({1, 2, 3, 5, 6, 10, 15, 30})); +} + static void configure_cli11_si_sched_info(CLI::App& app, du_high_unit_sib_config::si_sched_info_config& si_sched_info) { add_option(app, "--si_period", si_sched_info.si_period_rf, "SI message scheduling period in radio frames") @@ -1233,10 +1284,14 @@ static void configure_cli11_common_cell_args(CLI::App& app, du_high_unit_base_ce CLI::App* pusch_subcmd = add_subcommand(app, "pusch", "PUSCH parameters"); configure_cli11_pusch_args(*pusch_subcmd, cell_params.pusch_cfg); - // PUSCH configuration. + // PUCCH configuration. CLI::App* pucch_subcmd = add_subcommand(app, "pucch", "PUCCH parameters"); configure_cli11_pucch_args(*pucch_subcmd, cell_params.pucch_cfg); + // SRS configuration. + CLI::App* srs_subcmd = add_subcommand(app, "srs", "SRS parameters"); + configure_cli11_srs_args(*srs_subcmd, cell_params.srs_cfg); + // PRACH configuration. CLI::App* prach_subcmd = add_subcommand(app, "prach", "PRACH parameters"); configure_cli11_prach_args(*prach_subcmd, cell_params.prach_cfg); @@ -1585,9 +1640,9 @@ static void configure_cli11_qos_args(CLI::App& app, du_high_unit_qos_config& qos app.needs(mac_subcmd); } -static void configure_cli11_e2_args(CLI::App& app, du_high_unit_e2_config& e2_params) +static void configure_cli11_e2_args(CLI::App& app, e2_config& e2_params) { - add_option(app, "--enable_du_e2", e2_params.enable_du_e2, "Enable DU E2 agent")->capture_default_str(); + add_option(app, "--enable_du_e2", e2_params.enable_unit_e2, "Enable DU E2 agent")->capture_default_str(); add_option(app, "--addr", e2_params.ip_addr, "RIC IP address")->capture_default_str(); add_option(app, "--port", e2_params.port, "RIC port")->check(CLI::Range(20000, 40000))->capture_default_str(); add_option(app, "--bind_addr", e2_params.bind_addr, "Local IP address to bind for RIC connection") diff --git a/apps/units/flexible_du/du_high/du_high_config_translators.cpp b/apps/units/flexible_du/du_high/du_high_config_translators.cpp index bc66f224c4..cfa92f29b2 100644 --- a/apps/units/flexible_du/du_high/du_high_config_translators.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_translators.cpp @@ -180,8 +180,13 @@ static void fill_csi_resources(serving_cell_config& out_cell, const du_high_unit // [Implementation-defined] The default CSI symbols are in symbols 4 and 8, the DM-RS for PDSCH might collide in // symbol index 8 when the number of DM-RS additional positions is 3. if (uint_to_dmrs_additional_positions(cell_cfg.pdsch_cfg.dmrs_add_pos) == dmrs_additional_positions::pos3) { - csi_params.csi_ofdm_symbol_index = 9; - csi_params.tracking_csi_ofdm_symbol_indexes = {4, 9, 4, 9}; + csi_params.csi_ofdm_symbol_index = 9; + // As per TS 38.214, clause 5.1.6.1.1, following time-domain locations of the two CSI-RS resources in a slot, or of + // the four CSI-RS resources in two consecutive slots are allowed: + // {4,8}, {5,9}, or {6,10} for frequency range 1 and frequency range 2. + // NOTE: As per TS 38.211, table 7.4.1.1.2-3, PDSCH DM-RS time-domain positions for single-symbol DM-RS + // corresponding to ld >= 12 and dmrs-AdditionalPosition pos3 are l0, 5, 8, 11. + csi_params.tracking_csi_ofdm_symbol_indexes = {6, 10, 6, 10}; } if (cell_cfg.tdd_ul_dl_cfg.has_value()) { @@ -230,8 +235,6 @@ static void fill_csi_resources(serving_cell_config& out_cell, const du_high_unit std::vector srsran::generate_du_cell_config(const du_high_unit_config& config) { - srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB", false); - std::vector out_cfg; out_cfg.reserve(config.cells_cfg.size()); @@ -557,8 +560,10 @@ std::vector srsran::generate_du_cell_config(const du_hig // Parameters for SRS-Config. srs_du::srs_builder_params& du_srs_cfg = out_cell.srs_cfg; const du_high_unit_srs_config& user_srs_cfg = base_cell.srs_cfg; - if (user_srs_cfg.srs_period.has_value()) { - du_srs_cfg.srs_period.emplace(static_cast(*user_srs_cfg.srs_period)); + if (user_srs_cfg.srs_period_ms.has_value()) { + const unsigned srs_period_slots = static_cast( + static_cast(get_nof_slots_per_subframe(base_cell.common_scs)) * user_srs_cfg.srs_period_ms.value()); + du_srs_cfg.srs_period.emplace(static_cast(srs_period_slots)); } du_srs_cfg.max_nof_symbols = user_srs_cfg.max_nof_symbols_per_slot; @@ -641,8 +646,16 @@ std::vector srsran::generate_du_cell_config(const du_hig base_cell.csi_cfg.csi_rs_enabled ? std::optional{base_cell.csi_cfg.csi_rs_period_msec} : std::nullopt); - // The maximum number of symbols for cell PUCCH resources is computed based on the SRS configuration. + // The maximum number of symbols for cell PUCCH resources is computed based on the SRS configuration, but only if + // the SRS are periodic. The aperiodic SRS resources are not currently supported and used only for the UE to accept + // the configuration; therefore, the maximum number of symbols for PUCCH resources is computed only for periodic + // SRS. du_pucch_cfg.max_nof_symbols = config_helpers::compute_max_nof_pucch_symbols(du_srs_cfg); + if (user_srs_cfg.srs_period_ms.has_value() and + std::holds_alternative(du_pucch_cfg.f0_or_f1_params)) { + auto& f1_params = std::get(du_pucch_cfg.f0_or_f1_params); + f1_params.nof_symbols = std::min(du_pucch_cfg.max_nof_symbols.to_uint(), f1_params.nof_symbols.to_uint()); + } if (update_msg1_frequency_start) { rach_cfg.rach_cfg_generic.msg1_frequency_start = config_helpers::compute_prach_frequency_start( du_pucch_cfg, out_cell.ul_cfg_common.init_ul_bwp.generic_params.crbs.length(), is_long_prach); @@ -652,21 +665,6 @@ std::vector srsran::generate_du_cell_config(const du_hig std::vector cell_plmns{base_cell.plmn}; out_cell.rrm_policy_members = generate_du_slicing_rrm_policy_config(cell_plmns, base_cell.slice_cfg, nof_crbs); - logger.info( - "SSB derived parameters for cell: {}, band: {}, dl_arfcn:{}, crbs: {} scs:{}, ssb_scs:{}:\n\t - SSB offset " - "pointA:{} \n\t - k_SSB:{} \n\t - SSB arfcn:{} \n\t - Coreset index:{} \n\t - Searchspace index:{}", - base_cell.pci, - *param.band, - base_cell.dl_f_ref_arfcn, - nof_crbs, - to_string(base_cell.common_scs), - to_string(out_cfg.back().ssb_cfg.scs), - ssb_freq_loc->offset_to_point_A.to_uint(), - ssb_freq_loc->k_ssb.to_uint(), - ssb_freq_loc->ssb_arfcn, - ssb_freq_loc->coreset0_idx, - ssb_freq_loc->searchspace0_idx); - error_type error = is_du_cell_config_valid(out_cfg.back()); if (!error) { report_error("Invalid configuration DU cell detected.\n> {}\n", error.error()); diff --git a/apps/units/flexible_du/du_high/du_high_config_validator.cpp b/apps/units/flexible_du/du_high/du_high_config_validator.cpp index 531952f411..11ef3ac7b6 100644 --- a/apps/units/flexible_du/du_high/du_high_config_validator.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_validator.cpp @@ -458,6 +458,67 @@ static bool validate_pucch_cell_unit_config(const du_high_unit_base_cell_config& return true; } +static bool validate_srs_cell_unit_config(const du_high_unit_srs_config& config, + subcarrier_spacing scs_common, + unsigned nof_ul_ports) +{ + if (config.srs_period_ms.has_value()) { + const auto srs_period_slots = + static_cast(get_nof_slots_per_subframe(scs_common) * config.srs_period_ms.value()); + + // Check that the SR period in milliseconds leads to an integer number of slots. + if (static_cast(get_nof_slots_per_subframe(scs_common) * config.srs_period_ms.value()) != + static_cast(srs_period_slots)) { + fmt::print( + "SRS period (i.e., {}ms) times the number of slots per subframe (i.e., {}) must be an integer number of " + "slots\n", + config.srs_period_ms.has_value(), + get_nof_slots_per_subframe(scs_common)); + return false; + } + + if (scs_common == srsran::subcarrier_spacing::kHz30 and config.srs_period_ms.value() > 1280) { + fmt::print("With 30kHz SCS the maximum SRS period is 1280ms\n"); + return false; + } + } + + if (config.nof_symbols > config.max_nof_symbols_per_slot) { + fmt::print("The number of symbols per SRS resource ({}) should be less than or equal to the maximum number of " + "SRS symbols per slot" + "({})\n", + config.nof_symbols, + config.max_nof_symbols_per_slot); + return false; + } + + if (config.tx_comb == 2U) { + if (nof_ul_ports == 2 and (config.cyclic_shift_reuse_factor == 3 or config.cyclic_shift_reuse_factor == 6)) { + fmt::print("With TX comb n2 and 2 UL antenna ports, valid cyclic-reuse-factor values are 1, 2, 4\n", + config.nof_symbols, + config.max_nof_symbols_per_slot); + return false; + } + if (nof_ul_ports == 4 and (config.cyclic_shift_reuse_factor == 3 or config.cyclic_shift_reuse_factor == 4 or + config.cyclic_shift_reuse_factor == 6)) { + fmt::print("With TX comb n2 and 4 UL antenna ports, valid cyclic-reuse-factor values are 1, 2\n", + config.nof_symbols, + config.max_nof_symbols_per_slot); + return false; + } + } else { + if (nof_ul_ports == 4 and (config.cyclic_shift_reuse_factor == 2 or config.cyclic_shift_reuse_factor == 4 or + config.cyclic_shift_reuse_factor == 6)) { + fmt::print("With TX comb n4 and 4 UL antenna ports, valid cyclic-reuse-factor values are 1, 3\n", + config.nof_symbols, + config.max_nof_symbols_per_slot); + return false; + } + } + + return true; +} + /// Validates the given PUCCH cell application configuration. Returns true on success, otherwise false. static bool validate_ul_common_unit_config(const du_high_unit_ul_common_config& config) { @@ -803,6 +864,10 @@ static bool validate_base_cell_unit_config(const du_high_unit_base_cell_config& return false; } + if (!validate_srs_cell_unit_config(config.srs_cfg, config.common_scs, config.nof_antennas_ul)) { + return false; + } + if (!validate_ul_common_unit_config(config.ul_common_cfg)) { return false; } diff --git a/apps/units/flexible_du/du_high/du_high_config_yaml_writer.cpp b/apps/units/flexible_du/du_high/du_high_config_yaml_writer.cpp index de51c7c2d8..68778dd912 100644 --- a/apps/units/flexible_du/du_high/du_high_config_yaml_writer.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_yaml_writer.cpp @@ -747,9 +747,9 @@ static YAML::Node build_du_high_testmode_section(const du_high_unit_test_mode_co return node; } -static void fill_du_high_e2_section(YAML::Node node, const du_high_unit_e2_config& config) +static void fill_du_high_e2_section(YAML::Node node, const e2_config& config) { - node["enable_du_e2"] = config.enable_du_e2; + node["enable_du_e2"] = config.enable_unit_e2; node["addr"] = config.ip_addr; node["port"] = config.port; node["bind_addr"] = config.bind_addr; diff --git a/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.cpp b/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.cpp index 4a2552b915..0b8a1e2857 100644 --- a/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.cpp +++ b/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.cpp @@ -21,8 +21,7 @@ */ #include "du_high_wrapper_config_helper.h" - -#include "apps/services/e2_metric_connector_manager.h" +#include "apps/services/e2/e2_metric_connector_manager.h" #include "du_high_commands.h" #include "du_high_config.h" #include "du_high_config_translators.h" @@ -31,11 +30,14 @@ #include "metrics/du_high_scheduler_cell_metrics_consumers.h" #include "metrics/du_high_scheduler_cell_metrics_producer.h" #include "srsran/du/du_high/du_high_wrapper_factory.h" +#include "srsran/e2/e2_du_metrics_connector.h" using namespace srsran; void srsran::announce_du_high_cells(const du_high_unit_config& du_high_unit_cfg) { + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB", false); + // Generate DU cells. auto cells = generate_du_cell_config(du_high_unit_cfg); @@ -50,6 +52,21 @@ void srsran::announce_du_high_cells(const du_high_unit_config& du_high_unit_cfg) srsran::band_helper::nr_arfcn_to_freq(cell.dl_carrier.arfcn_f_ref) / 1e6, cell.dl_cfg_common.freq_info_dl.absolute_frequency_ssb, srsran::band_helper::nr_arfcn_to_freq(cell.ul_carrier.arfcn_f_ref) / 1e6); + + logger.info( + "SSB derived parameters for cell: {}, band: {}, dl_arfcn:{}, nof_crbs: {} scs:{}, ssb_scs:{}:\n\t - SSB offset " + "pointA:{} \n\t - k_SSB:{} \n\t - SSB arfcn:{} \n\t - Coreset index:{} \n\t - Searchspace index:{}", + cell.pci, + cell.dl_carrier.band, + cell.dl_carrier.arfcn_f_ref, + cell.dl_cfg_common.init_dl_bwp.generic_params.crbs.length(), + to_string(cell.dl_cfg_common.init_dl_bwp.generic_params.scs), + to_string(cell.ssb_cfg.scs), + cell.ssb_cfg.offset_to_point_A.to_uint(), + cell.ssb_cfg.k_ssb.to_uint(), + cell.dl_cfg_common.freq_info_dl.absolute_frequency_ssb, + cell.coreset0_idx, + cell.searchspace0_idx); } fmt::print("\n"); @@ -91,7 +108,7 @@ build_scheduler_du_metrics(std::pair, } // Connect E2 agent to DU Scheduler UE metrics. - if (du_high_unit_cfg.e2_cfg.enable_du_e2) { + if (du_high_unit_cfg.e2_cfg.enable_unit_e2) { sched_metrics_cfg.consumers.push_back(std::make_unique(e2_notifier)); } @@ -107,7 +124,7 @@ static rlc_metrics_notifier* build_rlc_du_metrics(std::vector(rlc_json_channel)); } - if (du_high_unit_cfg.e2_cfg.enable_du_e2) { + if (du_high_unit_cfg.e2_cfg.enable_unit_e2) { rlc_metrics_cfg.consumers.push_back(std::make_unique(e2_notifier)); } @@ -141,6 +158,7 @@ static rlc_metrics_notifier* build_rlc_du_metrics(std::vector, std::vector>> + srsran::fill_du_high_wrapper_config(srs_du::du_high_wrapper_config& out_cfg, const du_high_unit_config& du_high_unit_cfg, unsigned du_idx, @@ -151,7 +169,7 @@ srsran::fill_du_high_wrapper_config(srs_du::du_high_wrapper_config& out_cfg, mac_pcap& mac_p, rlc_pcap& rlc_p, e2_connection_client& e2_client_handler, - e2_metric_connector_manager& e2_metric_connectors, + e2_du_metrics_connector_manager& e2_metric_connectors, srslog::sink& json_sink, app_services::metrics_notifier& metrics_notifier) { @@ -174,28 +192,28 @@ srsran::fill_du_high_wrapper_config(srs_du::du_high_wrapper_config& out_cfg, du_hi_cfg.mac_p = &mac_p; du_hi_cfg.rlc_p = &rlc_p; - if (du_high_unit_cfg.e2_cfg.enable_du_e2) { + if (du_high_unit_cfg.e2_cfg.enable_unit_e2) { // Connect E2 agent to RLC metric source. du_hi_cfg.e2_client = &e2_client_handler; du_hi_cfg.e2ap_config = generate_e2_config(du_high_unit_cfg); - du_hi_cfg.e2_du_metric_iface = &(e2_metric_connectors.get_e2_du_metrics_interface(du_idx)); + du_hi_cfg.e2_du_metric_iface = &(e2_metric_connectors.get_e2_metrics_interface(du_idx)); } // DU high metrics. std::pair, std::vector>> du_services_cfg; - du_hi_cfg.sched_ue_metrics_notifier = - build_scheduler_du_metrics(du_services_cfg, - metrics_notifier, - du_high_unit_cfg, - json_sink, - e2_metric_connectors.get_e2_du_metric_notifier(du_idx)); + + du_hi_cfg.sched_ue_metrics_notifier = build_scheduler_du_metrics(du_services_cfg, + metrics_notifier, + du_high_unit_cfg, + json_sink, + e2_metric_connectors.get_e2_metric_notifier(du_idx)); du_hi_cfg.rlc_metrics_notif = build_rlc_du_metrics(du_services_cfg.first, metrics_notifier, du_high_unit_cfg, json_sink, - e2_metric_connectors.get_e2_du_metric_notifier(du_idx)); + e2_metric_connectors.get_e2_metric_notifier(du_idx)); // Configure test mode if (du_high_unit_cfg.test_mode_cfg.test_ue.rnti != rnti_t::INVALID_RNTI) { diff --git a/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.h b/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.h index 6a243191d1..156b94f825 100644 --- a/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.h +++ b/apps/units/flexible_du/du_high/du_high_wrapper_config_helper.h @@ -39,18 +39,28 @@ class f1c_connection_client; class f1u_du_gateway; } // namespace srs_du +class du_high_executor_mapper; +template class e2_metric_connector_manager; +class e2_du_metrics_connector; +class e2_du_metrics_notifier; +class e2_du_metrics_interface; class e2_connection_client; class mac_pcap; class rlc_pcap; class timer_manager; struct du_high_unit_config; +struct du_high_wrapper_config; +struct du_high_wrapper_dependencies; +using e2_du_metrics_connector_manager = + e2_metric_connector_manager; -/// Set up sources for the DU high metrics. +/// Prints basic DU info in the stdout and in the GNB logs. void announce_du_high_cells(const du_high_unit_config& du_high_unit_cfg); /// Fills the given DU high wrapper configuration. std::pair, std::vector>> + fill_du_high_wrapper_config(srs_du::du_high_wrapper_config& out_cfg, const du_high_unit_config& du_high_unit_cfg, unsigned du_idx, @@ -61,7 +71,7 @@ fill_du_high_wrapper_config(srs_du::du_high_wrapper_config& out_cfg, mac_pcap& mac_p, rlc_pcap& rlc_p, e2_connection_client& e2_client_handler, - e2_metric_connector_manager& e2_metric_connectors, + e2_du_metrics_connector_manager& e2_metric_connectors, srslog::sink& json_sink, app_services::metrics_notifier& metrics_notifier); diff --git a/apps/units/flexible_du/du_high/metrics/du_high_scheduler_cell_metrics_consumers.cpp b/apps/units/flexible_du/du_high/metrics/du_high_scheduler_cell_metrics_consumers.cpp index 0e7034c1cb..6db7628c61 100644 --- a/apps/units/flexible_du/du_high/metrics/du_high_scheduler_cell_metrics_consumers.cpp +++ b/apps/units/flexible_du/du_high/metrics/du_high_scheduler_cell_metrics_consumers.cpp @@ -374,8 +374,10 @@ void scheduler_cell_metrics_consumer_log::handle_metric(const app_services::metr unsigned ul_total = ue.ul_nof_ok + ue.ul_nof_nok; if (ul_total > 0) { fmt::format_to(buffer, " ul_error_rate={}%", int((float)100 * ue.ul_nof_nok / ul_total)); + fmt::format_to(buffer, " crc_delay_ms={}", ue.ul_delay_ms); } else { fmt::format_to(buffer, " ul_error_rate={}%", 0); + fmt::format_to(buffer, " crc_delay_ms=n/a"); } fmt::format_to(buffer, " bsr={}", scaled_fmt_integer(ue.bsr, false)); if (ue.last_ta.has_value()) { diff --git a/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.cpp b/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.cpp index 6867847d04..7bc27b1a7b 100644 --- a/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.cpp +++ b/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.cpp @@ -71,19 +71,9 @@ static void generate_dl_processor_config(downlink_processor_factory_sw_config& o out_cfg.nof_concurrent_threads = upper_phy_threads_cfg.nof_dl_threads; } -void srsran::make_du_low_wrapper_config_and_dependencies( - srs_du::du_low_wrapper_config& out_cfg, - const du_low_unit_config& du_low_unit_cfg, - std::vector prach_ports, - span du_cells, - span max_puschs_per_slot, - upper_phy_rg_gateway& rg_gateway, - upper_phy_rx_symbol_request_notifier& rx_symbol_request_notifier, - worker_manager& workers, - unsigned du_id) +hal_upper_phy_config srsran::make_du_low_hal_config_and_dependencies(const du_low_unit_config& du_low_unit_cfg, + unsigned nof_cells) { - out_cfg.du_low_cfg.logger = &srslog::fetch_basic_logger("DU"); - // Initialize hardware-accelerator (only if needed). hal_upper_phy_config hal_config = {}; hal_config.hwacc_pdsch_processor = false; @@ -98,7 +88,7 @@ void srsran::make_du_low_wrapper_config_and_dependencies( hal::bbdev_hwacc_pdsch_enc_factory_configuration hwacc_pdsch_enc_cfg = {}; hal::bbdev_hwacc_pusch_dec_factory_configuration hwacc_pusch_dec_cfg = {}; std::shared_ptr harq_buffer_context = nullptr; - unsigned nof_hwacc_dus = du_cells.size(); + unsigned nof_hwacc_dus = nof_cells; // Create a bbdev accelerator factory. std::unique_ptr bbdev_acc_factory = @@ -159,11 +149,28 @@ void srsran::make_du_low_wrapper_config_and_dependencies( } #endif // DPDK_FOUND + return hal_config; +} + +void srsran::make_du_low_wrapper_config_and_dependencies( + srs_du::du_low_wrapper_config& out_cfg, + const du_low_unit_config& du_low_unit_cfg, + std::vector prach_ports, + span du_cells, + span max_puschs_per_slot, + upper_phy_rg_gateway& rg_gateway, + upper_phy_rx_symbol_request_notifier& rx_symbol_request_notifier, + worker_manager& workers, + unsigned du_id, + const hal_upper_phy_config& du_low_hal_config) +{ + out_cfg.du_low_cfg.logger = &srslog::fetch_basic_logger("DU"); + generate_du_low_wrapper_config(out_cfg, du_low_unit_cfg, du_cells, max_puschs_per_slot, du_id); // Fill the hal config. for (auto& cell : out_cfg.du_low_cfg.cells) { - cell.upper_phy_cfg.hal_config = hal_config; + cell.upper_phy_cfg.hal_config = du_low_hal_config; } // Fill the PRACH ports. diff --git a/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.h b/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.h index 1410ecbfcc..abf98dd57c 100644 --- a/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.h +++ b/apps/units/flexible_du/du_low/du_low_wrapper_config_helper.h @@ -34,6 +34,9 @@ struct du_cell_config; struct du_low_unit_config; struct worker_manager; +hal_upper_phy_config make_du_low_hal_config_and_dependencies(const du_low_unit_config& du_low_unit_cfg, + unsigned nof_cells); + void make_du_low_wrapper_config_and_dependencies(srs_du::du_low_wrapper_config& out_cfg, const du_low_unit_config& du_low_unit_cfg, std::vector prach_ports, @@ -42,6 +45,7 @@ void make_du_low_wrapper_config_and_dependencies(srs_du::du_low_wrapper_config& upper_phy_rg_gateway& rg_gateway, upper_phy_rx_symbol_request_notifier& rx_symbol_request_notifier, worker_manager& workers, - unsigned du_id); + unsigned du_id, + const hal_upper_phy_config& hal_config); } // namespace srsran diff --git a/apps/units/flexible_du/du_unit.h b/apps/units/flexible_du/du_unit.h index fe395f10e4..256fb89fd0 100644 --- a/apps/units/flexible_du/du_unit.h +++ b/apps/units/flexible_du/du_unit.h @@ -40,7 +40,11 @@ class f1c_connection_client; } // namespace srs_du class e2_connection_client; +template class e2_metric_connector_manager; +class e2_du_metrics_connector; +class e2_du_metrics_notifier; +class e2_du_metrics_interface; class mac_pcap; class rlc_pcap; class timer_manager; @@ -51,20 +55,21 @@ struct du_unit { std::unique_ptr unit; std::vector> commands; std::vector metrics; + std::unique_ptr> + e2_metric_connectors; }; /// DU unit dependencies. struct du_unit_dependencies { - worker_manager* workers = nullptr; - srs_du::f1c_connection_client* f1c_client_handler = nullptr; - srs_du::f1u_du_gateway* f1u_gw = nullptr; - timer_manager* timer_mng = nullptr; - mac_pcap* mac_p = nullptr; - rlc_pcap* rlc_p = nullptr; - e2_connection_client* e2_client_handler = nullptr; - e2_metric_connector_manager* e2_metric_connectors = nullptr; - srslog::sink* json_sink = nullptr; - app_services::metrics_notifier* metrics_notifier = nullptr; + worker_manager* workers = nullptr; + srs_du::f1c_connection_client* f1c_client_handler = nullptr; + srs_du::f1u_du_gateway* f1u_gw = nullptr; + timer_manager* timer_mng = nullptr; + mac_pcap* mac_p = nullptr; + rlc_pcap* rlc_p = nullptr; + e2_connection_client* e2_client_handler = nullptr; + srslog::sink* json_sink = nullptr; + app_services::metrics_notifier* metrics_notifier = nullptr; }; } // namespace srsran diff --git a/apps/units/flexible_du/split_7_2/helpers/ru_ofh_config.h b/apps/units/flexible_du/split_7_2/helpers/ru_ofh_config.h index cf02ac227a..0b281a8803 100644 --- a/apps/units/flexible_du/split_7_2/helpers/ru_ofh_config.h +++ b/apps/units/flexible_du/split_7_2/helpers/ru_ofh_config.h @@ -105,11 +105,11 @@ struct ru_ofh_unit_cell_config { /// V-LAN Tag control information field for U-Plane. std::optional vlan_tag_up; /// RU PRACH port. - std::vector ru_prach_port_id = {4, 5}; + std::vector ru_prach_port_id = {4}; /// RU Downlink port. - std::vector ru_dl_port_id = {0, 1}; + std::vector ru_dl_port_id = {0}; /// RU Uplink port. - std::vector ru_ul_port_id = {0, 1}; + std::vector ru_ul_port_id = {0}; }; /// RU OFH logging functionalities. diff --git a/apps/units/flexible_du/split_7_2/split_7_2_du_factory.cpp b/apps/units/flexible_du/split_7_2/split_7_2_du_factory.cpp index ac1ec10641..911bd5fe1e 100644 --- a/apps/units/flexible_du/split_7_2/split_7_2_du_factory.cpp +++ b/apps/units/flexible_du/split_7_2/split_7_2_du_factory.cpp @@ -113,6 +113,9 @@ du_unit srsran::create_split_7_2_du(const split_7_2_du_unit_config& du_72_cfg, c max_pusch_per_slot.push_back(high.cell.pusch_cfg.max_puschs_per_slot); } + // Initialize and configure the HAL. + hal_upper_phy_config du_low_hal_cfg = make_du_low_hal_config_and_dependencies(du_lo, du_cells.size()); + for (unsigned i = 0, e = du_cells.size(); i != e; ++i) { // Create one DU per cell. srs_du::du_wrapper_config du_cfg = {}; @@ -128,7 +131,8 @@ du_unit srsran::create_split_7_2_du(const split_7_2_du_unit_config& du_72_cfg, c du_impl->get_upper_ru_dl_rg_adapter(), du_impl->get_upper_ru_ul_request_adapter(), *dependencies.workers, - i); + i, + du_low_hal_cfg); auto cell_services_cfg = fill_du_high_wrapper_config(du_cfg.du_high_cfg, tmp_cfg, diff --git a/apps/units/flexible_du/split_8/split_8_du_factory.cpp b/apps/units/flexible_du/split_8/split_8_du_factory.cpp index 796952eaae..e2fb68b915 100644 --- a/apps/units/flexible_du/split_8/split_8_du_factory.cpp +++ b/apps/units/flexible_du/split_8/split_8_du_factory.cpp @@ -120,6 +120,9 @@ du_unit srsran::create_split_8_du(const split_8_du_unit_config& du_8_cfg, const tmp_cfg.cells_cfg.resize(1); tmp_cfg.cells_cfg[0] = du_hi.cells_cfg[i]; + // Initialize and configure the HAL. + hal_upper_phy_config du_low_hal_cfg = make_du_low_hal_config_and_dependencies(du_lo, du_cells.size()); + make_du_low_wrapper_config_and_dependencies(du_cfg.du_low_cfg, du_lo, {prach_ports[i]}, @@ -128,7 +131,8 @@ du_unit srsran::create_split_8_du(const split_8_du_unit_config& du_8_cfg, const du_impl->get_upper_ru_dl_rg_adapter(), du_impl->get_upper_ru_ul_request_adapter(), *dependencies.workers, - i); + i, + du_low_hal_cfg); auto cell_services_cfg = fill_du_high_wrapper_config(du_cfg.du_high_cfg, tmp_cfg, diff --git a/apps/units/flexible_du/split_dynamic/dynamic_du_application_unit_impl.cpp b/apps/units/flexible_du/split_dynamic/dynamic_du_application_unit_impl.cpp index f854c87156..42f4c9141c 100644 --- a/apps/units/flexible_du/split_dynamic/dynamic_du_application_unit_impl.cpp +++ b/apps/units/flexible_du/split_dynamic/dynamic_du_application_unit_impl.cpp @@ -21,6 +21,7 @@ */ #include "dynamic_du_application_unit_impl.h" +#include "apps/services/e2/e2_metric_connector_manager.h" #include "dynamic_du_factory.h" #include "dynamic_du_translators.h" #include "dynamic_du_unit_cli11_schema.h" diff --git a/apps/units/flexible_du/split_dynamic/dynamic_du_factory.cpp b/apps/units/flexible_du/split_dynamic/dynamic_du_factory.cpp index 455d62db06..90887f10a5 100644 --- a/apps/units/flexible_du/split_dynamic/dynamic_du_factory.cpp +++ b/apps/units/flexible_du/split_dynamic/dynamic_du_factory.cpp @@ -21,7 +21,7 @@ */ #include "dynamic_du_factory.h" -#include "apps/services/e2_metric_connector_manager.h" +#include "apps/services/e2/e2_metric_connector_manager.h" #include "apps/services/worker_manager.h" #include "apps/units/flexible_du/du_high/du_high_commands.h" #include "apps/units/flexible_du/du_high/du_high_config_translators.h" @@ -37,6 +37,7 @@ #include "dynamic_du_unit_config.h" #include "srsran/du/du_wrapper.h" #include "srsran/du/du_wrapper_factory.h" +#include "srsran/e2/e2_du_metrics_connector.h" #include "srsran/pcap/rlc_pcap.h" #include "srsran/ru/ru_dummy_factory.h" @@ -147,6 +148,9 @@ static void update_du_metrics(std::vector& flexibl du_unit srsran::create_dynamic_du(const dynamic_du_unit_config& dyn_du_cfg, const du_unit_dependencies& dependencies) { du_unit du_cmd_wrapper; + du_cmd_wrapper.e2_metric_connectors = std::make_unique< + e2_metric_connector_manager>( + dyn_du_cfg.du_high_cfg.config.cells_cfg.size()); const du_high_unit_config& du_hi = dyn_du_cfg.du_high_cfg.config; const du_low_unit_config& du_lo = dyn_du_cfg.du_low_cfg; @@ -164,6 +168,9 @@ du_unit srsran::create_dynamic_du(const dynamic_du_unit_config& dyn_du_cfg, cons max_pusch_per_slot.push_back(high.cell.pusch_cfg.max_puschs_per_slot); } + // Initialize and configure the HAL. + hal_upper_phy_config du_low_hal_cfg = make_du_low_hal_config_and_dependencies(du_lo, du_cells.size()); + for (unsigned i = 0, e = du_cells.size(); i != e; ++i) { // Create one DU per cell. srs_du::du_wrapper_config du_cfg = {}; @@ -179,7 +186,8 @@ du_unit srsran::create_dynamic_du(const dynamic_du_unit_config& dyn_du_cfg, cons du_impl->get_upper_ru_dl_rg_adapter(), du_impl->get_upper_ru_ul_request_adapter(), *dependencies.workers, - i); + i, + du_low_hal_cfg); auto cell_services_cfg = fill_du_high_wrapper_config(du_cfg.du_high_cfg, tmp_cfg, @@ -191,11 +199,11 @@ du_unit srsran::create_dynamic_du(const dynamic_du_unit_config& dyn_du_cfg, cons *dependencies.mac_p, *dependencies.rlc_p, *dependencies.e2_client_handler, - *dependencies.e2_metric_connectors, + *(du_cmd_wrapper.e2_metric_connectors), *dependencies.json_sink, *dependencies.metrics_notifier); - update_du_metrics(du_cmd_wrapper.metrics, std::move(cell_services_cfg.first), tmp_cfg.e2_cfg.enable_du_e2); + update_du_metrics(du_cmd_wrapper.metrics, std::move(cell_services_cfg.first), tmp_cfg.e2_cfg.enable_unit_e2); // Use the commands of the first cell. if (i == 0) { diff --git a/apps/units/flexible_du/split_dynamic/dynamic_du_factory.h b/apps/units/flexible_du/split_dynamic/dynamic_du_factory.h index ee0b3eedcb..2171001bdc 100644 --- a/apps/units/flexible_du/split_dynamic/dynamic_du_factory.h +++ b/apps/units/flexible_du/split_dynamic/dynamic_du_factory.h @@ -37,7 +37,6 @@ class f1u_du_gateway; struct dynamic_du_unit_config; class e2_connection_client; -class e2_metric_connector_manager; class f1ap_message_notifier; class console_helper; class metrics_log_helper; diff --git a/configs/cell_cfg_max_256_ues.yml b/configs/cell_cfg_max_256_ues.yml index 085d49ab50..5441a8d6f3 100644 --- a/configs/cell_cfg_max_256_ues.yml +++ b/configs/cell_cfg_max_256_ues.yml @@ -12,7 +12,7 @@ cell_cfg: pucch: sr_period_ms: 20 # This can be set either 20 or 40 ms. nof_ue_res_harq_per_set: 8 - nof_cell_harq_pucch_sets: 2 # Increase this if UEs are not scheduled PDSCH due to PUCCH resources starvation. + nof_cell_harq_pucch_res_sets: 2 # Increase this if UEs are not scheduled PDSCH due to PUCCH resources starvation. f0_or_f1_nof_cell_res_sr: 50 f2_nof_cell_res_csi: 50 csi: diff --git a/configs/cell_cfg_max_512_ues.yml b/configs/cell_cfg_max_512_ues.yml index 322385a6ae..71afd39b89 100644 --- a/configs/cell_cfg_max_512_ues.yml +++ b/configs/cell_cfg_max_512_ues.yml @@ -13,7 +13,7 @@ cell_cfg: pucch: sr_period_ms: 20 # This can be set either 20 or 40 ms. nof_ue_res_harq_per_set: 8 - nof_cell_harq_pucch_sets: 2 # Increase this if UEs are not scheduled PDSCH due to PUCCH resources starvation. + nof_cell_harq_pucch_res_sets: 2 # Increase this if UEs are not scheduled PDSCH due to PUCCH resources starvation. f0_or_f1_nof_cell_res_sr: 80 f2_nof_cell_res_csi: 80 csi: diff --git a/docker/Dockerfile b/docker/Dockerfile index d60f089939..d5cde5ebc4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -60,10 +60,11 @@ RUN /src/docker/scripts/build_${LIB}.sh ${LIB_VERSION} ${MARCH} ${NUM_CORES} ARG EXTRA_CMAKE_ARGS="" RUN if [ -z "$NUM_CORES" ]; then NUM_CORES=$(nproc); fi && \ LIB_UPPER=$(echo $LIB | tr '[:lower:]' '[:upper:]') && \ - export ${LIB_UPPER}_DIR="/opt/${LIB}/${LIB_VERSION}" \ + export ${LIB_UPPER}_DIR="/opt/${LIB}/${LIB_VERSION}" && \ + if [ "$LIB_UPPER" = "UHD" ]; then SPLIT="SPLIT_8"; else SPLIT="SPLIT_7_2"; fi \ && \ /src/docker/scripts/builder.sh -m "-j${NUM_CORES} install" \ - -DBUILD_TESTS=False -DENABLE_${LIB_UPPER}=On -DMARCH=${MARCH} -DCMAKE_INSTALL_PREFIX=/opt/srs \ + -DBUILD_TESTS=False -DENABLE_${LIB_UPPER}=On -DDU_SPLIT_TYPE=${SPLIT} -DMARCH=${MARCH} -DCMAKE_INSTALL_PREFIX=/opt/srs \ ${EXTRA_CMAKE_ARGS} /src \ && \ /src/docker/scripts/builder.sh -m "-j${NUM_CORES} ru_emulator" \ diff --git a/include/srsran/adt/bit_buffer.h b/include/srsran/adt/bit_buffer.h index 725cac7eab..9f09d1d30f 100644 --- a/include/srsran/adt/bit_buffer.h +++ b/include/srsran/adt/bit_buffer.h @@ -477,9 +477,9 @@ struct formatter { auto format(const srsran::bit_buffer& s, FormatContext& ctx) -> decltype(std::declval().out()) { if (mode == hexadecimal) { - return s.template to_hex_string(ctx.out()); + return s.template to_hex_string().out())>(ctx.out()); } - return s.template to_bin_string(ctx.out()); + return s.template to_bin_string().out())>(ctx.out()); } }; diff --git a/include/srsran/adt/bounded_bitset.h b/include/srsran/adt/bounded_bitset.h index 0284acd0a3..1296d876c9 100644 --- a/include/srsran/adt/bounded_bitset.h +++ b/include/srsran/adt/bounded_bitset.h @@ -1484,7 +1484,7 @@ struct formatter> { -> decltype(std::declval().out()) { if (mode == hexadecimal) { - return s.template to_string_of_hex(ctx.out(), order == reverse); + return s.template to_string_of_hex().out())>(ctx.out(), order == reverse); } if (mode == bit_positions) { @@ -1508,7 +1508,7 @@ struct formatter> { return ctx.out(); } - return s.template to_string_of_bits(ctx.out(), order == reverse); + return s.template to_string_of_bits().out())>(ctx.out(), order == reverse); } }; } // namespace fmt diff --git a/include/srsran/adt/noop_functor.h b/include/srsran/adt/noop_functor.h index 14fefd626a..cf04105f89 100644 --- a/include/srsran/adt/noop_functor.h +++ b/include/srsran/adt/noop_functor.h @@ -10,6 +10,10 @@ struct noop_operation { { // Do nothing. } + void operator()() const + { + // Do nothing. + } }; } // namespace srsran diff --git a/include/srsran/adt/slotted_array.h b/include/srsran/adt/slotted_array.h index 7850f3b646..79e46a8734 100644 --- a/include/srsran/adt/slotted_array.h +++ b/include/srsran/adt/slotted_array.h @@ -474,7 +474,7 @@ class slotted_vector /// Erase object pointed by the given iterator. Iterator must point to valid element. /// \param it container iterator - void erase(iterator it) noexcept { erase(this->extract_iterator_index(it)); } + void erase(iterator it) noexcept { erase(extract_iterator_index(it)); } /// Clear all elements of the container void clear() noexcept diff --git a/include/srsran/cu_cp/cu_cp_configuration.h b/include/srsran/cu_cp/cu_cp_configuration.h index c8ae959766..a66a2aed2e 100644 --- a/include/srsran/cu_cp/cu_cp_configuration.h +++ b/include/srsran/cu_cp/cu_cp_configuration.h @@ -25,6 +25,9 @@ #include "srsran/cu_cp/cell_meas_manager_config.h" #include "srsran/cu_cp/mobility_manager_config.h" #include "srsran/cu_cp/ue_configuration.h" +#include "srsran/e2/e2_connection_client.h" +#include "srsran/e2/e2_cu.h" +#include "srsran/e2/e2ap_configuration.h" #include "srsran/f1ap/cu_cp/f1ap_configuration.h" #include "srsran/rrc/rrc_ue_config.h" #include "srsran/support/async/async_task.h" @@ -151,6 +154,12 @@ struct cu_cp_configuration { plugin_params plugin; /// Timers, executors, and other services used by the CU-CP. service_params services; + /// E2AP configuration. + e2ap_configuration e2ap_config; + /// E2 connection client. + e2_connection_client* e2_client = nullptr; + /// E2 CU metrics interface. + e2_cu_metrics_interface* e2_cu_metric_iface = nullptr; }; } // namespace srs_cu_cp diff --git a/include/srsran/du/du_cell_config.h b/include/srsran/du/du_cell_config.h index 63c441be78..8e45ed37a7 100644 --- a/include/srsran/du/du_cell_config.h +++ b/include/srsran/du/du_cell_config.h @@ -122,7 +122,7 @@ struct srs_builder_params { /// \remark The SRS resources are always placed at the end of the slot. /// \remark As per TS 38.211, Section 6.4.1.4.1, SRS resource can only be placed in the last 6 symbols of a slot. bounded_integer max_nof_symbols = 2U; - /// \c Transmission comb number , as per TS 38.211, Section 6.4.1.4.2, or TS 38.331, "SRS-Resource". + /// \c Transmission comb number, as per TS 38.211, Section 6.4.1.4.2, or TS 38.331, "SRS-Resource". tx_comb_size tx_comb = tx_comb_size::n4; /// Defines the number of symbols per SRS resource. srs_nof_symbols nof_symbols = srs_nof_symbols::n1; diff --git a/include/srsran/du/du_high/du_high_configuration.h b/include/srsran/du/du_high/du_high_configuration.h index b02250fbe2..bc02d7babc 100644 --- a/include/srsran/du/du_high/du_high_configuration.h +++ b/include/srsran/du/du_high/du_high_configuration.h @@ -6,8 +6,8 @@ #include "srsran/du/du_high/du_qos_config.h" #include "srsran/du/du_high/du_srb_config.h" #include "srsran/du/du_high/du_test_mode_config.h" -#include "srsran/e2/e2.h" #include "srsran/e2/e2_connection_client.h" +#include "srsran/e2/e2_du.h" #include "srsran/e2/e2ap_configuration.h" #include "srsran/f1ap/du/f1ap_du.h" #include "srsran/f1ap/gateways/f1c_connection_client.h" diff --git a/include/srsran/e2/e2.h b/include/srsran/e2/e2.h index 11168a9ae3..c89e1f8224 100644 --- a/include/srsran/e2/e2.h +++ b/include/srsran/e2/e2.h @@ -30,8 +30,6 @@ #include "srsran/asn1/e2sm/e2sm_common_ies.h" #include "srsran/asn1/e2sm/e2sm_kpm_ies.h" #include "srsran/ran/lcid.h" -#include "srsran/rlc/rlc_metrics.h" -#include "srsran/scheduler/scheduler_metrics.h" #include "srsran/support/async/async_task.h" #include "srsran/support/async/eager_async_task.h" @@ -84,28 +82,6 @@ class e2_connection_manager virtual async_task start_initial_e2_setup_routine() = 0; }; -class e2_du_metrics_notifier : public scheduler_metrics_notifier, public rlc_metrics_notifier -{ -public: - virtual ~e2_du_metrics_notifier() = default; - - using rlc_metrics_notifier::report_metrics; - using scheduler_metrics_notifier::report_metrics; -}; - -class e2_du_metrics_interface -{ -public: - virtual ~e2_du_metrics_interface() = default; - /// @brief Get the metrics from the scheduler. - /// @param ue_metrics - virtual void get_metrics(scheduler_ue_metrics& ue_metrics) = 0; - - /// \brief connects e2_du_metric_provider - /// \param[in] meas_provider pointer to the e2_du_metric_provider - virtual void connect_e2_du_meas_provider(std::unique_ptr meas_provider) = 0; -}; - /// This interface is used to pack outgoing and unpack incoming E2 messages. class e2ap_packer : public e2_message_handler { diff --git a/apps/services/e2_metric_connector_manager.h b/include/srsran/e2/e2_cu.h similarity index 64% rename from apps/services/e2_metric_connector_manager.h rename to include/srsran/e2/e2_cu.h index 677b8f555e..ca70e5cd37 100644 --- a/apps/services/e2_metric_connector_manager.h +++ b/include/srsran/e2/e2_cu.h @@ -22,19 +22,23 @@ #pragma once -#include "srsran/e2/e2_du_metrics_connector.h" - +#include "e2.h" namespace srsran { -/// Manages the E2 metric connectors of the app. -class e2_metric_connector_manager +class e2_cu_metrics_notifier +{ +public: + virtual ~e2_cu_metrics_notifier() = default; +}; + +class e2_cu_metrics_interface { public: - explicit e2_metric_connector_manager(unsigned nof_cells); + virtual ~e2_cu_metrics_interface() = default; - std::vector> e2_du_metric_connectors; - e2_du_metrics_notifier& get_e2_du_metric_notifier(unsigned du_index); - e2_du_metrics_interface& get_e2_du_metrics_interface(unsigned du_index); + /// \brief connects e2_cu_metric_provider + /// \param[in] meas_provider pointer to the e2_cu_metric_provider + virtual void connect_e2_cu_meas_provider(std::unique_ptr meas_provider) = 0; }; } // namespace srsran diff --git a/include/srsran/e2/e2_cu_factory.h b/include/srsran/e2/e2_cu_factory.h new file mode 100644 index 0000000000..b8b029d304 --- /dev/null +++ b/include/srsran/e2/e2_cu_factory.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "e2_cu.h" +#include "e2_factory.h" + +namespace srsran { +/// Creates a instance of an E2 interface (with subscription manager) +std::unique_ptr create_e2_cu_entity(e2ap_configuration& e2ap_cfg_, + e2_connection_client* e2_client_, + e2_cu_metrics_interface* e2_metrics_var, + timer_factory timers_, + task_executor& e2_exec_); + +} // namespace srsran diff --git a/include/srsran/e2/e2_cu_metrics_connector.h b/include/srsran/e2/e2_cu_metrics_connector.h new file mode 100644 index 0000000000..cfe342fe91 --- /dev/null +++ b/include/srsran/e2/e2_cu_metrics_connector.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/span.h" +#include "srsran/e2/e2_cu.h" +#include + +namespace srsran { + +constexpr unsigned MAX_UE_METRICS = 10; + +/// \brief Class used to receive metrics reports from scheduler and sends them to the e2 interface. +class e2_cu_metrics_connector : public e2_cu_metrics_notifier, public e2_cu_metrics_interface +{ +public: + e2_cu_metrics_connector(); + + void connect_e2_cu_meas_provider(std::unique_ptr meas_provider) override; + +private: + std::unique_ptr e2_meas_provider; +}; +} // namespace srsran diff --git a/include/srsran/e2/e2_du.h b/include/srsran/e2/e2_du.h new file mode 100644 index 0000000000..d9e8624bd2 --- /dev/null +++ b/include/srsran/e2/e2_du.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "e2.h" +#include "srsran/rlc/rlc_metrics.h" +#include "srsran/scheduler/scheduler_metrics.h" + +namespace srsran { + +class e2_du_metrics_notifier : public scheduler_metrics_notifier, public rlc_metrics_notifier +{ +public: + virtual ~e2_du_metrics_notifier() = default; + + using rlc_metrics_notifier::report_metrics; + using scheduler_metrics_notifier::report_metrics; +}; + +class e2_du_metrics_interface +{ +public: + virtual ~e2_du_metrics_interface() = default; + + /// \brief connects e2_du_metric_provider + /// \param[in] meas_provider pointer to the e2_du_metric_provider + virtual void connect_e2_du_meas_provider(std::unique_ptr meas_provider) = 0; +}; +} // namespace srsran diff --git a/include/srsran/e2/e2_du_factory.h b/include/srsran/e2/e2_du_factory.h new file mode 100644 index 0000000000..4bc9c7c112 --- /dev/null +++ b/include/srsran/e2/e2_du_factory.h @@ -0,0 +1,40 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "e2_du.h" +#include "e2_factory.h" +#include "srsran/du/du_high/du_manager/du_configurator.h" +#include "srsran/f1ap/du/f1ap_du.h" + +namespace srsran { +/// Creates a instance of an E2 interface (with subscription manager) +std::unique_ptr create_e2_du_entity(e2ap_configuration& e2ap_cfg_, + e2_connection_client* e2_client_, + e2_du_metrics_interface* e2_metrics_var, + srs_du::f1ap_ue_id_translator* f1ap_ue_id_translator_, + srs_du::du_configurator* du_configurator_, + timer_factory timers_, + task_executor& e2_exec_); + +} // namespace srsran diff --git a/include/srsran/e2/e2_du_metrics_connector.h b/include/srsran/e2/e2_du_metrics_connector.h index 566946cd89..3fe870dceb 100644 --- a/include/srsran/e2/e2_du_metrics_connector.h +++ b/include/srsran/e2/e2_du_metrics_connector.h @@ -23,7 +23,7 @@ #pragma once #include "srsran/adt/span.h" -#include "srsran/e2/e2.h" +#include "srsran/e2/e2_du.h" #include "srsran/scheduler/scheduler_metrics.h" #include @@ -42,12 +42,9 @@ class e2_du_metrics_connector : public e2_du_metrics_notifier, public e2_du_metr void report_metrics(const rlc_metrics& metrics) override; - void get_metrics(scheduler_ue_metrics& ue_metrics) override; - void connect_e2_du_meas_provider(std::unique_ptr meas_provider) override; private: - std::deque ue_metrics_queue; std::unique_ptr e2_meas_provider; }; } // namespace srsran diff --git a/include/srsran/e2/e2_factory.h b/include/srsran/e2/e2_factory.h index 765b1a6cae..1250997aec 100644 --- a/include/srsran/e2/e2_factory.h +++ b/include/srsran/e2/e2_factory.h @@ -27,8 +27,6 @@ #include "e2ap_configuration.h" #include "e2sm/e2sm_manager.h" #include "subscription/e2_subscription.h" -#include "srsran/du/du_high/du_manager/du_configurator.h" -#include "srsran/f1ap/du/f1ap_du.h" #include "srsran/gateways/sctp_network_gateway.h" #include "srsran/pcap/dlt_pcap.h" #include "srsran/support/timers.h" @@ -51,15 +49,6 @@ std::unique_ptr create_e2_with_task_exec(e2ap_configuration& e2sm_manager& e2sm_manager_, task_executor& e2_exec_); -/// Creates a instance of an E2 interface (with subscription manager) -std::unique_ptr create_e2_entity(e2ap_configuration& e2ap_cfg_, - e2_connection_client* e2_client_, - e2_du_metrics_interface& e2_du_metrics_, - srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - srs_du::du_configurator& du_configurator_, - timer_factory timers_, - task_executor& e2_exec_); - /// Creates an instance of an E2AP ASN1 packer. std::unique_ptr create_e2ap_asn1_packer(sctp_network_gateway_data_handler& gw_, e2_message_handler& e2_, dlt_pcap& pcap_); diff --git a/include/srsran/e2/e2ap_configuration.h b/include/srsran/e2/e2ap_configuration.h index 9484a9c3a2..1029e30fdb 100644 --- a/include/srsran/e2/e2ap_configuration.h +++ b/include/srsran/e2/e2ap_configuration.h @@ -39,4 +39,29 @@ struct e2ap_configuration { bool e2sm_rc_enabled = false; }; +/// E2 Agent configuration. +struct e2_config { + /// Whether to enable E2 agent. + bool enable_unit_e2 = false; + /// RIC IP address. + std::string ip_addr = "127.0.0.1"; + /// RIC port. + uint16_t port = 36421; + /// Local IP address to bind for RIC connection. + std::string bind_addr = "127.0.0.1"; + /// SCTP initial RTO value for RIC connection. + int sctp_rto_initial = 120; + /// SCTP RTO min for RIC connection. + int sctp_rto_min = 120; + /// SCTP RTO max for RIC connection. + int sctp_rto_max = 500; + /// SCTP init max attempts for RIC connection. + int sctp_init_max_attempts = 3; + /// SCTP max init timeout for RIC connection. + int sctp_max_init_timeo = 500; + /// Whether to enable KPM service module. + bool e2sm_kpm_enabled = false; + /// Whether to enable RC service module. + bool e2sm_rc_enabled = false; +}; } // namespace srsran diff --git a/include/srsran/e2/e2sm/e2sm_kpm.h b/include/srsran/e2/e2sm/e2sm_kpm.h index ba62965208..1b07bb7912 100644 --- a/include/srsran/e2/e2sm/e2sm_kpm.h +++ b/include/srsran/e2/e2sm/e2sm_kpm.h @@ -82,17 +82,17 @@ class e2sm_kpm_meas_provider /// \brief check if cell with cell global id is supported /// \param[in] cell_global_id of the required cell /// \return Returns True if cell is present - virtual bool cell_supported(const asn1::e2sm::cgi_c& cell_global_id) = 0; + virtual bool is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) = 0; /// \brief check if UE with ueid is supported /// \param[in] ueid of the required UE /// \return Returns True if UE is present - virtual bool ue_supported(const asn1::e2sm::ue_id_c& ueid) = 0; + virtual bool is_ue_supported(const asn1::e2sm::ue_id_c& ueid) = 0; /// \brief check if a test condition is supported /// \param[in] test_cond_type /// \return Returns True if test condition is supported - virtual bool test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) = 0; + virtual bool is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) = 0; /// \brief check if a metric with labels, level and optional cell scope is supported /// \param[in] meas_type defines the metric @@ -100,10 +100,10 @@ class e2sm_kpm_meas_provider /// \param[in] level if metric can be measured at the given level /// \param[in] cell_scope if metric can be measured for a single cell /// \return Returns True if metric is supported with given labels, level and cell_scope - virtual bool metric_supported(const asn1::e2sm::meas_type_c& meas_type, - const asn1::e2sm::meas_label_s& label, - const e2sm_kpm_metric_level_enum level, - const bool& cell_scope) = 0; + virtual bool is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) = 0; /// \brief collected UE ids of the UEs matching the requested conditions /// \param[in] matching_cond_list defines the conditions to be satisfied diff --git a/include/srsran/f1ap/du/f1ap_du_factory.h b/include/srsran/f1ap/du/f1ap_du_factory.h index e33eb426dd..88657d3e88 100644 --- a/include/srsran/f1ap/du/f1ap_du_factory.h +++ b/include/srsran/f1ap/du/f1ap_du_factory.h @@ -6,6 +6,7 @@ namespace srsran { class du_high_ue_executor_mapper; +class timer_manager; namespace srs_du { @@ -16,7 +17,8 @@ std::unique_ptr create_f1ap(f1c_connection_client& f1c_client_hand f1ap_du_configurator& du_mng, task_executor& ctrl_exec, du_high_ue_executor_mapper& ue_exec_mapper, - f1ap_du_paging_notifier& paging_notifier); + f1ap_du_paging_notifier& paging_notifier, + srsran::timer_manager& timers); } // namespace srs_du } // namespace srsran diff --git a/include/srsran/f1ap/du/f1c_bearer.h b/include/srsran/f1ap/du/f1c_bearer.h index 0aa9553405..f83ca94e55 100644 --- a/include/srsran/f1ap/du/f1c_bearer.h +++ b/include/srsran/f1ap/du/f1c_bearer.h @@ -89,10 +89,5 @@ class f1c_rx_pdu_handler class f1c_bearer : public f1c_tx_sdu_handler, public f1c_tx_delivery_handler, public f1c_rx_pdu_handler {}; -std::unique_ptr create_f1ap(f1c_connection_client& f1c_client_handler, - f1ap_du_configurator& du_mng, - task_executor& ctrl_exec, - du_high_ue_executor_mapper& ue_exec_mapper, - f1ap_du_paging_notifier& paging_notifier); } // namespace srs_du } // namespace srsran diff --git a/include/srsran/fapi/message_builders.h b/include/srsran/fapi/message_builders.h index 955d14b426..3c4f57e751 100644 --- a/include/srsran/fapi/message_builders.h +++ b/include/srsran/fapi/message_builders.h @@ -1674,7 +1674,7 @@ class srs_indication_pdu_builder /// \note These parameters are specified in SCF-222 v4.0 Section 3.4.10 Table 3-132. srs_indication_pdu_builder& set_codebook_report_matrix(const srs_channel_matrix& matrix) { - pdu.srs_usage = srs_usage_mode::codebook; + pdu.usage = srs_usage::codebook; pdu.report_type = 1; pdu.matrix = matrix; diff --git a/include/srsran/fapi/messages.h b/include/srsran/fapi/messages.h index b2a0c9258c..441d0e4e70 100644 --- a/include/srsran/fapi/messages.h +++ b/include/srsran/fapi/messages.h @@ -793,14 +793,12 @@ struct ul_tti_request_message : public base_message { /// Maximum number of supported UL PDU types in this release. static constexpr unsigned MAX_NUM_UL_TYPES = 6; - /// Maximum number of supported UL PDUs in this message. - static constexpr unsigned MAX_NUM_UL_PDUS = 128; - - uint16_t sfn; - uint16_t slot; - std::array num_pdus_of_each_type; - uint16_t num_groups; - static_vector pdus; + + uint16_t sfn; + uint16_t slot; + std::array num_pdus_of_each_type; + uint16_t num_groups; + static_vector pdus; //: TODO: groups array }; @@ -1048,13 +1046,9 @@ struct uci_indication_pdu { /// UCI indication message. struct uci_indication_message : public base_message { - /// Maximum number of supported UCI PDUs in this message. - //: TODO: shared with ul_dci_request_message - static constexpr unsigned MAX_NUM_UCI_PDUS = 128; - - uint16_t sfn; - uint16_t slot; - static_vector pdus; + uint16_t sfn; + uint16_t slot; + static_vector pdus; }; /// Encodes the PRGs. @@ -1128,16 +1122,15 @@ struct srs_channel_svd_representation { std::array svd_prg; }; -/// Encodes the usage of the srs. -enum class srs_usage_mode : uint8_t { beam_management, codebook, non_codebook, antenna_switching, reserved }; - /// SRS indication pdu. struct srs_indication_pdu { - uint32_t handle; - rnti_t rnti; - uint16_t timing_advance_offset; - int16_t timing_advance_offset_ns; - srs_usage_mode srs_usage; + uint32_t handle; + rnti_t rnti; + uint16_t timing_advance_offset; + int16_t timing_advance_offset_ns; + /// \remark The enum doesn't contain the \c reserved value defined in the FAPI spec. This is because the value is + /// currently not used anywhere. + srs_usage usage; uint8_t report_type; tlv_info report; srs_channel_matrix matrix; @@ -1145,13 +1138,10 @@ struct srs_indication_pdu { /// SRS indication message. struct srs_indication_message : public base_message { - /// Maximum number of supported SRS PDUs in this message. - static constexpr unsigned MAX_NUM_SRS_PDUS = 32; - - uint16_t sfn; - uint16_t slot; - uint16_t control_length; - static_vector pdus; + uint16_t sfn; + uint16_t slot; + uint16_t control_length; + static_vector pdus; }; /// RACH indication pdu preamble. diff --git a/include/srsran/mac/mac_cell_control_information_handler.h b/include/srsran/mac/mac_cell_control_information_handler.h index d152dcf22c..87ad42d152 100644 --- a/include/srsran/mac/mac_cell_control_information_handler.h +++ b/include/srsran/mac/mac_cell_control_information_handler.h @@ -29,6 +29,8 @@ #include "srsran/ran/rnti.h" #include "srsran/ran/slot_pdu_capacity_constants.h" #include "srsran/ran/slot_point.h" +#include "srsran/ran/srs/srs_channel_matrix.h" +#include "srsran/ran/srs/srs_configuration.h" #include "srsran/ran/uci/uci_constants.h" #include "srsran/ran/uci/uci_mapping.h" #include @@ -252,6 +254,31 @@ struct mac_uci_indication_message { static_vector ucis; }; +struct mac_srs_pdu { + mac_srs_pdu() = default; + mac_srs_pdu(rnti_t rnti_, std::optional ta, srs_channel_matrix& matrix) : + rnti(rnti_), time_advance_offset(ta), channel_matrix(matrix) + { + } + + /// RNTI value corresponding to the UE that generated this PDU. + rnti_t rnti; + /// Timing Advance Offset measured for the UE. + std::optional time_advance_offset; + /// Channel matrix reported in the SRS codebook-based report. + /// \remark This Channel matrix assumes that the SRS usage is codebook-based, which is the only usage currently + /// supported. + srs_channel_matrix channel_matrix; +}; + +/// List of SRS indication PDUs for a given slot. +struct mac_srs_indication_message { + /// Slot point corresponding to the reception of this indication. + slot_point sl_rx; + /// List of SRS PDUs carried in this indication. + static_vector srss; +}; + /// Interface to handle feedback information from the PHY. class mac_cell_control_information_handler { @@ -267,6 +294,11 @@ class mac_cell_control_information_handler /// /// The UCI indication can be received on both PUSCH and PUCCH. There can be more than one UCI indication per slot. virtual void handle_uci(const mac_uci_indication_message& msg) = 0; + + /// \brief Handles an SRS indication. + /// + /// There can be more than one SRS indication per slot. + virtual void handle_srs(const mac_srs_indication_message& msg) = 0; }; } // namespace srsran diff --git a/include/srsran/mac/mac_config.h b/include/srsran/mac/mac_config.h index e60d1233a5..92991d28e3 100644 --- a/include/srsran/mac/mac_config.h +++ b/include/srsran/mac/mac_config.h @@ -32,6 +32,8 @@ namespace srsran { +class timer_manager; + /// \brief Implementation-specific parameters used to tune MAC operation. struct mac_expert_config { /// Initial C-RNTI to assign to created UEs. @@ -60,6 +62,7 @@ struct mac_config { // Parameters passed to MAC scheduler. scheduler_expert_config sched_cfg; scheduler_metrics_notifier& metric_notifier; + timer_manager& timers; }; } // namespace srsran diff --git a/include/srsran/ran/slot_pdu_capacity_constants.h b/include/srsran/ran/slot_pdu_capacity_constants.h index 87e6f9b4e7..3b96220b7e 100644 --- a/include/srsran/ran/slot_pdu_capacity_constants.h +++ b/include/srsran/ran/slot_pdu_capacity_constants.h @@ -97,6 +97,9 @@ static constexpr size_t MAX_UL_PDUS_PER_SLOT = /// [Implementation defined] Maximum number of UCI PDUS per UCI indication. static constexpr size_t MAX_UCI_PDUS_PER_UCI_IND = MAX_PUCCH_PDUS_PER_SLOT; +/// [Implementation defined] Maximum number of SRS PDUS per SRS indication. +static constexpr size_t MAX_SRS_PDUS_PER_SRS_IND = MAX_SRS_PDUS_PER_SLOT; + /// [Implementation defined] Maximum number of HARQ VALUES per HARQ PDU. static constexpr size_t MAX_HARQ_VALUES_PER_HARQ_PDU = 8; diff --git a/include/srsran/ran/srs/srs_configuration.h b/include/srsran/ran/srs/srs_configuration.h index 343a227998..9688316813 100644 --- a/include/srsran/ran/srs/srs_configuration.h +++ b/include/srsran/ran/srs/srs_configuration.h @@ -41,6 +41,10 @@ enum class srs_group_or_sequence_hopping { neither, groupHopping, sequenceHoppin /// \brief \c resourceType, as per TS 38.331, "SRS-Resource". enum class srs_resource_type { aperiodic, semi_persistent, periodic }; +/// \brief SRS resource usage. +/// \remark See TS 38.214, clause 6.2.1. +enum class srs_usage : uint8_t { beam_management, codebook, non_codebook, antenna_switching }; + /// Convert SRS resource type to string. inline std::string_view to_string(srs_resource_type res_type) { @@ -168,10 +172,6 @@ struct srs_config { bool operator!=(const periodic_resource_type& rhs) const { return !(rhs == *this); } }; - /// \brief SRS resource usage. - /// \remark See TS 38.214, clause 6.2.1. - enum class usage { beam_management, codebook, non_codebook, antenna_switching }; - enum class srs_pwr_ctrl_adjustment_states { same_as_fci2, separate_closed_loop, not_set }; /// The ID of this resource set. It is unique in the context of the BWP in which the parent SRS-Config is defined. @@ -186,7 +186,7 @@ struct srs_config { std::variant res_type; /// Indicates if the SRS resource set is used for beam management, codebook based or non-codebook based /// transmission or antenna switching. - usage srs_res_set_usage; + srs_usage srs_res_set_usage; /// When the field is not set the UE applies the value 1. alpha srs_pwr_ctrl_alpha{alpha::not_set}; /// P0 value for SRS power control. The value is in dBm. Only even values (step size 2) are allowed. Values diff --git a/include/srsran/scheduler/scheduler_feedback_handler.h b/include/srsran/scheduler/scheduler_feedback_handler.h index 5437a60199..86325e9433 100644 --- a/include/srsran/scheduler/scheduler_feedback_handler.h +++ b/include/srsran/scheduler/scheduler_feedback_handler.h @@ -33,6 +33,7 @@ #include "srsran/ran/rnti.h" #include "srsran/ran/slot_pdu_capacity_constants.h" #include "srsran/ran/slot_point.h" +#include "srsran/ran/srs/srs_channel_matrix.h" #include "srsran/ran/uci/uci_constants.h" #include "srsran/scheduler/harq_id.h" #include @@ -141,6 +142,37 @@ struct uci_indication { uci_pdu_list ucis; }; +struct srs_indication { + struct srs_indication_pdu { + srs_indication_pdu(const du_ue_index_t ue_idx, + const rnti_t ue_rnti_, + std::optional ta, + const srs_channel_matrix& matrix) : + ue_index(ue_idx), rnti(ue_rnti_), time_advance_offset(ta), channel_matrix(matrix) + { + } + + du_ue_index_t ue_index; + /// RNTI value corresponding to the UE that generated this PDU. + rnti_t rnti; + /// Timing Advance Offset measured for the UE. + std::optional time_advance_offset; + /// Channel matrix reported in the SRS codebook-based report. + /// \remark This Channel matrix assumes that the SRS usage is codebook-based, which is the only usage currently + /// supported. + srs_channel_matrix channel_matrix; + }; + + using srs_pdu_list = static_vector; + + // Note: user-defined ctor to avoid zero-initialization of srs_pdu_list. + srs_indication() {} + + du_cell_index_t cell_index; + slot_point slot_rx; + srs_pdu_list srss; +}; + struct dl_mac_ce_indication { du_ue_index_t ue_index; lcid_dl_sch_t ce_lcid; @@ -161,6 +193,7 @@ class scheduler_feedback_handler virtual void handle_ul_bsr_indication(const ul_bsr_indication_message& bsr) = 0; virtual void handle_crc_indication(const ul_crc_indication& crc) = 0; virtual void handle_uci_indication(const uci_indication& uci) = 0; + virtual void handle_srs_indication(const srs_indication& srs) = 0; /// \brief Handles PHR indication sent by MAC. /// diff --git a/include/srsran/scheduler/scheduler_metrics.h b/include/srsran/scheduler/scheduler_metrics.h index f387706c62..f043dc0d69 100644 --- a/include/srsran/scheduler/scheduler_metrics.h +++ b/include/srsran/scheduler/scheduler_metrics.h @@ -84,6 +84,8 @@ struct scheduler_cell_metrics { unsigned nof_dl_slots = 0; /// Number of full uplink slots. unsigned nof_ul_slots = 0; + /// Number of PRACH preambles detected. + unsigned nof_prach_preambles = 0; unsigned nof_error_indications = 0; std::chrono::microseconds average_decision_latency{0}; diff --git a/include/srsran/scheduler/scheduler_slot_handler.h b/include/srsran/scheduler/scheduler_slot_handler.h index 0363d9e068..13cd2cc7f1 100644 --- a/include/srsran/scheduler/scheduler_slot_handler.h +++ b/include/srsran/scheduler/scheduler_slot_handler.h @@ -581,7 +581,7 @@ struct ul_sched_result { /// PUCCH grants allocated in the current slot. static_vector pucchs; /// SRS grants allocated in the current slot. - static_vector srss; + static_vector srss; }; /// Scheduler decision made for DL and UL in a given slot. diff --git a/include/srsran/support/async/execute_on_blocking.h b/include/srsran/support/async/execute_on_blocking.h new file mode 100644 index 0000000000..dd94c437c5 --- /dev/null +++ b/include/srsran/support/async/execute_on_blocking.h @@ -0,0 +1,180 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/noop_functor.h" +#include "srsran/support/async/execute_on.h" +#include "srsran/support/timers.h" + +namespace srsran { + +namespace detail { + +template +auto dispatch_on_blocking(TaskExecutor& exec, timer_manager& timers, OnFailureToDispatch&& on_failure) +{ + struct blocking_dispatch_on_awaiter { + blocking_dispatch_on_awaiter(TaskExecutor& exec_, timer_manager& timers_, OnFailureToDispatch&& on_failure_) : + exec(exec_), timers(timers_), on_failure(std::forward(on_failure_)) + { + } + + bool await_ready() noexcept { return false; } + + void await_suspend(coro_handle<> suspending_awaitable) + { + auto task = [suspending_awaitable]() mutable { suspending_awaitable.resume(); }; + + // Try to dispatch task. + if constexpr (IsExecute) { + if (exec.execute(task)) { + return; + } + } else { + if (exec.defer(task)) { + return; + } + } + + // Task execute/defer failed (potentially because task executor queue is full). + on_failure(); + + // Leverage timer infrastructure to run task. + // Note: Even if the timer expiry fails to invoke task in executor, it keeps trying on every tick. + retry_timer = timers.create_unique_timer(exec); + retry_timer.set(std::chrono::milliseconds{1}, + [suspending_awaitable](timer_id_t tid) mutable { suspending_awaitable.resume(); }); + retry_timer.run(); + } + + void await_resume() {} + + blocking_dispatch_on_awaiter& get_awaiter() { return *this; } + + private: + TaskExecutor& exec; + timer_manager& timers; + OnFailureToDispatch on_failure; + unique_timer retry_timer; + }; + + return blocking_dispatch_on_awaiter{exec, timers, std::forward(on_failure)}; +} + +} // namespace detail + +/// \brief Returns an awaitable that resumes the suspended coroutine in a different execution context. If the call +/// to execute fails, the awaitable yields and will retry the dispatch at a later point, until it succeeds. +/// \param[in] exec Executor used to dispatch coroutine to a new execution context. +/// \param[in] timers Timer service used to handle reattempts to dispatch task to new execution context. +/// \param[in] on_failure Callback invoked in case the dispatch to executor fails at first attempt. +template +auto execute_on_blocking(TaskExecutor& exec, timer_manager& timers, OnFailureToDispatch&& on_failure = noop_operation{}) +{ + return detail::dispatch_on_blocking( + exec, timers, std::forward(on_failure)); +} + +/// \brief Returns an awaitable that resumes the suspended coroutine in a different execution context. If the call +/// to defer fails, the awaitable yields and will retry the dispatch at a later point, until it succeeds. +/// \param[in] exec Executor used to dispatch coroutine to a new execution context. +/// \param[in] timers Timer service used to handle reattempts to dispatch task to new execution context. +/// \param[in] on_failure Callback invoked in case the dispatch to executor fails at first attempt. +template +auto defer_on_blocking(TaskExecutor& exec, timer_manager& timers, OnFailureToDispatch&& on_failure = noop_operation{}) +{ + return detail::dispatch_on_blocking( + exec, timers, std::forward(on_failure)); +} + +/// \brief Returns an async_task that runs a given invocable task in a \c dispatch_exec executor, and once the +/// task is complete, it resumes the suspended coroutine in a \c return_exec executor. +template > +std::enable_if_t, async_task> +execute_and_continue_on_blocking(DispatchTaskExecutor& dispatch_exec, + CurrentTaskExecutor& return_exec, + timer_manager& timers, + Callable&& callable, + OnFailureToDispatch&& on_failure = noop_operation{}) +{ + return launch_async([&return_exec, + &dispatch_exec, + task = std::forward(callable), + on_failure = std::forward(on_failure), + &timers](coro_context>& ctx) mutable { + CORO_BEGIN(ctx); + + // Dispatch execution context switch. + CORO_AWAIT(execute_on_blocking(dispatch_exec, timers, on_failure)); + + // Run task. + task(); + + // Continuation in the original executor. + CORO_AWAIT(execute_on_blocking(return_exec, timers, on_failure)); + + CORO_RETURN(); + }); +} + +/// \brief Returns an async_task that runs a given invocable task in a \c dispatch_exec executor, and once +/// the task is complete, it resumes the suspended coroutine in a \c return_exec executor. +template > +std::enable_if_t, async_task> +execute_and_continue_on_blocking(DispatchTaskExecutor& dispatch_exec, + CurrentTaskExecutor& return_exec, + timer_manager& timers, + Callable&& callable, + OnFailureToDispatch&& on_failure = noop_operation{}) +{ + ReturnType ret{}; + return launch_async([&return_exec, + &dispatch_exec, + task = std::forward(callable), + on_failure = std::forward(on_failure), + &timers, + ret](coro_context>& ctx) mutable { + CORO_BEGIN(ctx); + + // Dispatch execution context switch. + CORO_AWAIT(execute_on_blocking(dispatch_exec, timers, on_failure)); + + // Run task. + ret = task(); + + // Continuation in the original executor. + CORO_AWAIT(execute_on_blocking(return_exec, timers, on_failure)); + + CORO_RETURN(ret); + }); +} + +} // namespace srsran \ No newline at end of file diff --git a/lib/asn1/CMakeLists.txt b/lib/asn1/CMakeLists.txt index a026ae5f9e..a9583c7102 100644 --- a/lib/asn1/CMakeLists.txt +++ b/lib/asn1/CMakeLists.txt @@ -48,6 +48,8 @@ add_library(e2ap_asn1 STATIC e2ap/e2ap.cpp e2sm/e2sm_common_ies.cpp e2sm/e2sm_kp target_compile_options(e2ap_asn1 PRIVATE -Os -fno-exceptions) target_link_libraries(e2ap_asn1 asn1_utils) +add_to_exported_libs(e2ap_asn1) + # NGAP ASN1 add_library(ngap_asn1 STATIC ngap/common.cpp ngap/ngap_ies.cpp ngap/ngap_pdu_contents.cpp ngap/ngap.cpp) target_compile_options(ngap_asn1 PRIVATE -Os -fno-exceptions) diff --git a/lib/cu_cp/CMakeLists.txt b/lib/cu_cp/CMakeLists.txt index 5b1a6db768..e1ae277961 100644 --- a/lib/cu_cp/CMakeLists.txt +++ b/lib/cu_cp/CMakeLists.txt @@ -77,7 +77,8 @@ target_link_libraries(srsran_cu_cp srslog srsran_support srsran_security + srsran_e2 ${CMAKE_DL_LIBS} ) -add_to_exported_libs(srsran_cu_cp) \ No newline at end of file +add_to_exported_libs(srsran_cu_cp) diff --git a/lib/cu_cp/cu_cp_impl.cpp b/lib/cu_cp/cu_cp_impl.cpp index 63190512c5..6bd4fabea2 100644 --- a/lib/cu_cp/cu_cp_impl.cpp +++ b/lib/cu_cp/cu_cp_impl.cpp @@ -113,6 +113,15 @@ cu_cp_impl::cu_cp_impl(const cu_cp_configuration& config_) : statistics_report_timer.set(cfg.metrics.statistics_report_period, [this](timer_id_t /*tid*/) { on_statistics_report_timer_expired(); }); statistics_report_timer.run(); + + if (cfg.e2_client) { + // todo: subscribe e2_metric_manager to a metric hub (currently not present) + e2ap_entity = create_e2_cu_entity(cfg.e2ap_config, + cfg.e2_client, + cfg.e2_cu_metric_iface, + timer_factory{*cfg.services.timers, *cfg.services.cu_cp_executor}, + *cfg.services.cu_cp_executor); + } } cu_cp_impl::~cu_cp_impl() @@ -131,6 +140,9 @@ bool cu_cp_impl::start() })) { report_fatal_error("Failed to initiate CU-CP setup"); } + if (e2ap_entity) { + e2ap_entity->start(); + } // Block waiting for CU-CP setup to complete. return fut.get(); @@ -142,6 +154,9 @@ void cu_cp_impl::stop() if (already_stopped) { return; } + if (e2ap_entity) { + e2ap_entity->stop(); + } logger.info("Stopping CU-CP..."); // Shut down components from within CU-CP executor. diff --git a/lib/cu_cp/cu_cp_impl.h b/lib/cu_cp/cu_cp_impl.h index 31e617637e..416636dfe1 100644 --- a/lib/cu_cp/cu_cp_impl.h +++ b/lib/cu_cp/cu_cp_impl.h @@ -37,6 +37,8 @@ #include "ue_manager/ue_manager_impl.h" #include "srsran/cu_cp/cu_cp_configuration.h" #include "srsran/cu_cp/cu_cp_types.h" +#include "srsran/e2/e2_cu.h" +#include "srsran/e2/e2_cu_factory.h" #include "srsran/f1ap/cu_cp/f1ap_cu.h" #include "srsran/ran/plmn_identity.h" #include @@ -220,6 +222,8 @@ class cu_cp_impl final : public cu_cp, start_ngap_handover_preparation_procedure_func start_ho_prep_func = nullptr; connect_amfs_func connect_amfs = nullptr; disconnect_amfs_func disconnect_amfs = nullptr; + // E2 interface + std::unique_ptr e2ap_entity; }; } // namespace srs_cu_cp diff --git a/lib/du/du_high/adapters/f1ap_adapters.h b/lib/du/du_high/adapters/f1ap_adapters.h index 4ec16da138..18216d97c9 100644 --- a/lib/du/du_high/adapters/f1ap_adapters.h +++ b/lib/du/du_high/adapters/f1ap_adapters.h @@ -24,7 +24,6 @@ #include "srsran/du/du_high/du_manager/du_manager.h" #include "srsran/f1ap/du/f1ap_du.h" -#include "srsran/support/async/execute_on.h" #include "srsran/support/timers.h" namespace srsran { diff --git a/lib/du/du_high/adapters/f1ap_test_mode_adapter.cpp b/lib/du/du_high/adapters/f1ap_test_mode_adapter.cpp index 13624ee39d..6754a03956 100644 --- a/lib/du/du_high/adapters/f1ap_test_mode_adapter.cpp +++ b/lib/du/du_high/adapters/f1ap_test_mode_adapter.cpp @@ -246,14 +246,15 @@ std::unique_ptr srsran::srs_du::create_du_high_f1ap(f1c_connection_clie task_executor& ctrl_exec, du_high_ue_executor_mapper& ue_exec_mapper, f1ap_du_paging_notifier& paging_notifier, + timer_manager& timers, const du_test_mode_config& test_cfg) { if (not test_cfg.test_ue.has_value()) { - return create_f1ap(f1c_client_handler, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier); + return create_f1ap(f1c_client_handler, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier, timers); } // Create a F1AP test mode adapter that wraps the real F1AP and intercepts messages to the F1-C client. auto f1ap_testmode = std::make_unique(*test_cfg.test_ue, f1c_client_handler, ctrl_exec); - f1ap_testmode->connect(create_f1ap(*f1ap_testmode, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier)); + f1ap_testmode->connect(create_f1ap(*f1ap_testmode, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier, timers)); return f1ap_testmode; } diff --git a/lib/du/du_high/adapters/f1ap_test_mode_adapter.h b/lib/du/du_high/adapters/f1ap_test_mode_adapter.h index 6becf40c93..9dc0ed26dd 100644 --- a/lib/du/du_high/adapters/f1ap_test_mode_adapter.h +++ b/lib/du/du_high/adapters/f1ap_test_mode_adapter.h @@ -37,6 +37,7 @@ std::unique_ptr create_du_high_f1ap(f1c_connection_client& f1c_cli task_executor& ctrl_exec, du_high_ue_executor_mapper& ue_exec_mapper, f1ap_du_paging_notifier& paging_notifier, + timer_manager& timers, const du_test_mode_config& test_cfg); } // namespace srs_du diff --git a/lib/du/du_high/adapters/mac_test_mode_adapter.cpp b/lib/du/du_high/adapters/mac_test_mode_adapter.cpp index bc03db94fc..6ae8bbefb2 100644 --- a/lib/du/du_high/adapters/mac_test_mode_adapter.cpp +++ b/lib/du/du_high/adapters/mac_test_mode_adapter.cpp @@ -469,6 +469,11 @@ void mac_test_mode_cell_adapter::handle_uci(const mac_uci_indication_message& ms forward_uci_ind_to_mac(msg_copy); } +void mac_test_mode_cell_adapter::handle_srs(const mac_srs_indication_message& msg) +{ + // TODO: Implement this method. +} + // Intercepts the UL results coming from the MAC. void mac_test_mode_cell_adapter::on_new_uplink_scheduler_results(const mac_ul_sched_result& ul_res) { @@ -761,6 +766,7 @@ std::unique_ptr srsran::srs_du::create_du_high_mac(const mac_conf mac_cfg.mac_cfg, mac_cfg.pcap, mac_cfg.sched_cfg, - mac_cfg.metric_notifier})); + mac_cfg.metric_notifier, + mac_cfg.timers})); return mac_testmode; } diff --git a/lib/du/du_high/adapters/mac_test_mode_adapter.h b/lib/du/du_high/adapters/mac_test_mode_adapter.h index 2d1ad24390..0038d22fc9 100644 --- a/lib/du/du_high/adapters/mac_test_mode_adapter.h +++ b/lib/du/du_high/adapters/mac_test_mode_adapter.h @@ -166,6 +166,8 @@ class mac_test_mode_cell_adapter : public mac_cell_control_information_handler, void handle_uci(const mac_uci_indication_message& msg) override; + void handle_srs(const mac_srs_indication_message& msg) override; + private: struct slot_decision_history { // Locks a given slot. diff --git a/lib/du/du_high/du_high_impl.cpp b/lib/du/du_high/du_high_impl.cpp index f609b9a34c..52bf1b47f9 100644 --- a/lib/du/du_high/du_high_impl.cpp +++ b/lib/du/du_high/du_high_impl.cpp @@ -27,8 +27,6 @@ #include "adapters/f1ap_test_mode_adapter.h" #include "du_high_executor_strategies.h" #include "srsran/du/du_high/du_manager/du_manager_factory.h" -#include "srsran/e2/e2.h" -#include "srsran/e2/e2_factory.h" #include "srsran/f1ap/du/f1ap_du_factory.h" #include "srsran/support/executors/task_redispatcher.h" #include "srsran/support/timers.h" @@ -126,13 +124,15 @@ du_high_impl::du_high_impl(const du_high_configuration& config_) : cfg.ran.mac_cfg, *cfg.mac_p, cfg.ran.sched_cfg, - cfg.sched_ue_metrics_notifier ? *cfg.sched_ue_metrics_notifier : *metrics_notifier}, + cfg.sched_ue_metrics_notifier ? *cfg.sched_ue_metrics_notifier : *metrics_notifier, + timers}, cfg.test_cfg); f1ap = create_du_high_f1ap(*cfg.f1c_client, adapters->f1_to_du_notifier, cfg.exec_mapper->du_control_executor(), cfg.exec_mapper->ue_mapper(), adapters->f1ap_paging_notifier, + timers, cfg.test_cfg); du_manager = create_du_manager(du_manager_params{ @@ -152,13 +152,13 @@ du_high_impl::du_high_impl(const du_high_configuration& config_) : if (cfg.e2_client) { // todo: subscribe e2_metric_manager to a metric hub (currently not present) - e2ap_entity = create_e2_entity(cfg.e2ap_config, - cfg.e2_client, - *cfg.e2_du_metric_iface, - *f1ap, - get_du_configurator(), - timer_factory{timers, cfg.exec_mapper->du_e2_executor()}, - cfg.exec_mapper->du_e2_executor()); + e2ap_entity = create_e2_du_entity(cfg.e2ap_config, + cfg.e2_client, + cfg.e2_du_metric_iface, + f1ap.get(), + &(get_du_configurator()), + timer_factory{timers, cfg.exec_mapper->du_e2_executor()}, + cfg.exec_mapper->du_e2_executor()); } } diff --git a/lib/du/du_high/du_high_impl.h b/lib/du/du_high/du_high_impl.h index 2b880728a0..a18dfd71a1 100644 --- a/lib/du/du_high/du_high_impl.h +++ b/lib/du/du_high/du_high_impl.h @@ -25,7 +25,8 @@ #include "srsran/du/du_high/du_high.h" #include "srsran/du/du_high/du_high_configuration.h" #include "srsran/du/du_high/du_manager/du_manager.h" -#include "srsran/e2/e2.h" +#include "srsran/e2/e2_du.h" +#include "srsran/e2/e2_du_factory.h" #include "srsran/f1ap/du/f1ap_du.h" #include "srsran/mac/mac.h" #include "srsran/scheduler/scheduler_metrics.h" diff --git a/lib/du/du_high/du_manager/converters/asn1_rrc_config_helpers.cpp b/lib/du/du_high/du_manager/converters/asn1_rrc_config_helpers.cpp index 11ead0ea51..02b2b2049f 100644 --- a/lib/du/du_high/du_manager/converters/asn1_rrc_config_helpers.cpp +++ b/lib/du/du_high/du_manager/converters/asn1_rrc_config_helpers.cpp @@ -2191,16 +2191,16 @@ asn1::rrc_nr::srs_res_set_s srsran::srs_du::make_asn1_rrc_srs_res_set(const srs_ } switch (cfg.srs_res_set_usage) { - case srs_config::srs_resource_set::usage::beam_management: + case srs_usage::beam_management: srs_res_set.usage = srs_res_set_s::usage_opts::beam_management; break; - case srs_config::srs_resource_set::usage::codebook: + case srs_usage::codebook: srs_res_set.usage = srs_res_set_s::usage_opts::codebook; break; - case srs_config::srs_resource_set::usage::non_codebook: + case srs_usage::non_codebook: srs_res_set.usage = srs_res_set_s::usage_opts::non_codebook; break; - case srs_config::srs_resource_set::usage::antenna_switching: + case srs_usage::antenna_switching: srs_res_set.usage = srs_res_set_s::usage_opts::ant_switching; break; default: diff --git a/lib/du/du_high/du_manager/du_ue/du_ue_controller_impl.cpp b/lib/du/du_high/du_manager/du_ue/du_ue_controller_impl.cpp index 1b3177dc42..9b88541793 100644 --- a/lib/du/du_high/du_manager/du_ue/du_ue_controller_impl.cpp +++ b/lib/du/du_high/du_manager/du_ue/du_ue_controller_impl.cpp @@ -21,7 +21,7 @@ */ #include "du_ue_controller_impl.h" -#include "srsran/support/async/execute_on.h" +#include "srsran/support/async/execute_on_blocking.h" using namespace srsran; using namespace srs_du; @@ -330,20 +330,27 @@ async_task du_ue_controller_impl::create_stop_traffic_task() async_task du_ue_controller_impl::run_in_ue_executor(unique_task task) { - return launch_async([this, task = std::move(task)](coro_context>& ctx) { + auto log_dispatch_retry = [this]() { + logger.warning("ue={}: Postpone dispatching of control task to executor. Cause: Task queue is full", ue_index); + }; + + return launch_async([this, task = std::move(task), log_dispatch_retry](coro_context>& ctx) { CORO_BEGIN(ctx); // Sync with UE control executor to run provided task. - CORO_AWAIT(execute_on_blocking(cfg.services.ue_execs.ctrl_executor(ue_index))); + CORO_AWAIT( + defer_on_blocking(cfg.services.ue_execs.ctrl_executor(ue_index), cfg.services.timers, log_dispatch_retry)); task(); - CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec)); + CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec, cfg.services.timers, log_dispatch_retry)); // Sync with remaining UE executors, as there might be still pending tasks dispatched to those. // TODO: use when_all awaiter - CORO_AWAIT(execute_on_blocking(cfg.services.ue_execs.mac_ul_pdu_executor(ue_index))); - CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec)); - CORO_AWAIT(execute_on_blocking(cfg.services.ue_execs.f1u_dl_pdu_executor(ue_index))); - CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec)); + CORO_AWAIT(defer_on_blocking( + cfg.services.ue_execs.mac_ul_pdu_executor(ue_index), cfg.services.timers, log_dispatch_retry)); + CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec, cfg.services.timers, log_dispatch_retry)); + CORO_AWAIT(defer_on_blocking( + cfg.services.ue_execs.f1u_dl_pdu_executor(ue_index), cfg.services.timers, log_dispatch_retry)); + CORO_AWAIT(execute_on_blocking(cfg.services.du_mng_exec, cfg.services.timers, log_dispatch_retry)); CORO_RETURN(); }); diff --git a/lib/du/du_high/du_manager/ran_resource_management/pucch_resource_generator.cpp b/lib/du/du_high/du_manager/ran_resource_management/pucch_resource_generator.cpp index 354d77ac6c..927b51041a 100644 --- a/lib/du/du_high/du_manager/ran_resource_management/pucch_resource_generator.cpp +++ b/lib/du/du_high/du_manager/ran_resource_management/pucch_resource_generator.cpp @@ -395,6 +395,11 @@ srsran::srs_du::pucch_parameters_validator(unsigned static_cast(std::ceil(static_cast(nof_res_f0_f1) / static_cast(nof_f0_per_block))); } else { const auto& f1_params = std::get(f0_f1_params); + if (f1_params.nof_symbols.to_uint() > max_nof_symbols.to_uint()) { + return make_unexpected("The number of symbols for PUCCH Format 1 exceeds the maximum number of symbols available " + "for PUCCH resources"); + } + // > Compute the number of RBs required for the PUCCH Format 1 resources. const unsigned nof_occ_codes = f1_params.occ_supported ? format1_symb_to_spreading_factor(f1_params.nof_symbols) : 1; diff --git a/lib/e2/CMakeLists.txt b/lib/e2/CMakeLists.txt index ab160bb92d..fc5872a298 100644 --- a/lib/e2/CMakeLists.txt +++ b/lib/e2/CMakeLists.txt @@ -29,6 +29,8 @@ set(SOURCES common/e2_impl.cpp common/e2_entity.cpp common/e2_subscription_manager_impl.cpp + common/e2_du_metrics_connector.cpp + common/e2_cu_metrics_connector.cpp e2sm/e2sm_kpm/e2sm_kpm_impl.cpp e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp @@ -40,10 +42,12 @@ set(SOURCES e2sm/e2sm_kpm/e2sm_kpm_utils.cpp e2sm/e2sm_kpm/e2sm_kpm_report_service_impl.cpp e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp - common/e2_du_metrics_connector.cpp + e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.cpp ) add_library(srsran_e2 STATIC ${SOURCES}) target_link_libraries(srsran_e2 e2ap_asn1 srsran_support) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_to_exported_libs(srsran_e2) \ No newline at end of file diff --git a/apps/services/e2_metric_connector_manager.cpp b/lib/e2/common/e2_cu_metrics_connector.cpp similarity index 53% rename from apps/services/e2_metric_connector_manager.cpp rename to lib/e2/common/e2_cu_metrics_connector.cpp index 3bbd2e69e4..235bbac8c1 100644 --- a/apps/services/e2_metric_connector_manager.cpp +++ b/lib/e2/common/e2_cu_metrics_connector.cpp @@ -20,25 +20,13 @@ * */ -#include "e2_metric_connector_manager.h" +#include "srsran/e2/e2_cu_metrics_connector.h" using namespace srsran; -e2_metric_connector_manager::e2_metric_connector_manager(unsigned nof_cells) -{ - for (unsigned i = 0, e = nof_cells; i != e; ++i) { - e2_du_metric_connectors.push_back(std::make_unique()); - } -} - -e2_du_metrics_notifier& e2_metric_connector_manager::get_e2_du_metric_notifier(unsigned du_index) -{ - srsran_assert(du_index < e2_du_metric_connectors.size(), "Invalid DU index"); - return *e2_du_metric_connectors[du_index]; -} +e2_cu_metrics_connector::e2_cu_metrics_connector() = default; -e2_du_metrics_interface& e2_metric_connector_manager::get_e2_du_metrics_interface(unsigned du_index) +void e2_cu_metrics_connector::connect_e2_cu_meas_provider(std::unique_ptr meas_provider) { - srsran_assert(du_index < e2_du_metric_connectors.size(), "Invalid DU index"); - return *e2_du_metric_connectors[du_index]; + e2_meas_provider = std::move(meas_provider); } diff --git a/lib/e2/common/e2_du_metrics_connector.cpp b/lib/e2/common/e2_du_metrics_connector.cpp index e7845c9408..da9f971e99 100644 --- a/lib/e2/common/e2_du_metrics_connector.cpp +++ b/lib/e2/common/e2_du_metrics_connector.cpp @@ -24,20 +24,10 @@ using namespace srsran; -e2_du_metrics_connector::e2_du_metrics_connector() -{ - ue_metrics_queue.resize(MAX_UE_METRICS); -} +e2_du_metrics_connector::e2_du_metrics_connector() {} void e2_du_metrics_connector::report_metrics(const scheduler_cell_metrics& metrics) { - for (auto& ue_metric : metrics.ue_metrics) { - if (ue_metrics_queue.size() == MAX_UE_METRICS) { - ue_metrics_queue.pop_front(); - } - ue_metrics_queue.push_back(ue_metric); - } - if (e2_meas_provider) { // Pass metrics to the E2 Measurement Provider. e2_meas_provider->report_metrics(metrics); @@ -52,14 +42,6 @@ void e2_du_metrics_connector::report_metrics(const rlc_metrics& metrics) } } -void e2_du_metrics_connector::get_metrics(scheduler_ue_metrics& ue_metrics) -{ - if (ue_metrics_queue.empty()) { - return; - } - ue_metrics = ue_metrics_queue.front(); -} - void e2_du_metrics_connector::connect_e2_du_meas_provider(std::unique_ptr meas_provider) { e2_meas_provider = std::move(meas_provider); diff --git a/lib/e2/common/e2_entity.cpp b/lib/e2/common/e2_entity.cpp index 39c3f24be1..5f36704792 100644 --- a/lib/e2/common/e2_entity.cpp +++ b/lib/e2/common/e2_entity.cpp @@ -29,6 +29,7 @@ #include "../e2sm/e2sm_rc/e2sm_rc_impl.h" #include "e2_impl.h" #include "e2_subscription_manager_impl.h" +#include "e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.h" #include "e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h" #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/e2/e2.h" @@ -45,13 +46,13 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, decorated_e2_iface = std::move(decorated_e2_iface_); } -e2_entity::e2_entity(e2ap_configuration& cfg_, - e2_connection_client* e2_client_, - e2_du_metrics_interface& e2_du_metrics_iface_, - srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - srs_du::du_configurator& du_configurator_, - timer_factory timers_, - task_executor& task_exec_) : +e2_entity::e2_entity(e2ap_configuration& cfg_, + e2_connection_client* e2_client_, + std::variant e2_metrics_, + srs_du::f1ap_ue_id_translator* f1ap_ue_id_translator_, + srs_du::du_configurator* du_configurator_, + timer_factory timers_, + task_executor& task_exec_) : logger(srslog::fetch_basic_logger("E2")), cfg(cfg_), task_exec(task_exec_), main_ctrl_loop(128) { e2_pdu_notifier = e2_client_->handle_connection_request(); @@ -59,21 +60,42 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, subscription_mngr = std::make_unique(*e2_pdu_notifier, *e2sm_mngr); if (cfg.e2sm_kpm_enabled) { - auto e2sm_kpm_meas_provider = std::make_unique(f1ap_ue_id_translator_); - auto e2sm_kpm_packer = std::make_unique(*e2sm_kpm_meas_provider); - auto e2sm_kpm_iface = std::make_unique(logger, *e2sm_kpm_packer, *e2sm_kpm_meas_provider); + std::variant, std::unique_ptr> + e2sm_kpm_meas_provider; + if (std::holds_alternative(e2_metrics_)) { + e2sm_kpm_meas_provider = std::make_unique(*f1ap_ue_id_translator_); + } else { + e2sm_kpm_meas_provider = std::make_unique(); + } + std::unique_ptr e2sm_kpm_packer; + std::unique_ptr e2sm_kpm_iface; + std::visit( + [&e2sm_kpm_packer, &e2sm_kpm_iface, this](auto&& arg) { + e2sm_kpm_packer = std::make_unique(*arg); + e2sm_kpm_iface = std::make_unique(this->logger, *e2sm_kpm_packer, *arg); + }, + e2sm_kpm_meas_provider); + e2sm_handlers.push_back(std::move(e2sm_kpm_packer)); e2sm_mngr->add_e2sm_service(e2sm_kpm_asn1_packer::oid, std::move(e2sm_kpm_iface)); subscription_mngr->add_ran_function_oid(e2sm_kpm_asn1_packer::ran_func_id, e2sm_kpm_asn1_packer::oid); - e2_du_metrics_iface_.connect_e2_du_meas_provider(std::move(e2sm_kpm_meas_provider)); + if (std::holds_alternative(e2_metrics_)) { + std::get(e2_metrics_) + ->connect_e2_du_meas_provider( + std::move(std::get>(e2sm_kpm_meas_provider))); + } else { + std::get(e2_metrics_) + ->connect_e2_cu_meas_provider( + std::move(std::get>(e2sm_kpm_meas_provider))); + } } - if (cfg.e2sm_rc_enabled) { + if (cfg.e2sm_rc_enabled && du_configurator_) { auto e2sm_rc_packer = std::make_unique(); auto e2sm_rc_iface = std::make_unique(logger, *e2sm_rc_packer); // Create e2sm_rc Control Service Style 2. std::unique_ptr rc_control_service_style2 = std::make_unique(2); std::unique_ptr rc_control_action_2_6_executor = - std::make_unique(du_configurator_); + std::make_unique(*du_configurator_); rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); e2sm_rc_packer->add_e2sm_control_service(rc_control_service_style2.get()); diff --git a/lib/e2/common/e2_entity.h b/lib/e2/common/e2_entity.h index 2a8139f4cb..cb8fa510c7 100644 --- a/lib/e2/common/e2_entity.h +++ b/lib/e2/common/e2_entity.h @@ -27,8 +27,9 @@ #include "procedures/e2_subscription_setup_procedure.h" #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/du/du_high/du_manager/du_configurator.h" -#include "srsran/e2/e2.h" #include "srsran/e2/e2_connection_client.h" +#include "srsran/e2/e2_cu.h" +#include "srsran/e2/e2_du.h" #include "srsran/e2/e2ap_configuration.h" #include "srsran/e2/e2sm/e2sm_factory.h" #include "srsran/e2/e2sm/e2sm_manager.h" @@ -46,13 +47,13 @@ class e2_entity final : public e2_interface public: e2_entity(e2ap_configuration& cfg_, std::unique_ptr decorated_e2_iface_, task_executor& task_exec_); - e2_entity(e2ap_configuration& cfg_, - e2_connection_client* e2_client_, - e2_du_metrics_interface& e2_du_metrics_, - srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - srs_du::du_configurator& du_configurator_, - timer_factory timers_, - task_executor& task_exec_); + e2_entity(e2ap_configuration& cfg_, + e2_connection_client* e2_client_, + std::variant e2_metrics_, + srs_du::f1ap_ue_id_translator* f1ap_ue_id_translator_, + srs_du::du_configurator* du_configurator_, + timer_factory timers_, + task_executor& task_exec_); void start() override; void stop() override; diff --git a/lib/e2/common/e2_factory.cpp b/lib/e2/common/e2_factory.cpp index 47dc90e3c0..116ef9df56 100644 --- a/lib/e2/common/e2_factory.cpp +++ b/lib/e2/common/e2_factory.cpp @@ -24,6 +24,8 @@ #include "e2_entity.h" #include "e2_impl.h" #include "e2ap_asn1_packer.h" +#include "srsran/e2/e2_cu_factory.h" +#include "srsran/e2/e2_du_factory.h" using namespace srsran; @@ -49,16 +51,29 @@ std::unique_ptr srsran::create_e2_with_task_exec(e2ap_configuratio return e2_ext; } -std::unique_ptr srsran::create_e2_entity(e2ap_configuration& e2ap_cfg_, - e2_connection_client* e2_client_, - e2_du_metrics_interface& e2_du_metrics_, - srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - srs_du::du_configurator& du_configurator_, - timer_factory timers_, - task_executor& e2_exec_) +std::unique_ptr srsran::create_e2_du_entity(e2ap_configuration& e2ap_cfg_, + e2_connection_client* e2_client_, + e2_du_metrics_interface* e2_metrics_var, + srs_du::f1ap_ue_id_translator* f1ap_ue_id_translator_, + srs_du::du_configurator* du_configurator_, + timer_factory timers_, + task_executor& e2_exec_) { - auto e2_ext = std::make_unique( - e2ap_cfg_, e2_client_, e2_du_metrics_, f1ap_ue_id_translator_, du_configurator_, timers_, e2_exec_); + std::variant e2_du_metrics_var = e2_metrics_var; + auto e2_ext = std::make_unique( + e2ap_cfg_, e2_client_, e2_du_metrics_var, f1ap_ue_id_translator_, du_configurator_, timers_, e2_exec_); + return e2_ext; +} + +std::unique_ptr srsran::create_e2_cu_entity(e2ap_configuration& e2ap_cfg_, + e2_connection_client* e2_client_, + e2_cu_metrics_interface* e2_metrics_var, + timer_factory timers_, + task_executor& e2_exec_) +{ + std::variant e2_cu_metrics_var = e2_metrics_var; + auto e2_ext = + std::make_unique(e2ap_cfg_, e2_client_, e2_cu_metrics_var, nullptr, nullptr, timers_, e2_exec_); return e2_ext; } diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.cpp new file mode 100644 index 0000000000..8c90150d6d --- /dev/null +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.cpp @@ -0,0 +1,162 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "e2sm_kpm_cu_meas_provider_impl.h" + +using namespace asn1::e2ap; +using namespace asn1::e2sm; +using namespace srsran; + +e2sm_kpm_cu_meas_provider_impl::e2sm_kpm_cu_meas_provider_impl() : logger(srslog::fetch_basic_logger("E2SM-KPM")) +{ + supported_metrics.emplace( + "PdcpReordDelayUl", + e2sm_kpm_supported_metric_t{ + NO_LABEL, ALL_LEVELS, false, &e2sm_kpm_cu_meas_provider_impl::get_pdcp_reordering_delay_ul}); +} + +bool e2sm_kpm_cu_meas_provider_impl::check_e2sm_kpm_metrics_definitions(span metric_defs) +{ + std::string metric_name; + auto name_matches = [&metric_name](const e2sm_kpm_metric_t& x) { + return (x.name == metric_name.c_str() or x.name == metric_name); + }; + + for (auto& supported_metric : supported_metrics) { + metric_name = supported_metric.first; + auto it = std::find_if(metric_defs.begin(), metric_defs.end(), name_matches); + if (it == metric_defs.end()) { + continue; + } + + if (supported_metric.second.supported_labels & ~(it->optional_labels | e2sm_kpm_label_enum::NO_LABEL)) { + logger.debug("Wrong definition of the supported metric: \"{}\", labels cannot be supported.", metric_name); + } + + if (supported_metric.second.supported_levels & ~it->optional_levels) { + logger.debug("Wrong definition of the supported metric: \"{}\", level cannot be supported.", metric_name); + } + + if (is_cell_id_required(*it) and not supported_metric.second.cell_scope_supported) { + logger.debug("Wrong definition of the supported metric: \"{}\", cell scope has to be supported.", + metric_name.c_str()); + } + } + return true; +} + +std::vector e2sm_kpm_cu_meas_provider_impl::get_supported_metric_names(e2sm_kpm_metric_level_enum level) +{ + std::vector metrics; + for (auto& m : supported_metrics) { + if ((level & E2_NODE_LEVEL) and (m.second.supported_levels & E2_NODE_LEVEL)) { + metrics.push_back(m.first); + } else if ((level & UE_LEVEL) and (m.second.supported_levels & UE_LEVEL)) { + metrics.push_back(m.first); + } + } + return metrics; +} + +bool e2sm_kpm_cu_meas_provider_impl::is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) +{ + // TODO: check if CELL is supported + return true; +} + +bool e2sm_kpm_cu_meas_provider_impl::is_ue_supported(const asn1::e2sm::ue_id_c& ueid) +{ + // TODO: check if UE is supported + return true; +} + +bool e2sm_kpm_cu_meas_provider_impl::is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) +{ + // TODO: check if test condition is supported + return true; +} + +bool e2sm_kpm_cu_meas_provider_impl::is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) +{ + if (!label.no_label_present) { + logger.debug("Currently only NO_LABEL metric supported."); + return false; + } + + for (auto& metric : supported_metrics) { + if (strcmp(meas_type.meas_name().to_string().c_str(), metric.first.c_str()) == 0) { + return true; + } + } + + // TODO: check if metric supported with required label, level and cell_scope + return false; +} + +bool e2sm_kpm_cu_meas_provider_impl::get_ues_matching_test_conditions( + const asn1::e2sm::matching_cond_list_l& matching_cond_list, + std::vector& ues) +{ + return true; +} + +bool e2sm_kpm_cu_meas_provider_impl::get_ues_matching_test_conditions( + const asn1::e2sm::matching_ue_cond_per_sub_list_l& matching_ue_cond_list, + std::vector& ues) +{ + return true; +} + +bool e2sm_kpm_cu_meas_provider_impl::get_meas_data(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::label_info_list_l label_info_list, + const std::vector& ues, + const std::optional cell_global_id, + std::vector& items) +{ + metric_meas_getter_func_ptr metric_meas_getter_func; + auto it = supported_metrics.find(meas_type.meas_name().to_string().c_str()); + if (it == supported_metrics.end()) { + logger.debug("Metric {} not supported.", meas_type.meas_name().to_string()); + return false; + } + metric_meas_getter_func = it->second.func; + srsran_assert(metric_meas_getter_func != nullptr, "Metric getter function cannot be empty."); + return (this->*metric_meas_getter_func)(label_info_list, ues, cell_global_id, items); +} + +float e2sm_kpm_cu_meas_provider_impl::bytes_to_kbits(float value) +{ + constexpr unsigned nof_bits_per_byte = 8; + return (nof_bits_per_byte * value / 1e3); +} + +bool e2sm_kpm_cu_meas_provider_impl::get_pdcp_reordering_delay_ul(const asn1::e2sm::label_info_list_l label_info_list, + const std::vector& ues, + const std::optional cell_global_id, + std::vector& items) +{ + bool meas_collected = false; + return meas_collected; +} \ No newline at end of file diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.h new file mode 100644 index 0000000000..afb98c2141 --- /dev/null +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.h @@ -0,0 +1,100 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "e2sm_kpm_metric_defs.h" +#include "e2sm_kpm_utils.h" +#include "srsran/adt/optional.h" +#include "srsran/asn1/asn1_utils.h" +#include "srsran/asn1/e2sm/e2sm_kpm_ies.h" +#include "srsran/e2/e2_cu.h" +#include "srsran/e2/e2sm/e2sm.h" +#include "srsran/e2/e2sm/e2sm_kpm.h" +#include +#include + +namespace srsran { + +class e2sm_kpm_cu_meas_provider_impl : public e2sm_kpm_meas_provider, public e2_cu_metrics_notifier +{ +public: + // constructor takes logger as argument + e2sm_kpm_cu_meas_provider_impl(); + + ~e2sm_kpm_cu_meas_provider_impl() = default; + + /// e2sm_kpm_meas_provider functions. + std::vector get_supported_metric_names(e2sm_kpm_metric_level_enum level) override; + + bool is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) override; + + bool is_ue_supported(const asn1::e2sm::ue_id_c& ueid) override; + + bool is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) override; + + bool is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) override; + + bool get_ues_matching_test_conditions(const asn1::e2sm::matching_cond_list_l& matching_cond_list, + std::vector& ues) override; + + bool get_ues_matching_test_conditions(const asn1::e2sm::matching_ue_cond_per_sub_list_l& matching_ue_cond_list, + std::vector& ues) override; + + bool get_meas_data(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::label_info_list_l label_info_list, + const std::vector& ues, + const std::optional cell_global_id, + std::vector& items) override; + +private: + typedef bool(metric_meas_getter_func_t)(const asn1::e2sm::label_info_list_l label_info_list, + const std::vector& ues, + const std::optional cell_global_id, + std::vector& items); + + typedef metric_meas_getter_func_t(e2sm_kpm_cu_meas_provider_impl::*metric_meas_getter_func_ptr); + + struct e2sm_kpm_supported_metric_t { + uint32_t supported_labels; + uint32_t supported_levels; + bool cell_scope_supported; + metric_meas_getter_func_ptr func; + }; + + bool check_e2sm_kpm_metrics_definitions(span metrics_defs); + + // Helper functions. + float bytes_to_kbits(float value); + + // Measurement getter functions. + metric_meas_getter_func_t get_pdcp_reordering_delay_ul; + + srslog::basic_logger& logger; + + std::map supported_metrics; +}; + +} // namespace srsran diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp index afa68adfb6..bb34dc7d4a 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp @@ -96,6 +96,10 @@ e2sm_kpm_du_meas_provider_impl::e2sm_kpm_du_meas_provider_impl(srs_du::f1ap_ue_i e2sm_kpm_supported_metric_t{ NO_LABEL, ALL_LEVELS, true, &e2sm_kpm_du_meas_provider_impl::get_drb_ul_rlc_sdu_latency}); + supported_metrics.emplace( + "RACH.PreambleDedCell", + e2sm_kpm_supported_metric_t{NO_LABEL, ALL_LEVELS, true, &e2sm_kpm_du_meas_provider_impl::get_prach_cell_count}); + // Check if the supported metrics are matching e2sm_kpm metrics definitions. check_e2sm_kpm_metrics_definitions(get_e2sm_kpm_28_552_metrics()); check_e2sm_kpm_metrics_definitions(get_e2sm_kpm_oran_metrics()); @@ -141,10 +145,10 @@ bool e2sm_kpm_du_meas_provider_impl::check_e2sm_kpm_metrics_definitions(span e2sm_kpm_du_meas_provider_impl::get_supported_metric_na return metrics; } -bool e2sm_kpm_du_meas_provider_impl::cell_supported(const asn1::e2sm::cgi_c& cell_global_id) +bool e2sm_kpm_du_meas_provider_impl::is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) { // TODO: check if CELL is supported return true; } -bool e2sm_kpm_du_meas_provider_impl::ue_supported(const asn1::e2sm::ue_id_c& ueid) +bool e2sm_kpm_du_meas_provider_impl::is_ue_supported(const asn1::e2sm::ue_id_c& ueid) { // TODO: check if UE is supported return true; } -bool e2sm_kpm_du_meas_provider_impl::test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) +bool e2sm_kpm_du_meas_provider_impl::is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) { // TODO: check if test condition is supported return true; } -bool e2sm_kpm_du_meas_provider_impl::metric_supported(const asn1::e2sm::meas_type_c& meas_type, - const asn1::e2sm::meas_label_s& label, - const e2sm_kpm_metric_level_enum level, - const bool& cell_scope) +bool e2sm_kpm_du_meas_provider_impl::is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) { if (!label.no_label_present) { logger.debug("Currently only NO_LABEL metric supported."); @@ -516,6 +520,28 @@ bool e2sm_kpm_du_meas_provider_impl::get_delay_ul(const asn1::e2sm::label_info_l return meas_collected; } +bool e2sm_kpm_du_meas_provider_impl::get_prach_cell_count(const asn1::e2sm::label_info_list_l label_info_list, + const std::vector& ues, + const std::optional cell_global_id, + std::vector& items) +{ + bool meas_collected = false; + if (last_ue_metrics.empty()) { + return handle_no_meas_data_available(ues, items, asn1::e2sm::meas_record_item_c::types::options::integer); + } + + if ((label_info_list.size() > 1 or + (label_info_list.size() == 1 and not label_info_list[0].meas_label.no_label_present))) { + logger.debug("Metric: RACH.PreambleDedCell supports only NO_LABEL label."); + return meas_collected; + } + meas_record_item_c meas_record_item; + meas_record_item.set_integer() = nof_ded_cell_preambles; + items.push_back(meas_record_item); + + return meas_collected; +} + float e2sm_kpm_du_meas_provider_impl::bytes_to_kbits(float value) { constexpr unsigned nof_bits_per_byte = 8; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h index 425007ff44..af9c26b668 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h @@ -27,7 +27,7 @@ #include "srsran/adt/optional.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/e2sm/e2sm_kpm_ies.h" -#include "srsran/e2/e2.h" +#include "srsran/e2/e2_du.h" #include "srsran/e2/e2sm/e2sm.h" #include "srsran/e2/e2sm/e2sm_kpm.h" #include "srsran/f1ap/du/f1ap_du.h" @@ -53,16 +53,16 @@ class e2sm_kpm_du_meas_provider_impl : public e2sm_kpm_meas_provider, public e2_ /// e2sm_kpm_meas_provider functions. std::vector get_supported_metric_names(e2sm_kpm_metric_level_enum level) override; - bool cell_supported(const asn1::e2sm::cgi_c& cell_global_id) override; + bool is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) override; - bool ue_supported(const asn1::e2sm::ue_id_c& ueid) override; + bool is_ue_supported(const asn1::e2sm::ue_id_c& ueid) override; - bool test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) override; + bool is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) override; - bool metric_supported(const asn1::e2sm::meas_type_c& meas_type, - const asn1::e2sm::meas_label_s& label, - const e2sm_kpm_metric_level_enum level, - const bool& cell_scope) override; + bool is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) override; bool get_ues_matching_test_conditions(const asn1::e2sm::matching_cond_list_l& matching_cond_list, std::vector& ues) override; @@ -116,12 +116,14 @@ class e2sm_kpm_du_meas_provider_impl : public e2sm_kpm_meas_provider, public e2_ metric_meas_getter_func_t get_drb_ul_mean_throughput; metric_meas_getter_func_t get_drb_dl_rlc_sdu_latency; metric_meas_getter_func_t get_drb_ul_rlc_sdu_latency; + metric_meas_getter_func_t get_prach_cell_count; srslog::basic_logger& logger; srs_du::f1ap_ue_id_translator& f1ap_ue_id_provider; unsigned nof_cell_prbs; unsigned nof_dl_slots; unsigned nof_ul_slots; + unsigned nof_ded_cell_preambles; std::vector last_ue_metrics; std::map> ue_aggr_rlc_metrics; size_t max_rlc_metrics = 1; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp index aaa3ffdae5..9859ed624b 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp @@ -83,7 +83,7 @@ bool e2sm_kpm_impl::process_action_def_meas_info_list(const meas_info_list_l& for (uint32_t l = 0; l < meas_info_list[i].label_info_list.size(); l++) { const meas_label_s& meas_label = meas_info_list[i].label_info_list[l].meas_label; - if (du_meas_provider.metric_supported(meas_type, meas_label, level, cell_scope)) { + if (du_meas_provider.is_metric_supported(meas_type, meas_label, level, cell_scope)) { admitted_value_type_labels[meas_name] = NO_LABEL; } else { return false; @@ -113,7 +113,7 @@ bool e2sm_kpm_impl::process_action_definition_format1( } if (cell_scope) { - if (not du_meas_provider.cell_supported(action_definition.cell_global_id)) { + if (not du_meas_provider.is_cell_supported(action_definition.cell_global_id)) { logger.debug("Cell not available -> do not admitted action\n"); return false; } @@ -140,7 +140,7 @@ bool e2sm_kpm_impl::process_action_definition_format2(const e2sm_kpm_action_defi const ue_id_c& ueid = action_definition.ue_id; const e2sm_kpm_action_definition_format1_s& subscript_info = action_definition.subscript_info; - if (not du_meas_provider.ue_supported(ueid)) { + if (not du_meas_provider.is_ue_supported(ueid)) { return false; } @@ -161,7 +161,7 @@ bool e2sm_kpm_impl::process_action_definition_format3(const e2sm_kpm_action_defi } if (cell_scope) { - if (not du_meas_provider.cell_supported(action_definition.cell_global_id)) { + if (not du_meas_provider.is_cell_supported(action_definition.cell_global_id)) { logger.debug("Cell not available -> do not admit action\n"); return false; } @@ -174,14 +174,14 @@ bool e2sm_kpm_impl::process_action_definition_format3(const e2sm_kpm_action_defi matching_cond_item_choice_c::types test_type = matching_cond_item.matching_cond_choice.type(); if (test_type == matching_cond_item_choice_c::types_opts::test_cond_info) { const test_cond_info_s& test_cond_info = matching_cond_item.matching_cond_choice.test_cond_info(); - if (not du_meas_provider.test_cond_supported(test_cond_info.test_type)) { + if (not du_meas_provider.is_test_cond_supported(test_cond_info.test_type)) { logger.debug("Matching UE test condition [test_cond] not supported -> do not admit action"); return false; } } else { // test_type == matching_cond_item_choice_c::types_opts::meas_label const meas_label_s& meas_label = matching_cond_item.matching_cond_choice.meas_label(); - if (not du_meas_provider.metric_supported(meas_type, meas_label, UE_LEVEL, cell_scope)) { + if (not du_meas_provider.is_metric_supported(meas_type, meas_label, UE_LEVEL, cell_scope)) { logger.debug("Matching UE test condition [meas_label] not supported -> do not admit action"); return false; } @@ -199,7 +199,7 @@ bool e2sm_kpm_impl::process_action_definition_format4(const e2sm_kpm_action_defi for (uint32_t i = 0; i < action_definition.matching_ue_cond_list.size(); ++i) { const test_cond_type_c& test_cond_type = action_definition.matching_ue_cond_list[i].test_cond_info.test_type; - if (not du_meas_provider.test_cond_supported(test_cond_type)) { + if (not du_meas_provider.is_test_cond_supported(test_cond_type)) { logger.debug("Matching UE test condition not supported -> do not admit action"); return false; } @@ -219,7 +219,7 @@ bool e2sm_kpm_impl::process_action_definition_format5(const e2sm_kpm_action_defi for (uint32_t i = 0; i < action_definition.matching_ue_id_list.size(); ++i) { const ue_id_c& ueid = action_definition.matching_ue_id_list[i].ue_id; // if at least one UE not present -> do not admit - if (not du_meas_provider.ue_supported(ueid)) { + if (not du_meas_provider.is_ue_supported(ueid)) { return false; } } diff --git a/lib/f1ap/du/f1ap_du_factory.cpp b/lib/f1ap/du/f1ap_du_factory.cpp index 6e1621f1bf..e9c4357191 100644 --- a/lib/f1ap/du/f1ap_du_factory.cpp +++ b/lib/f1ap/du/f1ap_du_factory.cpp @@ -22,9 +22,6 @@ #include "srsran/f1ap/du/f1ap_du_factory.h" #include "f1ap_du_impl.h" -#include "srsran/du/du_high/du_manager/du_manager.h" - -/// Notice this would be the only place were we include concrete class implementation files. using namespace srsran; using namespace srs_du; @@ -33,8 +30,10 @@ std::unique_ptr srsran::srs_du::create_f1ap(f1c_connection_client& f1ap_du_configurator& du_mng, task_executor& ctrl_exec, du_high_ue_executor_mapper& ue_exec_mapper, - f1ap_du_paging_notifier& paging_notifier) + f1ap_du_paging_notifier& paging_notifier, + srsran::timer_manager& timers) { - auto f1ap_du = std::make_unique(f1c_client_handler, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier); + auto f1ap_du = + std::make_unique(f1c_client_handler, du_mng, ctrl_exec, ue_exec_mapper, paging_notifier, timers); return f1ap_du; } diff --git a/lib/f1ap/du/f1ap_du_impl.cpp b/lib/f1ap/du/f1ap_du_impl.cpp index e3a153c307..52e1c50f1a 100644 --- a/lib/f1ap/du/f1ap_du_impl.cpp +++ b/lib/f1ap/du/f1ap_du_impl.cpp @@ -83,13 +83,14 @@ f1ap_du_impl::f1ap_du_impl(f1c_connection_client& f1c_client_handler_, f1ap_du_configurator& du_mng_, task_executor& ctrl_exec_, du_high_ue_executor_mapper& ue_exec_mapper_, - f1ap_du_paging_notifier& paging_notifier_) : + f1ap_du_paging_notifier& paging_notifier_, + timer_manager& timers_) : logger(srslog::fetch_basic_logger("DU-F1")), ctrl_exec(ctrl_exec_), du_mng(du_mng_), paging_notifier(paging_notifier_), connection_handler(f1c_client_handler_, *this, du_mng, ctrl_exec), - ues(du_mng, ctrl_exec, ue_exec_mapper_), + ues(du_mng, ctrl_exec, ue_exec_mapper_, timers_), events(std::make_unique(du_mng.get_timer_factory())) { } diff --git a/lib/f1ap/du/f1ap_du_impl.h b/lib/f1ap/du/f1ap_du_impl.h index 692c184f3a..0ac0cee712 100644 --- a/lib/f1ap/du/f1ap_du_impl.h +++ b/lib/f1ap/du/f1ap_du_impl.h @@ -43,7 +43,8 @@ class f1ap_du_impl final : public f1ap_du f1ap_du_configurator& task_sched_, task_executor& ctrl_exec, du_high_ue_executor_mapper& ue_exec_mapper, - f1ap_du_paging_notifier& paging_notifier_); + f1ap_du_paging_notifier& paging_notifier_, + timer_manager& timers_); ~f1ap_du_impl() override; bool connect_to_cu_cp() override; diff --git a/lib/f1ap/du/ue_context/f1ap_du_ue.h b/lib/f1ap/du/ue_context/f1ap_du_ue.h index c3effcfaf2..f99a7a45d2 100644 --- a/lib/f1ap/du/ue_context/f1ap_du_ue.h +++ b/lib/f1ap/du/ue_context/f1ap_du_ue.h @@ -41,11 +41,12 @@ class f1ap_du_ue f1ap_du_configurator& du_handler_, f1ap_message_notifier& f1ap_msg_notifier_, task_executor& ctrl_exec, - task_executor& ue_exec) : + task_executor& ue_exec, + timer_manager& timers) : context(ue_index_, gnb_f1ap_du_ue_id_), f1ap_msg_notifier(f1ap_msg_notifier_), du_handler(du_handler_), - bearers(context, f1ap_msg_notifier, du_handler, ctrl_exec, ue_exec) + bearers(context, f1ap_msg_notifier, du_handler, ctrl_exec, ue_exec, timers) { } diff --git a/lib/f1ap/du/ue_context/f1ap_du_ue_manager.h b/lib/f1ap/du/ue_context/f1ap_du_ue_manager.h index 2fc3fb7fc1..a8391fc99d 100644 --- a/lib/f1ap/du/ue_context/f1ap_du_ue_manager.h +++ b/lib/f1ap/du/ue_context/f1ap_du_ue_manager.h @@ -36,8 +36,9 @@ class f1ap_du_ue_manager public: f1ap_du_ue_manager(f1ap_du_configurator& du_handler_, task_executor& ctrl_exec_, - du_high_ue_executor_mapper& ue_exec_mapper_) : - du_handler(du_handler_), ctrl_exec(ctrl_exec_), ue_exec_mapper(ue_exec_mapper_) + du_high_ue_executor_mapper& ue_exec_mapper_, + timer_manager& timers_) : + du_handler(du_handler_), ctrl_exec(ctrl_exec_), ue_exec_mapper(ue_exec_mapper_), timers(timers_) { } @@ -50,8 +51,14 @@ class f1ap_du_ue_manager srsran_assert(not ues.contains(ue_index), "Duplicate ueId={} detected", ue_index); gnb_du_ue_f1ap_id_t f1ap_id = static_cast(next_gnb_f1ap_du_ue_id++); - ues.emplace( - ue_index, ue_index, f1ap_id, du_handler, *f1ap_msg_notifier, ctrl_exec, ue_exec_mapper.ctrl_executor(ue_index)); + ues.emplace(ue_index, + ue_index, + f1ap_id, + du_handler, + *f1ap_msg_notifier, + ctrl_exec, + ue_exec_mapper.ctrl_executor(ue_index), + timers); { std::lock_guard lock(map_mutex); @@ -116,6 +123,7 @@ class f1ap_du_ue_manager f1ap_message_notifier* f1ap_msg_notifier = nullptr; task_executor& ctrl_exec; du_high_ue_executor_mapper& ue_exec_mapper; + timer_manager& timers; uint64_t next_gnb_f1ap_du_ue_id = 0; diff --git a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp index 3265720729..26cd559997 100644 --- a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp +++ b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp @@ -28,7 +28,7 @@ #include "srsran/pdcp/pdcp_sn_util.h" #include "srsran/support/async/async_no_op_task.h" #include "srsran/support/async/async_timer.h" -#include "srsran/support/async/execute_on.h" +#include "srsran/support/async/execute_on_blocking.h" using namespace srsran; using namespace srsran::srs_du; @@ -141,7 +141,8 @@ f1c_other_srb_du_bearer::f1c_other_srb_du_bearer(f1ap_ue_context& ue_ctxt_ f1c_rx_sdu_notifier& f1c_sdu_notifier_, f1ap_du_configurator& du_configurator_, task_executor& ctrl_exec_, - task_executor& ue_exec_) : + task_executor& ue_exec_, + timer_manager& timers_) : ue_ctxt(ue_ctxt_), srb_id(srb_id_), f1ap_notifier(f1ap_notifier_), @@ -149,6 +150,7 @@ f1c_other_srb_du_bearer::f1c_other_srb_du_bearer(f1ap_ue_context& ue_ctxt_ du_configurator(du_configurator_), ctrl_exec(ctrl_exec_), ue_exec(ue_exec_), + timers(timers_), logger(srslog::fetch_basic_logger("DU-F1")), event_pool(MAX_CONCURRENT_PDU_EVENTS) { @@ -275,7 +277,7 @@ async_task f1c_other_srb_du_bearer::handle_pdu_and_await(byte_buffer sdu = std::move(pdu)](coro_context>& ctx) mutable { CORO_BEGIN(ctx); - CORO_AWAIT(execute_on_blocking(ue_exec)); + CORO_AWAIT(execute_on_blocking(ue_exec, timers)); // Forward SDU to lower layers. sdu_notifier.on_new_sdu(std::move(sdu)); @@ -284,7 +286,7 @@ async_task f1c_other_srb_du_bearer::handle_pdu_and_await(byte_buffer CORO_AWAIT_VALUE(result, wait_for_notification(pdcp_sn, tx_or_delivery, time_to_wait)); // Return back to control executor. - CORO_AWAIT(execute_on_blocking(ctrl_exec)); + CORO_AWAIT(execute_on_blocking(ctrl_exec, timers)); // True for success, false for timeout/cancel. CORO_RETURN(result.index() == 0); diff --git a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.h b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.h index ab510dbf70..1edc2c24a5 100644 --- a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.h +++ b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.h @@ -83,7 +83,8 @@ class f1c_other_srb_du_bearer final : public f1c_bearer f1c_rx_sdu_notifier& f1c_sdu_notifier_, f1ap_du_configurator& du_configurator_, task_executor& ctrl_exec_, - task_executor& ue_exec_); + task_executor& ue_exec_, + timer_manager& timers_); /// \brief Packs and forwards the UL RRC message transfer as per TS 38.473 section 8.4.3. /// \param[in] sdu The message to be encoded in the RRC container of the UL RRC message transfer message to transmit. @@ -126,6 +127,7 @@ class f1c_other_srb_du_bearer final : public f1c_bearer f1ap_du_configurator& du_configurator; task_executor& ctrl_exec; task_executor& ue_exec; + timer_manager& timers; srslog::basic_logger& logger; event_observer_type always_set_event; diff --git a/lib/f1ap/du/ue_context/ue_bearer_manager.cpp b/lib/f1ap/du/ue_context/ue_bearer_manager.cpp index 72d637c4db..9340d668a2 100644 --- a/lib/f1ap/du/ue_context/ue_bearer_manager.cpp +++ b/lib/f1ap/du/ue_context/ue_bearer_manager.cpp @@ -51,5 +51,5 @@ void ue_bearer_manager::add_f1c_bearer(srb_id_t srb_id, f1c_rx_sdu_notifier& rx_ f1c_bearers.emplace(srb_id_to_uint(srb_id), std::make_unique( - ue_ctx, srb_id, f1ap_notifier, rx_sdu_notif, du_configurator, ctrl_exec, ue_exec)); + ue_ctx, srb_id, f1ap_notifier, rx_sdu_notif, du_configurator, ctrl_exec, ue_exec, timers)); } diff --git a/lib/f1ap/du/ue_context/ue_bearer_manager.h b/lib/f1ap/du/ue_context/ue_bearer_manager.h index e4bf5a6c47..703976a382 100644 --- a/lib/f1ap/du/ue_context/ue_bearer_manager.h +++ b/lib/f1ap/du/ue_context/ue_bearer_manager.h @@ -35,6 +35,9 @@ #include "srsran/support/executors/task_executor.h" namespace srsran { + +class timer_manager; + namespace srs_du { class f1ap_event_manager; @@ -47,12 +50,14 @@ class ue_bearer_manager f1ap_message_notifier& f1ap_notif_, f1ap_du_configurator& du_configurator_, task_executor& ctrl_exec_, - task_executor& ue_exec_) : + task_executor& ue_exec_, + timer_manager& timers_) : ue_ctx(ue_ctx_), f1ap_notifier(f1ap_notif_), du_configurator(du_configurator_), ctrl_exec(ctrl_exec_), - ue_exec(ue_exec_) + ue_exec(ue_exec_), + timers(timers_) { } @@ -78,6 +83,7 @@ class ue_bearer_manager f1ap_du_configurator& du_configurator; task_executor& ctrl_exec; task_executor& ue_exec; + timer_manager& timers; slotted_array, MAX_NOF_SRBS> f1c_bearers; }; diff --git a/lib/fapi/validators/message_validators.cpp b/lib/fapi/validators/message_validators.cpp index 9759da4080..92be35759a 100644 --- a/lib/fapi/validators/message_validators.cpp +++ b/lib/fapi/validators/message_validators.cpp @@ -482,7 +482,7 @@ error_type srsran::fapi::validate_srs_indication(const srs_ind success &= validate_rnti(to_value(pdu.rnti), message_type_id::srs_indication, report); success &= validate_timing_advance_offset(pdu.timing_advance_offset, message_type_id::srs_indication, report); success &= validate_timing_advance_offset_ns(pdu.timing_advance_offset_ns, message_type_id::srs_indication, report); - success &= validate_srs_usage(static_cast(pdu.srs_usage), report); + success &= validate_srs_usage(static_cast(pdu.usage), report); success &= validate_report_type(pdu.report_type, report); } diff --git a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp index 79fb186aba..e1d5f02ac9 100644 --- a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp +++ b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp @@ -47,6 +47,8 @@ class mac_cell_control_information_handler_dummy : public mac_cell_control_infor void handle_crc(const mac_crc_indication_message& msg) override {} void handle_uci(const mac_uci_indication_message& msg) override {} + + void handle_srs(const mac_srs_indication_message& msg) override {} }; } // namespace @@ -61,7 +63,7 @@ static mac_pdu_handler_dummy dummy_pdu_handler; /// This dummy object is passed to the constructor of the FAPI-to-MAC message translator as a placeholder for the /// actual, cell-specific MAC CRC handler, which will be later set up through the \ref set_cell_crc_handler() method. -static mac_cell_control_information_handler_dummy dummy_crc_handler; +static mac_cell_control_information_handler_dummy dummy_cell_control_handler; /// Converts the given FAPI UCI SINR to dB as per SCF-222 v4.0 section 3.4.9. static float to_uci_ul_sinr(int sinr) @@ -100,7 +102,10 @@ static std::optional convert_fapi_to_mac_rsrp(uint16_t fapi_rsrp) } fapi_to_mac_data_msg_translator::fapi_to_mac_data_msg_translator(subcarrier_spacing scs_) : - scs(scs_), rach_handler(dummy_mac_rach_handler), pdu_handler(dummy_pdu_handler), crc_handler(dummy_crc_handler) + scs(scs_), + rach_handler(dummy_mac_rach_handler), + pdu_handler(dummy_pdu_handler), + cell_control_handler(dummy_cell_control_handler) { } @@ -152,15 +157,16 @@ void fapi_to_mac_data_msg_translator::on_crc_indication(const fapi::crc_indicati } } - crc_handler.get().handle_crc(indication); + cell_control_handler.get().handle_crc(indication); } /// Converts the given FAPI Timing Advance Offset in nanoseconds to Physical layer time unit. -static void convert_fapi_to_mac_ta_offset(std::optional& mac_ta_offset, int16_t fapi_ta_offset_ns) +static std::optional convert_fapi_to_mac_ta_offset(int16_t fapi_ta_offset_ns) { if (fapi_ta_offset_ns != std::numeric_limits::min()) { - mac_ta_offset = phy_time_unit::from_seconds(static_cast(fapi_ta_offset_ns) * 1e-9); + return phy_time_unit::from_seconds(static_cast(fapi_ta_offset_ns) * 1e-9); } + return std::nullopt; } /// Converts the given FAPI UCI RSSI to dB as per SCF-222 v4.0 section 3.4.9. @@ -182,10 +188,10 @@ static bool is_fapi_uci_payload_valid(uci_pusch_or_pucch_f2_3_4_detection_status static void convert_fapi_to_mac_pucch_f0_f1_uci_ind(mac_uci_pdu::pucch_f0_or_f1_type& mac_pucch, const fapi::uci_pucch_pdu_format_0_1& fapi_pucch) { - mac_pucch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pucch.ul_sinr_metric); - mac_pucch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pucch.rssi); - mac_pucch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pucch.rsrp); - convert_fapi_to_mac_ta_offset(mac_pucch.time_advance_offset, fapi_pucch.timing_advance_offset_ns); + mac_pucch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pucch.ul_sinr_metric); + mac_pucch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pucch.rssi); + mac_pucch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pucch.rsrp); + mac_pucch.time_advance_offset = convert_fapi_to_mac_ta_offset(fapi_pucch.timing_advance_offset_ns); // Fill SR. if (fapi_pucch.pdu_bitmap.test(fapi::uci_pucch_pdu_format_0_1::SR_BIT)) { @@ -200,10 +206,10 @@ static void convert_fapi_to_mac_pucch_f0_f1_uci_ind(mac_uci_pdu::pucch_f0_or_f1_ static void convert_fapi_to_mac_pusch_uci_ind(mac_uci_pdu::pusch_type& mac_pusch, const fapi::uci_pusch_pdu& fapi_pusch) { - mac_pusch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pusch.ul_sinr_metric); - mac_pusch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pusch.rssi); - mac_pusch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pusch.rsrp); - convert_fapi_to_mac_ta_offset(mac_pusch.time_advance_offset, fapi_pusch.timing_advance_offset_ns); + mac_pusch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pusch.ul_sinr_metric); + mac_pusch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pusch.rssi); + mac_pusch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pusch.rsrp); + mac_pusch.time_advance_offset = convert_fapi_to_mac_ta_offset(fapi_pusch.timing_advance_offset_ns); // Fill HARQ. if (fapi_pusch.pdu_bitmap.test(fapi::uci_pusch_pdu::HARQ_BIT)) { @@ -234,10 +240,10 @@ static void convert_fapi_to_mac_pusch_uci_ind(mac_uci_pdu::pusch_type& mac_pusch static void convert_fapi_to_mac_pucch_f2_f3_f4_uci_ind(mac_uci_pdu::pucch_f2_or_f3_or_f4_type& mac_pucch, const fapi::uci_pucch_pdu_format_2_3_4& fapi_pucch) { - mac_pucch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pucch.ul_sinr_metric); - mac_pucch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pucch.rssi); - mac_pucch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pucch.rsrp); - convert_fapi_to_mac_ta_offset(mac_pucch.time_advance_offset, fapi_pucch.timing_advance_offset_ns); + mac_pucch.ul_sinr_dB = convert_fapi_to_mac_ul_sinr(fapi_pucch.ul_sinr_metric); + mac_pucch.rssi_dBFS = convert_fapi_to_mac_rssi(fapi_pucch.rssi); + mac_pucch.rsrp_dBFS = convert_fapi_to_mac_rsrp(fapi_pucch.rsrp); + mac_pucch.time_advance_offset = convert_fapi_to_mac_ta_offset(fapi_pucch.timing_advance_offset_ns); // Fill SR. if (fapi_pucch.pdu_bitmap.test(fapi::uci_pucch_pdu_format_2_3_4::SR_BIT)) { @@ -303,10 +309,23 @@ void fapi_to_mac_data_msg_translator::on_uci_indication(const fapi::uci_indicati } } - crc_handler.get().handle_uci(mac_msg); + cell_control_handler.get().handle_uci(mac_msg); } -void fapi_to_mac_data_msg_translator::on_srs_indication(const fapi::srs_indication_message& msg) {} +void fapi_to_mac_data_msg_translator::on_srs_indication(const fapi::srs_indication_message& msg) +{ + mac_srs_indication_message mac_msg; + mac_msg.sl_rx = slot_point(scs, msg.sfn, msg.slot); + + for (const auto& pdu : msg.pdus) { + mac_srs_pdu& mac_pdu = mac_msg.srss.emplace_back(); + mac_pdu.rnti = pdu.rnti; + mac_pdu.time_advance_offset = convert_fapi_to_mac_ta_offset(pdu.timing_advance_offset_ns); + mac_pdu.channel_matrix = pdu.matrix; + } + + cell_control_handler.get().handle_srs(mac_msg); +} /// Converts the given FAPI RACH occasion RSSI to dB as per SCF-222 v4.0 section 3.4.11. static float to_prach_rssi_dB(int fapi_rssi) @@ -367,5 +386,5 @@ void fapi_to_mac_data_msg_translator::set_cell_pdu_handler(mac_pdu_handler& hand void fapi_to_mac_data_msg_translator::set_cell_crc_handler(mac_cell_control_information_handler& handler) { - crc_handler = std::ref(handler); + cell_control_handler = std::ref(handler); } diff --git a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.h b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.h index 9e997c1bc1..94c14c17a1 100644 --- a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.h +++ b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.h @@ -67,7 +67,7 @@ class fapi_to_mac_data_msg_translator : public fapi::slot_data_message_notifier const subcarrier_spacing scs; std::reference_wrapper rach_handler; std::reference_wrapper pdu_handler; - std::reference_wrapper crc_handler; + std::reference_wrapper cell_control_handler; }; } // namespace fapi_adaptor diff --git a/lib/mac/mac_dl/mac_cell_processor.cpp b/lib/mac/mac_dl/mac_cell_processor.cpp index 889e517a63..733af65298 100644 --- a/lib/mac/mac_dl/mac_cell_processor.cpp +++ b/lib/mac/mac_dl/mac_cell_processor.cpp @@ -24,7 +24,7 @@ #include "srsran/instrumentation/traces/du_traces.h" #include "srsran/mac/mac_cell_result.h" #include "srsran/ran/pdsch/pdsch_constants.h" -#include "srsran/support/async/execute_on.h" +#include "srsran/support/async/execute_on_blocking.h" using namespace srsran; @@ -38,13 +38,15 @@ mac_cell_processor::mac_cell_processor(const mac_cell_creation_request& cell_cfg task_executor& cell_exec_, task_executor& slot_exec_, task_executor& ctrl_exec_, - mac_pcap& pcap_) : + mac_pcap& pcap_, + timer_manager& timers_) : logger(srslog::fetch_basic_logger("MAC")), cell_cfg(cell_cfg_req_), cell_exec(cell_exec_), slot_exec(slot_exec_), ctrl_exec(ctrl_exec_), phy_cell(phy_notifier_), + timers(timers_), ue_mng(rnti_table), dl_harq_buffers(band_helper::get_n_rbs_from_bw(MHz_to_bs_channel_bandwidth(cell_cfg.dl_carrier.carrier_bw_mhz), cell_cfg.scs_common, @@ -68,21 +70,35 @@ mac_cell_processor::mac_cell_processor(const mac_cell_creation_request& cell_cfg async_task mac_cell_processor::start() { - return execute_and_continue_on_blocking(cell_exec, ctrl_exec, [this]() { state = cell_state::active; }); + return execute_and_continue_on_blocking( + cell_exec, + ctrl_exec, + timers, + [this]() { state = cell_state::active; }, + [this, cell_index = cell_cfg.cell_index]() { + logger.warning("cell={}: Postponed cell start operation. Cause: Task queue is full", cell_index); + }); } async_task mac_cell_processor::stop() { - return execute_and_continue_on_blocking(cell_exec, ctrl_exec, [this]() { - if (state == cell_state::inactive) { - return; - } + return execute_and_continue_on_blocking( + cell_exec, + ctrl_exec, + timers, + [this]() { + if (state == cell_state::inactive) { + return; + } - // Set cell state as inactive to stop answering to slot indications. - state = cell_state::inactive; + // Set cell state as inactive to stop answering to slot indications. + state = cell_state::inactive; - logger.info("cell={}: Cell was stopped.", cell_cfg.cell_index); - }); + logger.info("cell={}: Cell was stopped.", cell_cfg.cell_index); + }, + [this, cell_index = cell_cfg.cell_index]() { + logger.warning("cell={}: Postponed cell stop operation. Cause: Task queue is full", cell_index); + }); } void mac_cell_processor::handle_slot_indication(slot_point sl_tx) @@ -114,28 +130,39 @@ async_task mac_cell_processor::add_ue(const mac_ue_create_request& request mac_dl_ue_context ue_inst(request); // > Update the UE context inside the cell executor. - return execute_and_continue_on_blocking(cell_exec, ctrl_exec, [this, ue_inst = std::move(ue_inst)]() mutable { - // > Insert UE and DL bearers. - // Note: Ensure we only do so if the cell is active. - return state == cell_state::active and ue_mng.add_ue(std::move(ue_inst)); - }); + return execute_and_continue_on_blocking( + cell_exec, + ctrl_exec, + timers, + [this, ue_inst = std::move(ue_inst)]() mutable { + // > Insert UE and DL bearers. + // Note: Ensure we only do so if the cell is active. + return state == cell_state::active and ue_mng.add_ue(std::move(ue_inst)); + }, + [this, ue_index = request.ue_index]() { + logger.warning("ue={}: Postponed UE creation. Cause: Task queue is full", ue_index); + }); } async_task mac_cell_processor::remove_ue(const mac_ue_delete_request& request) { - return launch_async([this, request](coro_context>& ctx) mutable { + auto log_dispatch_failure = [this, ue_index = request.ue_index]() { + logger.warning("ue={}: Postponed UE removal. Cause: task queue is full", ue_index); + }; + + return launch_async([this, request, log_dispatch_failure](coro_context>& ctx) mutable { CORO_BEGIN(ctx); // Change to respective DL cell executor. // Note: Caller (ctrl exec) blocks if the cell executor is full. - CORO_AWAIT(execute_on_blocking(cell_exec)); + CORO_AWAIT(execute_on_blocking(cell_exec, timers, log_dispatch_failure)); // Remove UE associated DL channels ue_mng.remove_ue(request.ue_index); // Change back to CTRL executor before returning // Note: Blocks if the executor is full (which should never happen). - CORO_AWAIT(execute_on_blocking(ctrl_exec)); + CORO_AWAIT(execute_on_blocking(ctrl_exec, timers, log_dispatch_failure)); // Deallocate DL HARQ buffers back in the CTRL executor. dl_harq_buffers.deallocate_ue_buffers(request.ue_index); @@ -147,20 +174,34 @@ async_task mac_cell_processor::remove_ue(const mac_ue_delete_request& requ async_task mac_cell_processor::addmod_bearers(du_ue_index_t ue_index, const std::vector& logical_channels) { - return execute_and_continue_on_blocking(cell_exec, ctrl_exec, [this, ue_index, logical_channels]() { - // Configure logical channels. - return state == cell_state::active and ue_mng.addmod_bearers(ue_index, logical_channels); - }); + return execute_and_continue_on_blocking( + cell_exec, + ctrl_exec, + timers, + [this, ue_index, logical_channels]() { + // Configure logical channels. + return state == cell_state::active and ue_mng.addmod_bearers(ue_index, logical_channels); + }, + [this, ue_index]() { + logger.warning("ue={}: Postponed UE bearer add/mod operation. Cause: Task queue is full", ue_index); + }); } async_task mac_cell_processor::remove_bearers(du_ue_index_t ue_index, span lcids_to_rem) { std::vector lcids(lcids_to_rem.begin(), lcids_to_rem.end()); - return execute_and_continue_on_blocking(cell_exec, ctrl_exec, [this, ue_index, lcids = std::move(lcids)]() { - // Remove logical channels. - return ue_mng.remove_bearers(ue_index, lcids); - }); + return execute_and_continue_on_blocking( + cell_exec, + ctrl_exec, + timers, + [this, ue_index, lcids = std::move(lcids)]() { + // Remove logical channels. + return ue_mng.remove_bearers(ue_index, lcids); + }, + [this, ue_index]() { + logger.warning("ue={}: Postponed UE bearer removal. Cause: Task queue is full", ue_index); + }); } void mac_cell_processor::handle_slot_indication_impl(slot_point sl_tx) diff --git a/lib/mac/mac_dl/mac_cell_processor.h b/lib/mac/mac_dl/mac_cell_processor.h index 0ba5167404..5d203757b2 100644 --- a/lib/mac/mac_dl/mac_cell_processor.h +++ b/lib/mac/mac_dl/mac_cell_processor.h @@ -38,6 +38,8 @@ namespace srsran { +class timer_manager; + class mac_cell_processor final : public mac_cell_slot_handler, public mac_cell_controller { public: @@ -48,7 +50,8 @@ class mac_cell_processor final : public mac_cell_slot_handler, public mac_cell_c task_executor& cell_exec, task_executor& slot_exec, task_executor& ctrl_exec, - mac_pcap& pcap); + mac_pcap& pcap, + timer_manager& timers); /// Starts configured cell. async_task start() override; @@ -100,6 +103,7 @@ class mac_cell_processor final : public mac_cell_slot_handler, public mac_cell_c task_executor& slot_exec; task_executor& ctrl_exec; mac_cell_result_notifier& phy_cell; + timer_manager& timers; // Mapper of upper-layer bearers to MAC logical channels in the DL direction. mac_dl_ue_repository ue_mng; diff --git a/lib/mac/mac_dl/mac_dl_processor.cpp b/lib/mac/mac_dl/mac_dl_processor.cpp index 18ebe3a8f9..f9f62241d8 100644 --- a/lib/mac/mac_dl/mac_dl_processor.cpp +++ b/lib/mac/mac_dl/mac_dl_processor.cpp @@ -50,7 +50,8 @@ void mac_dl_processor::add_cell(const mac_cell_creation_request& cell_cfg_req) cfg.cell_exec_mapper.executor(cell_cfg_req.cell_index), cfg.cell_exec_mapper.slot_ind_executor(cell_cfg_req.cell_index), cfg.ctrl_exec, - cfg.pcap); + cfg.pcap, + cfg.timers); } void mac_dl_processor::remove_cell(du_cell_index_t cell_index) diff --git a/lib/mac/mac_dl/mac_dl_processor.h b/lib/mac/mac_dl/mac_dl_processor.h index 50cafda1ad..6ce0a87e4d 100644 --- a/lib/mac/mac_dl/mac_dl_processor.h +++ b/lib/mac/mac_dl/mac_dl_processor.h @@ -38,6 +38,7 @@ struct mac_dl_config { task_executor& ctrl_exec; mac_result_notifier& phy_notifier; mac_pcap& pcap; + timer_manager& timers; }; class mac_dl_processor final : public mac_dl_configurator diff --git a/lib/mac/mac_impl.cpp b/lib/mac/mac_impl.cpp index cce65215ff..7dca571919 100644 --- a/lib/mac/mac_impl.cpp +++ b/lib/mac/mac_impl.cpp @@ -28,16 +28,21 @@ namespace srsran { mac_impl::mac_impl(const mac_config& params) : rnti_table(params.mac_cfg.initial_crnti), mac_sched(std::make_unique(params, rnti_table)), - dl_unit( - mac_dl_config{params.ue_exec_mapper, params.cell_exec_mapper, params.ctrl_exec, params.phy_notifier, params.pcap}, - *mac_sched, - rnti_table), + dl_unit(mac_dl_config{params.ue_exec_mapper, + params.cell_exec_mapper, + params.ctrl_exec, + params.phy_notifier, + params.pcap, + params.timers}, + *mac_sched, + rnti_table), ul_unit(mac_ul_config{params.ctrl_exec, params.ue_exec_mapper, params.ul_ccch_notifier, *mac_sched, rnti_table, - params.pcap}), + params.pcap, + params.timers}), ctrl_unit( mac_control_config{params.ul_ccch_notifier, params.ue_exec_mapper, params.cell_exec_mapper, params.ctrl_exec}, ul_unit, diff --git a/lib/mac/mac_sched/srsran_scheduler_adapter.cpp b/lib/mac/mac_sched/srsran_scheduler_adapter.cpp index ef9e9a11cb..39ca64dae7 100644 --- a/lib/mac/mac_sched/srsran_scheduler_adapter.cpp +++ b/lib/mac/mac_sched/srsran_scheduler_adapter.cpp @@ -21,7 +21,6 @@ */ #include "srsran_scheduler_adapter.h" -#include "../mac_ul/ul_bsr.h" #include "srsran/scheduler/scheduler_factory.h" using namespace srsran; @@ -310,7 +309,7 @@ void srsran_scheduler_adapter::cell_handler::handle_crc(const mac_crc_indication ind.cell_index = cell_idx; ind.sl_rx = msg.sl_rx; ind.crcs.resize(msg.crcs.size()); - for (unsigned i = 0; i != msg.crcs.size(); ++i) { + for (unsigned i = 0, size = msg.crcs.size(); i != size; ++i) { const mac_crc_pdu& mac_pdu = msg.crcs[i]; ul_crc_pdu_indication& pdu = ind.crcs[i]; pdu.rnti = mac_pdu.rnti; @@ -326,11 +325,11 @@ void srsran_scheduler_adapter::cell_handler::handle_crc(const mac_crc_indication parent->sched_impl->handle_crc_indication(ind); // Report to RLF handler the CRC result. - for (unsigned i = 0; i != ind.crcs.size(); ++i) { + for (const auto& crc : ind.crcs) { // If Msg3, ignore the CRC result. // Note: UE index is invalid for Msg3 CRCs because no UE has been allocated yet. - if (ind.crcs[i].ue_index != INVALID_DU_UE_INDEX) { - parent->rlf_handler.handle_crc(ind.crcs[i].ue_index, cell_idx, ind.crcs[i].tb_crc_success); + if (crc.ue_index != INVALID_DU_UE_INDEX) { + parent->rlf_handler.handle_crc(crc.ue_index, cell_idx, crc.tb_crc_success); } } } @@ -340,3 +339,16 @@ void srsran_scheduler_adapter::cell_handler::handle_uci(const mac_uci_indication // Forward UCI indication to the scheduler. parent->sched_impl->handle_uci_indication(uci_decoder.decode_uci(msg)); } + +void srsran_scheduler_adapter::cell_handler::handle_srs(const mac_srs_indication_message& msg) +{ + srs_indication ind; + ind.cell_index = cell_idx; + ind.slot_rx = msg.sl_rx; + for (const auto& mac_pdu : msg.srss) { + ind.srss.emplace_back( + parent->rnti_mng[mac_pdu.rnti], mac_pdu.rnti, mac_pdu.time_advance_offset, mac_pdu.channel_matrix); + } + // Forward SRS indication to the scheduler. + parent->sched_impl->handle_srs_indication(ind); +} diff --git a/lib/mac/mac_sched/srsran_scheduler_adapter.h b/lib/mac/mac_sched/srsran_scheduler_adapter.h index c5936cbd30..186987d9e3 100644 --- a/lib/mac/mac_sched/srsran_scheduler_adapter.h +++ b/lib/mac/mac_sched/srsran_scheduler_adapter.h @@ -105,6 +105,8 @@ class srsran_scheduler_adapter final : public mac_scheduler_adapter void handle_uci(const mac_uci_indication_message& msg) override; + void handle_srs(const mac_srs_indication_message& msg) override; + uci_cell_decoder uci_decoder; private: diff --git a/lib/mac/mac_ul/mac_ul_processor.cpp b/lib/mac/mac_ul/mac_ul_processor.cpp index cbaa895ff1..475fd876fb 100644 --- a/lib/mac/mac_ul/mac_ul_processor.cpp +++ b/lib/mac/mac_ul/mac_ul_processor.cpp @@ -22,6 +22,7 @@ #include "mac_ul_processor.h" #include "srsran/srslog/srslog.h" +#include "srsran/support/async/execute_on_blocking.h" using namespace srsran; @@ -41,15 +42,25 @@ async_task mac_ul_processor::add_ue(const mac_ue_create_request& request) // Dispatch UE creation task to new UL executor. return execute_and_continue_on_blocking( - ul_exec, cfg.ctrl_exec, [this, request]() { return ue_manager.add_ue(request); }); + ul_exec, + cfg.ctrl_exec, + cfg.timers, + [this, request]() { return ue_manager.add_ue(request); }, + [this, ue_idx = request.ue_index]() { + logger.warning("ue={}: Postponed UE creation. Cause: Task queue is full", ue_idx); + }); } async_task mac_ul_processor::addmod_bearers(du_ue_index_t ue_index, const std::vector& ul_logical_channels) { return execute_and_continue_on_blocking( - cfg.ue_exec_mapper.ctrl_executor(ue_index), cfg.ctrl_exec, [this, ue_index, ul_logical_channels]() { - return ue_manager.addmod_bearers(ue_index, ul_logical_channels); + cfg.ue_exec_mapper.ctrl_executor(ue_index), + cfg.ctrl_exec, + cfg.timers, + [this, ue_index, ul_logical_channels]() { return ue_manager.addmod_bearers(ue_index, ul_logical_channels); }, + [this, ue_index]() { + logger.warning("ue={}: Postponed UE bearer add/mod operation. Cause: Task queue is full", ue_index); }); } @@ -57,16 +68,25 @@ async_task mac_ul_processor::remove_bearers(du_ue_index_t ue_index, span lcids(lcids_to_rem.begin(), lcids_to_rem.end()); return execute_and_continue_on_blocking( - cfg.ue_exec_mapper.ctrl_executor(ue_index), cfg.ctrl_exec, [this, ue_index, lcids = std::move(lcids)]() { - return ue_manager.remove_bearers(ue_index, lcids); + cfg.ue_exec_mapper.ctrl_executor(ue_index), + cfg.ctrl_exec, + cfg.timers, + [this, ue_index, lcids = std::move(lcids)]() { return ue_manager.remove_bearers(ue_index, lcids); }, + [this, ue_index]() { + logger.warning("ue={}: Postponed UE bearer removal. Cause: Task queue is full", ue_index); }); } async_task mac_ul_processor::remove_ue(const mac_ue_delete_request& msg) { - return execute_and_continue_on_blocking(cfg.ue_exec_mapper.ctrl_executor(msg.ue_index), - cfg.ctrl_exec, - [this, ue_index = msg.ue_index]() { ue_manager.remove_ue(ue_index); }); + return execute_and_continue_on_blocking( + cfg.ue_exec_mapper.ctrl_executor(msg.ue_index), + cfg.ctrl_exec, + cfg.timers, + [this, ue_index = msg.ue_index]() { ue_manager.remove_ue(ue_index); }, + [this, ue_index = msg.ue_index]() { + logger.warning("ue={}: Postponed UE removal. Cause: Task queue is full", ue_index); + }); } bool mac_ul_processor::flush_ul_ccch_msg(du_ue_index_t ue_index, byte_buffer ccch_pdu) diff --git a/lib/mac/mac_ul/mac_ul_processor.h b/lib/mac/mac_ul/mac_ul_processor.h index 49e68db8f4..a07f4b21e9 100644 --- a/lib/mac/mac_ul/mac_ul_processor.h +++ b/lib/mac/mac_ul/mac_ul_processor.h @@ -29,10 +29,11 @@ #include "srsran/mac/mac.h" #include "srsran/mac/mac_config.h" #include "srsran/scheduler/scheduler_feedback_handler.h" -#include "srsran/support/async/execute_on.h" namespace srsran { +class timer_manager; + struct mac_ul_config { task_executor& ctrl_exec; srs_du::du_high_ue_executor_mapper& ue_exec_mapper; @@ -40,6 +41,7 @@ struct mac_ul_config { mac_scheduler_ce_info_handler& sched; du_rnti_table& rnti_table; mac_pcap& pcap; + timer_manager& timers; }; class mac_ul_processor final : public mac_ul_configurator, public mac_pdu_handler diff --git a/lib/scheduler/cell_scheduler.cpp b/lib/scheduler/cell_scheduler.cpp index 9e3386ba89..9806ab35c1 100644 --- a/lib/scheduler/cell_scheduler.cpp +++ b/lib/scheduler/cell_scheduler.cpp @@ -41,7 +41,7 @@ cell_scheduler::cell_scheduler(const scheduler_expert_config& s ssb_sch(cell_cfg), pdcch_sch(cell_cfg), csi_sch(cell_cfg), - ra_sch(sched_cfg.ra, cell_cfg, pdcch_sch, event_logger), + ra_sch(sched_cfg.ra, cell_cfg, pdcch_sch, event_logger, metrics), prach_sch(cell_cfg), pucch_alloc(cell_cfg, sched_cfg.ue.max_pucchs_per_slot, sched_cfg.ue.max_ul_grants_per_slot), uci_alloc(pucch_alloc), diff --git a/lib/scheduler/common_scheduling/ra_scheduler.cpp b/lib/scheduler/common_scheduling/ra_scheduler.cpp index eb9ce518e6..612eababdf 100644 --- a/lib/scheduler/common_scheduling/ra_scheduler.cpp +++ b/lib/scheduler/common_scheduling/ra_scheduler.cpp @@ -22,6 +22,7 @@ #include "ra_scheduler.h" #include "../logging/scheduler_event_logger.h" +#include "../logging/scheduler_metrics_handler.h" #include "../pdcch_scheduling/pdcch_resource_allocator_impl.h" #include "../support/dci_builder.h" #include "../support/dmrs_helpers.h" @@ -111,11 +112,13 @@ static constexpr size_t CRC_IND_QUEUE_SIZE = MAX_PUCCH_PDUS_PER_SLOT * 2; ra_scheduler::ra_scheduler(const scheduler_ra_expert_config& sched_cfg_, const cell_configuration& cellcfg_, pdcch_resource_allocator& pdcch_sch_, - scheduler_event_logger& ev_logger_) : + scheduler_event_logger& ev_logger_, + cell_metrics_handler& metrics_hdlr_) : sched_cfg(sched_cfg_), cell_cfg(cellcfg_), pdcch_sch(pdcch_sch_), ev_logger(ev_logger_), + metrics_hdlr(metrics_hdlr_), ra_win_nof_slots(cell_cfg.ul_cfg_common.init_ul_bwp.rach_cfg_common->rach_cfg_generic.ra_resp_window), ra_crb_lims( pdsch_helper::get_ra_crb_limits_common(cell_cfg.dl_cfg_common.init_dl_bwp, @@ -299,6 +302,9 @@ void ra_scheduler::handle_rach_indication_impl(const rach_indication_message& ms msg3_entry.msg3_harq_ent = msg3_harqs.add_ue(to_du_ue_index(msg3_ring_idx), prach_preamble.tc_rnti, 1, 1); } } + + // Forward RACH indication to metrics handler. + metrics_hdlr.handle_rach_indication(msg); } void ra_scheduler::handle_crc_indication(const ul_crc_indication& crc_ind) diff --git a/lib/scheduler/common_scheduling/ra_scheduler.h b/lib/scheduler/common_scheduling/ra_scheduler.h index f3e8ea2b4b..a595e5fa69 100644 --- a/lib/scheduler/common_scheduling/ra_scheduler.h +++ b/lib/scheduler/common_scheduling/ra_scheduler.h @@ -36,6 +36,7 @@ namespace srsran { class scheduler_event_logger; +class cell_metrics_handler; /// Get MSG3 Delay. /// \param[in] pusch_td_res_alloc PUSCH-TimeDomainResourceAllocation. @@ -58,7 +59,8 @@ class ra_scheduler explicit ra_scheduler(const scheduler_ra_expert_config& sched_cfg_, const cell_configuration& cfg_, pdcch_resource_allocator& pdcch_sched_, - scheduler_event_logger& ev_logger_); + scheduler_event_logger& ev_logger_, + cell_metrics_handler& metrics_handler_); /// Enqueue RACH indication /// \remark See TS 38.321, 5.1.3 - RAP transmission. @@ -162,6 +164,7 @@ class ra_scheduler const cell_configuration& cell_cfg; pdcch_resource_allocator& pdcch_sch; scheduler_event_logger& ev_logger; + cell_metrics_handler& metrics_hdlr; // derived from args srslog::basic_logger& logger = srslog::fetch_basic_logger("SCHED"); diff --git a/lib/scheduler/config/serving_cell_config_factory.cpp b/lib/scheduler/config/serving_cell_config_factory.cpp index e4c553b012..bc5a08e5d3 100644 --- a/lib/scheduler/config/serving_cell_config_factory.cpp +++ b/lib/scheduler/config/serving_cell_config_factory.cpp @@ -520,7 +520,7 @@ srs_config srsran::config_helpers::make_default_srs_config(const cell_config_bui res_set.res_type = srs_config::srs_resource_set::aperiodic_resource_type{.aperiodic_srs_res_trigger = 1, .slot_offset = 7}; - res_set.srs_res_set_usage = srs_config::srs_resource_set::usage::codebook; + res_set.srs_res_set_usage = srs_usage::codebook; res_set.p0 = -84; res_set.pathloss_ref_rs = static_cast(0); diff --git a/lib/scheduler/config/serving_cell_config_validator.cpp b/lib/scheduler/config/serving_cell_config_validator.cpp index 31d54783e1..eea90cddd4 100644 --- a/lib/scheduler/config/serving_cell_config_validator.cpp +++ b/lib/scheduler/config/serving_cell_config_validator.cpp @@ -428,8 +428,7 @@ validator_result srsran::config_validators::validate_srs_cfg(const serving_cell_ VERIFY(srs_cfg.srs_res_set_list.front().srs_res_id_list.front() == srs_cfg.srs_res_list.front().id.ue_res_id, "The SRS resource set ID 0's resource should point to the SRS resource ID 0"); const auto& srs_res_set = srs_cfg.srs_res_set_list.front(); - VERIFY(srs_res_set.srs_res_set_usage == srs_config::srs_resource_set::usage::codebook, - "Only SRS resource set usage \"codebook\" is supported"); + VERIFY(srs_res_set.srs_res_set_usage == srs_usage::codebook, "Only SRS resource set usage \"codebook\" is supported"); const auto& srs_res = srs_cfg.srs_res_list.front(); VERIFY( diff --git a/lib/scheduler/config/ue_configuration.cpp b/lib/scheduler/config/ue_configuration.cpp index d34b226144..d99e0d76ec 100644 --- a/lib/scheduler/config/ue_configuration.cpp +++ b/lib/scheduler/config/ue_configuration.cpp @@ -209,9 +209,7 @@ static dci_size_config get_dci_size_config(const ue_cell_configuration& ue_cell_ } } if (opt_srs_cfg.has_value()) { - const srs_config::srs_resource_set::usage usage = dci_sz_cfg.tx_config_non_codebook - ? srs_config::srs_resource_set::usage::non_codebook - : srs_config::srs_resource_set::usage::codebook; + const srs_usage usage = dci_sz_cfg.tx_config_non_codebook ? srs_usage::non_codebook : srs_usage::codebook; // See TS 38.214, clause 6.1.1.1 and 6.1.1.2. const auto* srs_res_set = std::find_if( opt_srs_cfg.value().srs_res_set_list.begin(), diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index f3d8648c1b..44ba30359b 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -22,6 +22,7 @@ #include "../config/cell_configuration.h" #include "scheduler_metrics_handler.h" +#include "srsran/scheduler/scheduler_configurator.h" #include "srsran/srslog/srslog.h" using namespace srsran; @@ -63,6 +64,13 @@ void cell_metrics_handler::handle_ue_deletion(du_ue_index_t ue_index) } } +void cell_metrics_handler::handle_rach_indication(const rach_indication_message& msg) +{ + for (auto& occ : msg.occasions) { + nof_prach_preambles += occ.preambles.size(); + } +} + void cell_metrics_handler::handle_crc_indication(const ul_crc_pdu_indication& crc_pdu, units::bytes tbs) { if (ues.contains(crc_pdu.ue_index)) { @@ -224,6 +232,7 @@ void cell_metrics_handler::report_metrics() next_report.nof_prbs = cell_cfg.nof_dl_prbs; // TODO: to be removed from the report. next_report.nof_dl_slots = nof_dl_slots; next_report.nof_ul_slots = nof_ul_slots; + next_report.nof_prach_preambles = nof_prach_preambles; // Reset cell-wide metric counters. error_indication_counter = 0; @@ -231,6 +240,7 @@ void cell_metrics_handler::report_metrics() decision_latency_hist = {}; nof_dl_slots = 0; nof_ul_slots = 0; + nof_prach_preambles = 0; // Report all UE metrics in a batch. notifier.report_metrics(next_report); @@ -300,10 +310,10 @@ void cell_metrics_handler::handle_slot_result(const sched_result& slot_res decision_latency_hist[bin_idx]++; } -void cell_metrics_handler::handle_ul_delay(du_ue_index_t ue_index, double delay) +void cell_metrics_handler::handle_ul_delay(du_ue_index_t ue_index, double delay_ms) { if (ues.contains(ue_index)) { - ues[ue_index].data.sum_ul_delay_ms += delay; + ues[ue_index].data.sum_ul_delay_ms += delay_ms; } } @@ -352,7 +362,7 @@ cell_metrics_handler::ue_metric_context::compute_report(std::chrono::millisecond ret.pusch_rsrp_db = data.nof_pusch_rsrp_reports > 0 ? data.sum_pusch_rsrp / data.nof_pusch_rsrp_reports : -std::numeric_limits::infinity(); ret.pucch_snr_db = data.nof_pucch_snr_reports > 0 ? data.sum_pucch_snrs / data.nof_pucch_snr_reports : 0; - ret.ul_delay_ms = data.sum_ul_delay_ms / data.count_crc_pdus; + ret.ul_delay_ms = data.count_crc_pdus > 0 ? data.sum_ul_delay_ms / data.count_crc_pdus : 0; ret.bsr = last_bsr; ret.dl_bs = 0; for (const unsigned value : last_dl_bs) { diff --git a/lib/scheduler/logging/scheduler_metrics_handler.h b/lib/scheduler/logging/scheduler_metrics_handler.h index 6e33383e7b..a3ae651d28 100644 --- a/lib/scheduler/logging/scheduler_metrics_handler.h +++ b/lib/scheduler/logging/scheduler_metrics_handler.h @@ -33,6 +33,7 @@ namespace srsran { class cell_configuration; +struct rach_indication_message; ///\brief Handler of scheduler slot metrics for a given cell. class cell_metrics_handler final : public harq_timeout_handler, public sched_metrics_ue_configurator @@ -105,6 +106,9 @@ class cell_metrics_handler final : public harq_timeout_handler, public sched_met /// Number of full uplink slots. unsigned nof_ul_slots = 0; + // Number of PRACH preambles + + unsigned nof_prach_preambles = 0; /// Counter of number of slots elapsed since the last report. unsigned slot_counter = 0; @@ -127,6 +131,9 @@ class cell_metrics_handler final : public harq_timeout_handler, public sched_met /// \brief Register removal of a UE. void handle_ue_deletion(du_ue_index_t ue_index) override; + /// \brief Register detected PRACH. + void handle_rach_indication(const rach_indication_message& msg); + /// \brief Register CRC indication. void handle_crc_indication(const ul_crc_pdu_indication& crc_pdu, units::bytes tbs); @@ -151,7 +158,7 @@ class cell_metrics_handler final : public harq_timeout_handler, public sched_met /// \brief Handle Error Indication reported to the scheduler for a given cell. void handle_error_indication(); - void handle_ul_delay(du_ue_index_t ue_index, double delay); + void handle_ul_delay(du_ue_index_t ue_index, double delay_ms); /// \brief Handle results stored in the scheduler result and push new entry. void push_result(slot_point sl_tx, const sched_result& slot_result, std::chrono::microseconds slot_decision_latency); diff --git a/lib/scheduler/scheduler_impl.cpp b/lib/scheduler/scheduler_impl.cpp index 8f057a222d..52f76c6f4c 100644 --- a/lib/scheduler/scheduler_impl.cpp +++ b/lib/scheduler/scheduler_impl.cpp @@ -160,6 +160,13 @@ void scheduler_impl::handle_uci_indication(const uci_indication& uci) cells[uci.cell_index]->ue_sched.get_feedback_handler().handle_uci_indication(uci); } +void scheduler_impl::handle_srs_indication(const srs_indication& srs) +{ + srsran_assert(cells.contains(srs.cell_index), "cell={} does not exist", srs.cell_index); + + cells[srs.cell_index]->ue_sched.get_feedback_handler().handle_srs_indication(srs); +} + void scheduler_impl::handle_dl_mac_ce_indication(const dl_mac_ce_indication& mac_ce) { du_cell_group_index_t grp_idx = cfg_mng.get_cell_group_index(mac_ce.ue_index); diff --git a/lib/scheduler/scheduler_impl.h b/lib/scheduler/scheduler_impl.h index 377b70b4be..f61f119341 100644 --- a/lib/scheduler/scheduler_impl.h +++ b/lib/scheduler/scheduler_impl.h @@ -65,6 +65,7 @@ class scheduler_impl final : public mac_scheduler void handle_rach_indication(const rach_indication_message& msg) override; void handle_crc_indication(const ul_crc_indication& crc) override; void handle_uci_indication(const uci_indication& uci) override; + void handle_srs_indication(const srs_indication& srs) override; private: const scheduler_expert_config expert_params; diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 41f9d02660..71a62192ef 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -382,8 +382,9 @@ void ue_event_manager::handle_crc_indication(const ul_crc_indication& crc_ind) if (not cell_specific_events[crc_ind.cell_index].try_push(cell_event_t{ crc_ind.crcs[i].ue_index, [this, sl_rx = crc_ind.sl_rx, crc = crc_ind.crcs[i]](ue_cell& ue_cc) { - double delay_ms = - static_cast(last_sl - sl_rx) * (10 / du_cells[ue_cc.cell_index].cfg->nof_slots_per_frame); + const double delay_ms = + static_cast(last_sl - sl_rx) * + (static_cast(10) / static_cast(du_cells[ue_cc.cell_index].cfg->nof_slots_per_frame)); const int tbs = ue_cc.handle_crc_pdu(sl_rx, crc); if (tbs < 0) { @@ -540,6 +541,13 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) } } +void ue_event_manager::handle_srs_indication(const srs_indication& ind) +{ + srsran_sanity_check(cell_exists(ind.cell_index), "Invalid cell index"); + + // TODO: Implement SRS handling. +} + void ue_event_manager::handle_dl_mac_ce_indication(const dl_mac_ce_indication& ce) { auto handle_mac_ce_impl = [this, ce]() { diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.h b/lib/scheduler/ue_scheduling/ue_event_manager.h index 426deffae2..a8541358fd 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.h +++ b/lib/scheduler/ue_scheduling/ue_event_manager.h @@ -73,6 +73,7 @@ class ue_event_manager final : public sched_ue_configuration_handler, void handle_ul_bsr_indication(const ul_bsr_indication_message& bsr) override; void handle_crc_indication(const ul_crc_indication& crc) override; void handle_uci_indication(const uci_indication& uci) override; + void handle_srs_indication(const srs_indication& srs) override; void handle_dl_mac_ce_indication(const dl_mac_ce_indication& ce) override; void handle_ul_phr_indication(const ul_phr_indication_message& phr_ind) override; diff --git a/tests/e2e/tests/ping.py b/tests/e2e/tests/ping.py index fe8c186b7d..9c8dd35141 100644 --- a/tests/e2e/tests/ping.py +++ b/tests/e2e/tests/ping.py @@ -227,7 +227,7 @@ def test_android_hp( ], ) # pylint: disable=too-many-arguments,too-many-positional-arguments -def test_zmq( +def test_zmq_32( retina_manager: RetinaTestManager, retina_data: RetinaTestData, ue_32: Tuple[UEStub, ...], @@ -260,6 +260,65 @@ def test_zmq( ) +@mark.parametrize( + "band, common_scs, bandwidth, ciphering", + ( + param(3, 15, 5, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(3, 15, 10, False, marks=mark.test, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(3, 15, 20, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(3, 15, 50, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(3, 15, 50, True, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(41, 30, 10, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(41, 30, 20, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(41, 30, 50, False, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + param(41, 30, 50, True, id="band:%s-scs:%s-bandwidth:%s-ciphering:%s"), + ), +) +@mark.zmq +@mark.flaky( + reruns=2, + only_rerun=[ + "failed to start", + "Attach timeout reached", + "Some packages got lost", + "socket is already closed", + "5GC crashed", + ], +) +# pylint: disable=too-many-arguments,too-many-positional-arguments +def test_zmq_64( + retina_manager: RetinaTestManager, + retina_data: RetinaTestData, + ue_64: Tuple[UEStub, ...], + fivegc: FiveGCStub, + gnb: GNBStub, + band: int, + common_scs: int, + bandwidth: int, + ciphering: bool, +): + """ + ZMQ Pings + """ + + _ping( + retina_manager=retina_manager, + retina_data=retina_data, + ue_array=ue_64, + gnb=gnb, + fivegc=fivegc, + band=band, + common_scs=common_scs, + bandwidth=bandwidth, + sample_rate=None, # default from testbed + global_timing_advance=0, + time_alignment_calibration=0, + ue_stop_timeout=3, + enable_security_mode=ciphering, + post_command=("cu_cp --inactivity_timer=600", ""), + ) + + @mark.parametrize( "band, common_scs, bandwidth", (param(3, 15, 10, id="band:%s-scs:%s-bandwidth:%s"),), diff --git a/tests/e2e/tests/viavi.py b/tests/e2e/tests/viavi.py index 280bb76934..ccd801a564 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -70,6 +70,7 @@ class _ViaviConfiguration: expected_dl_bitrate: float = 0 expected_nof_kos: int = 0 warning_as_errors: bool = True + enable_dddsu: bool = False # pylint: disable=too-many-instance-attributes @@ -109,6 +110,7 @@ def load_yaml_config(config_filename: str) -> List[_ViaviConfiguration]: expected_ul_bitrate=test_declaration["expected_ul_bitrate"], expected_nof_kos=test_declaration["expected_nof_kos"], warning_as_errors=test_declaration["warning_as_errors"], + enable_dddsu=test_declaration.get("enable_dddsu", False), ) ) return test_declaration_list @@ -344,6 +346,7 @@ def _test_viavi( "prach_config_index": 159, "max_puschs_per_slot": test_declaration.max_puschs_per_slot, "max_pdschs_per_slot": test_declaration.max_pdschs_per_slot, + "enable_dddsu": test_declaration.enable_dddsu, "enable_qos_viavi": test_declaration.enable_qos_viavi, "nof_antennas_dl": 4, "nof_antennas_ul": 1, diff --git a/tests/e2e/tests/viavi/test_declaration.yml b/tests/e2e/tests/viavi/test_declaration.yml index f561d2a66b..7c1c43425a 100644 --- a/tests/e2e/tests/viavi/test_declaration.yml +++ b/tests/e2e/tests/viavi/test_declaration.yml @@ -162,6 +162,21 @@ tests: expected_nof_kos: 9999999999999 warning_as_errors: false + - campaign_filename: *campaign_filename + test_name: "32UE ideal UDP attach-detach with traffic" + test_timeout: *test_timeout + gnb_extra_commands: "log --ngap_level=debug metrics --rlc_report_period=1000" + id: "32UE ideal UDP attach-detach with traffic DDDSU" + max_pdschs_per_slot: 1 + max_puschs_per_slot: 4 + enable_qos_viavi: false + # test/fail criteria + expected_dl_bitrate: 14.0e+3 + expected_ul_bitrate: 1.0e+3 + expected_nof_kos: 9999999999999 + warning_as_errors: false + enable_dddsu: true + - campaign_filename: *campaign_filename test_name: "1UE birth-death UDP bidirectional" test_timeout: *test_timeout diff --git a/tests/e2e/tests/viavi/test_declaration_schema.json b/tests/e2e/tests/viavi/test_declaration_schema.json index 392fb7237f..03ce347f4a 100644 --- a/tests/e2e/tests/viavi/test_declaration_schema.json +++ b/tests/e2e/tests/viavi/test_declaration_schema.json @@ -42,6 +42,9 @@ }, "warning_as_errors": { "type": "boolean" + }, + "enable_dddsu": { + "type": "boolean" } }, "required": [ diff --git a/tests/integrationtests/du_high/mac_test_mode_adapter_test.cpp b/tests/integrationtests/du_high/mac_test_mode_adapter_test.cpp index 3200a41a3a..41ad7f3270 100644 --- a/tests/integrationtests/du_high/mac_test_mode_adapter_test.cpp +++ b/tests/integrationtests/du_high/mac_test_mode_adapter_test.cpp @@ -82,6 +82,10 @@ class mac_dummy : public mac_interface, void handle_rach_indication(const mac_rach_indication& rach_ind) override {} void handle_crc(const mac_crc_indication_message& msg) override { events.last_crc = msg; } void handle_uci(const mac_uci_indication_message& msg) override { events.last_uci = msg; } + void handle_srs(const mac_srs_indication_message& msg) override + { + // TODO: Implement this. + } void handle_dl_buffer_state_update(const mac_dl_buffer_state_indication_message& dl_bs) override {} void handle_slot_indication(slot_point sl_tx) override { diff --git a/tests/integrationtests/e2ap/e2ap_integration_test.cpp b/tests/integrationtests/e2ap/e2ap_integration_test.cpp index 875637b5ef..cc35ad4514 100644 --- a/tests/integrationtests/e2ap/e2ap_integration_test.cpp +++ b/tests/integrationtests/e2ap/e2ap_integration_test.cpp @@ -203,8 +203,8 @@ class e2ap_gw_connector_integration_test : public ::testing::Test f1ap_ue_id_mapper = std::make_unique(); e2_client = std::make_unique(*epoll_broker, nw_config, *pcap); du_param_configurator = std::make_unique(); - e2ap = create_e2_entity( - cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *du_param_configurator, factory, ctrl_worker); + e2ap = create_e2_du_entity( + cfg, e2_client.get(), &(*du_metrics), &(*f1ap_ue_id_mapper), &(*du_param_configurator), factory, ctrl_worker); } e2ap_configuration cfg; diff --git a/tests/unittests/cu_cp/CMakeLists.txt b/tests/unittests/cu_cp/CMakeLists.txt index f3ab93d96b..066bb16f70 100644 --- a/tests/unittests/cu_cp/CMakeLists.txt +++ b/tests/unittests/cu_cp/CMakeLists.txt @@ -39,7 +39,7 @@ add_library(cu_cp_test_helpers du_processor_test_messages.cpp test_helpers.cpp) target_include_directories(cu_cp_test_helpers PRIVATE ${CMAKE_SOURCE_DIR}) -target_link_libraries(cu_cp_test_helpers srsran_cu_cp srsran_support srslog f1ap_test_helpers e1ap_test_helpers f1ap_asn1 ngap_asn1 e1ap_asn1) +target_link_libraries(cu_cp_test_helpers srsran_cu_cp srsran_support srslog f1ap_test_helpers e1ap_test_helpers f1ap_asn1 ngap_asn1 e1ap_asn1 srsran_e2) add_to_exported_libs(cu_cp_test_helpers) diff --git a/tests/unittests/cu_cp/du_processor/CMakeLists.txt b/tests/unittests/cu_cp/du_processor/CMakeLists.txt index ab96f8790f..89fe3cd0b0 100644 --- a/tests/unittests/cu_cp/du_processor/CMakeLists.txt +++ b/tests/unittests/cu_cp/du_processor/CMakeLists.txt @@ -39,6 +39,6 @@ set(SOURCES add_executable(du_processor_test ${SOURCES}) target_include_directories(du_processor_test PRIVATE ${CMAKE_SOURCE_DIR}) -target_link_libraries(du_processor_test du_processor_test_helpers srsran_support srslog gtest gtest_main) +target_link_libraries(du_processor_test du_processor_test_helpers srsran_support srsran_e2 srslog gtest gtest_main) add_test(du_processor_test du_processor_test) set_tests_properties(du_processor_test PROPERTIES LABELS "LABELS;du_processor") diff --git a/tests/unittests/cu_cp/up_resource_manager/CMakeLists.txt b/tests/unittests/cu_cp/up_resource_manager/CMakeLists.txt index f26cd0af4d..183515bf0d 100644 --- a/tests/unittests/cu_cp/up_resource_manager/CMakeLists.txt +++ b/tests/unittests/cu_cp/up_resource_manager/CMakeLists.txt @@ -21,5 +21,5 @@ set_directory_properties(PROPERTIES LABELS "cu_cp") add_executable(up_resource_manager_test up_resource_manager_test.cpp) -target_link_libraries(up_resource_manager_test srsran_up_resource_manager du_processor_test_helpers srsran_support srslog gtest gtest_main) +target_link_libraries(up_resource_manager_test srsran_up_resource_manager du_processor_test_helpers srsran_support srslog gtest gtest_main srsran_e2) gtest_discover_tests(up_resource_manager_test) diff --git a/tests/unittests/du_manager/du_ue/ue_manager_test.cpp b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp index fbb30b478f..9f01501d7b 100644 --- a/tests/unittests/du_manager/du_ue/ue_manager_test.cpp +++ b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp @@ -184,6 +184,7 @@ TEST_F(du_ue_manager_tester, // Action 1: UL CCCH Message and UE deletion request received concurrently. push_ul_ccch_message(create_ul_ccch_message(to_rnti(0x4601))); push_f1ap_ue_delete_request(get_last_ue_index()); + worker.run_pending_tasks(); // MAC and F1AP receive request to create UE. ASSERT_TRUE(mac_dummy.last_ue_create_msg.has_value()); @@ -193,6 +194,7 @@ TEST_F(du_ue_manager_tester, ASSERT_FALSE(mac_dummy.last_ue_delete_msg.has_value()); ASSERT_FALSE(f1ap_dummy.last_ue_release_req.has_value()); mac_completes_ue_creation(true); + worker.run_pending_tasks(); ASSERT_TRUE(mac_dummy.last_ue_delete_msg.has_value()); ASSERT_EQ(get_last_ue_index(), mac_dummy.last_ue_delete_msg->ue_index); @@ -288,6 +290,7 @@ TEST_F(du_ue_manager_tester, when_ue_is_being_removed_then_ue_notifiers_get_disc // TEST: UE notifiers are disconnected. mac_dummy.last_dl_bs.reset(); srb1.on_buffer_state_update(10); + worker.run_pending_tasks(); ASSERT_TRUE(not mac_dummy.last_dl_bs.has_value() or mac_dummy.last_dl_bs.value().bs == 0); } @@ -417,6 +420,7 @@ TEST_F(du_ue_manager_rlf_tester, when_ue_is_being_deleted_then_rlf_should_have_n { // Action: Initiate UE removal. push_f1ap_ue_delete_request(get_last_ue_index()); + worker.run_pending_tasks(); // Test: UE removal is under way. ASSERT_TRUE(mac_dummy.last_ue_delete_msg.has_value()); @@ -439,6 +443,7 @@ TEST_F(du_ue_manager_rlf_tester, when_rlf_is_triggered_but_ue_removal_starts_the // Action: Initiate UE removal. push_f1ap_ue_delete_request(get_last_ue_index()); + worker.run_pending_tasks(); // Test: UE removal is under way. ASSERT_TRUE(mac_dummy.last_ue_delete_msg.has_value()); diff --git a/tests/unittests/du_manager/serving_cell_config_converter_test.cpp b/tests/unittests/du_manager/serving_cell_config_converter_test.cpp index 4a25f4b0a5..d6f6fcc7eb 100644 --- a/tests/unittests/du_manager/serving_cell_config_converter_test.cpp +++ b/tests/unittests/du_manager/serving_cell_config_converter_test.cpp @@ -98,7 +98,7 @@ srs_config make_initial_srs_config() .srs_res_id_list = {static_cast(0)}, .res_type = srs_config::srs_resource_set::aperiodic_resource_type{.aperiodic_srs_res_trigger = 1, .slot_offset = 2}, - .srs_res_set_usage = srs_config::srs_resource_set::usage::codebook, + .srs_res_set_usage = srs_usage::codebook, .srs_pwr_ctrl_alpha = alpha::alpha1, .p0 = -80}); srs_config::srs_resource::tx_comb_params tx_comb{ @@ -749,7 +749,7 @@ TEST(serving_cell_config_converter_test, test_ue_custom_srs_cfg_conversion) srs_config::srs_resource_set{.id = static_cast(1), .srs_res_id_list = {static_cast(1)}, .res_type = semi_persistent_resource, - .srs_res_set_usage = srs_config::srs_resource_set::usage::non_codebook, + .srs_res_set_usage = srs_usage::non_codebook, .srs_pwr_ctrl_alpha = alpha::alpha07, .p0 = -70}); // Release. diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 850ba00217..568513a9a9 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -33,6 +33,7 @@ #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/asn1/e2sm/e2sm_rc_ies.h" #include "srsran/e2/e2.h" +#include "srsran/e2/e2_du_factory.h" #include "srsran/e2/e2_factory.h" #include "srsran/e2/e2ap_configuration_helpers.h" #include "srsran/e2/e2sm/e2sm.h" @@ -284,8 +285,6 @@ inline e2_message generate_ric_control_request(srslog::basic_logger& logger, class dummy_e2_du_metrics : public e2_du_metrics_interface { public: - void get_metrics(scheduler_ue_metrics& ue_metrics) override {} - void connect_e2_du_meas_provider(std::unique_ptr meas_provider) override { e2_meas_provider = std::move(meas_provider); @@ -343,9 +342,9 @@ class dummy_e2sm_kpm_du_meas_provider : public e2sm_kpm_meas_provider { return supported_metrics; }; - virtual bool cell_supported(const asn1::e2sm::cgi_c& cell_global_id) override { return true; }; - virtual bool ue_supported(const asn1::e2sm::ue_id_c& ueid) override { return true; }; - virtual bool test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) override { return true; }; + virtual bool is_cell_supported(const asn1::e2sm::cgi_c& cell_global_id) override { return true; }; + virtual bool is_ue_supported(const asn1::e2sm::ue_id_c& ueid) override { return true; }; + virtual bool is_test_cond_supported(const asn1::e2sm::test_cond_type_c& test_cond_type) override { return true; }; virtual bool get_ues_matching_test_conditions(const asn1::e2sm::matching_cond_list_l& matching_cond_list, std::vector& ues) override @@ -360,10 +359,10 @@ class dummy_e2sm_kpm_du_meas_provider : public e2sm_kpm_meas_provider return get_ues_matching_cond(ues); }; - virtual bool metric_supported(const asn1::e2sm::meas_type_c& meas_type, - const asn1::e2sm::meas_label_s& label, - const e2sm_kpm_metric_level_enum level, - const bool& cell_scope) override + virtual bool is_metric_supported(const asn1::e2sm::meas_type_c& meas_type, + const asn1::e2sm::meas_label_s& label, + const e2sm_kpm_metric_level_enum level, + const bool& cell_scope) override { if (std::find(supported_metrics.begin(), supported_metrics.end(), meas_type.meas_name().to_string()) != supported_metrics.end()) { @@ -903,8 +902,8 @@ class e2_entity_test : public e2_test_base f1ap_ue_id_mapper = std::make_unique(); factory = timer_factory{timers, task_worker}; rc_param_configurator = std::make_unique(); - e2 = create_e2_entity( - cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *rc_param_configurator, factory, task_worker); + e2 = create_e2_du_entity( + cfg, e2_client.get(), &(*du_metrics), &(*f1ap_ue_id_mapper), &(*rc_param_configurator), factory, task_worker); } void TearDown() override diff --git a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp index c297df010e..09b23205d5 100644 --- a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp +++ b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp @@ -46,8 +46,6 @@ inline void save_msg_pcap(const byte_buffer& last_pdu) class e2_rlc_metrics_notifier : public e2_du_metrics_notifier, public e2_du_metrics_interface { public: - void get_metrics(scheduler_ue_metrics& ue_metrics) override {} - void report_metrics(const scheduler_cell_metrics& metrics) override { if (e2_meas_provider) { diff --git a/tests/unittests/e2/e2sm_kpm_test.cpp b/tests/unittests/e2/e2sm_kpm_test.cpp index f60f58f148..8918ab3f4c 100644 --- a/tests/unittests/e2/e2sm_kpm_test.cpp +++ b/tests/unittests/e2/e2sm_kpm_test.cpp @@ -64,8 +64,8 @@ class e2_entity_test_with_pcap : public e2_test_base_with_pcap f1ap_ue_id_mapper = std::make_unique(); factory = timer_factory{timers, task_worker}; rc_param_configurator = std::make_unique(); - e2 = create_e2_entity( - cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *rc_param_configurator, factory, task_worker); + e2 = create_e2_du_entity( + cfg, e2_client.get(), &(*du_metrics), &(*f1ap_ue_id_mapper), &(*rc_param_configurator), factory, task_worker); } void TearDown() override diff --git a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp index fc09d0d73b..72aa8e5803 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp @@ -221,7 +221,7 @@ f1ap_du_test::f1ap_du_test() srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::debug); srslog::init(); - f1ap = create_f1ap(f1c_gw, f1ap_du_cfg_handler, ctrl_worker, ue_exec_mapper, paging_handler); + f1ap = create_f1ap(f1c_gw, f1ap_du_cfg_handler, ctrl_worker, ue_exec_mapper, paging_handler, timer_service); f1ap_du_cfg_handler.connect(*f1ap); } diff --git a/tests/unittests/fapi/builders/srs_indication_test.cpp b/tests/unittests/fapi/builders/srs_indication_test.cpp index 81fa9701f0..fa99194bfd 100644 --- a/tests/unittests/fapi/builders/srs_indication_test.cpp +++ b/tests/unittests/fapi/builders/srs_indication_test.cpp @@ -41,7 +41,7 @@ TEST(srs_indication_builder, valid_srs_indication_passes) std::optional timing = 0; std::optional timing_ns = 0; - srs_usage_mode srs_usage = srs_usage_mode::codebook; + srs_usage usage = srs_usage::codebook; pdu_builder.set_metrics_parameters(timing, timing_ns); @@ -59,7 +59,7 @@ TEST(srs_indication_builder, valid_srs_indication_passes) ASSERT_EQ(timing ? timing.value() : std::numeric_limits::max(), pdu.timing_advance_offset); ASSERT_EQ(timing_ns ? timing_ns.value() : std::numeric_limits::max(), pdu.timing_advance_offset_ns); - ASSERT_EQ(srs_usage, pdu.srs_usage); + ASSERT_EQ(usage, pdu.usage); ASSERT_EQ(matrix.get_nof_rx_ports(), pdu.matrix.get_nof_rx_ports()); ASSERT_EQ(matrix.get_nof_tx_ports(), pdu.matrix.get_nof_tx_ports()); } diff --git a/tests/unittests/fapi/message_builder_helpers.cpp b/tests/unittests/fapi/message_builder_helpers.cpp index 379c4eb666..8c802feec0 100644 --- a/tests/unittests/fapi/message_builder_helpers.cpp +++ b/tests/unittests/fapi/message_builder_helpers.cpp @@ -1283,7 +1283,7 @@ srs_indication_message unittest::build_valid_srs_indication() pdu.rnti = generate_rnti(); pdu.timing_advance_offset = generate_timing_advance_offset(); pdu.timing_advance_offset_ns = generate_timing_advance_offset_in_ns(); - pdu.srs_usage = srs_usage_mode::codebook; + pdu.usage = srs_usage::codebook; return msg; } diff --git a/tests/unittests/mac/mac_cell_processor_test.cpp b/tests/unittests/mac/mac_cell_processor_test.cpp index 04cd751beb..bc81f0ba69 100644 --- a/tests/unittests/mac/mac_cell_processor_test.cpp +++ b/tests/unittests/mac/mac_cell_processor_test.cpp @@ -39,7 +39,8 @@ class base_mac_cell_processor_test task_worker, task_worker, task_worker, - pcap) + pcap, + timers) { } @@ -54,6 +55,7 @@ class base_mac_cell_processor_test test_helpers::dummy_mac_cell_result_notifier phy_notifier; manual_task_worker task_worker{128}; null_mac_pcap pcap; + timer_manager timers; mac_cell_processor mac_cell; }; diff --git a/tests/unittests/mac/mac_dl_cfg_test.cpp b/tests/unittests/mac/mac_dl_cfg_test.cpp index c637c0426a..3457c2022d 100644 --- a/tests/unittests/mac/mac_dl_cfg_test.cpp +++ b/tests/unittests/mac/mac_dl_cfg_test.cpp @@ -111,8 +111,9 @@ TEST(test_mac_dl_cfg, test_dl_ue_procedure_execution_contexts) dummy_mac_result_notifier phy_notifier; dummy_scheduler_ue_metrics_notifier metrics_notif; null_mac_pcap pcap; - mac_dl_config mac_dl_cfg{ul_exec_mapper, dl_exec_mapper, ctrl_worker, phy_notifier, pcap}; - mac_config maccfg{du_mng_notifier, + timer_manager timers; + mac_dl_config mac_dl_cfg{ul_exec_mapper, dl_exec_mapper, ctrl_worker, phy_notifier, pcap, timers}; + mac_config maccfg{du_mng_notifier, ul_exec_mapper, dl_exec_mapper, ctrl_worker, @@ -120,8 +121,9 @@ TEST(test_mac_dl_cfg, test_dl_ue_procedure_execution_contexts) mac_expert_config{.configs = {{10000, 10000, 10000}}}, pcap, scheduler_expert_config{}, - metrics_notif}; - rnti_manager rnti_mng; + metrics_notif, + timers}; + rnti_manager rnti_mng; srsran_scheduler_adapter sched_cfg_adapter{maccfg, rnti_mng}; mac_dl_processor mac_dl(mac_dl_cfg, sched_cfg_adapter, rnti_mng); @@ -163,9 +165,10 @@ TEST(test_mac_dl_cfg, test_dl_ue_procedure_tsan) dummy_mac_event_indicator du_mng_notifier; dummy_mac_result_notifier phy_notifier; null_mac_pcap pcap; + timer_manager timers; dummy_scheduler_ue_metrics_notifier metrics_notif; - mac_dl_config mac_dl_cfg{ul_exec_mapper, dl_exec_mapper, ctrl_worker, phy_notifier, pcap}; - mac_config maccfg{du_mng_notifier, + mac_dl_config mac_dl_cfg{ul_exec_mapper, dl_exec_mapper, ctrl_worker, phy_notifier, pcap, timers}; + mac_config maccfg{du_mng_notifier, ul_exec_mapper, dl_exec_mapper, ctrl_worker, @@ -173,8 +176,9 @@ TEST(test_mac_dl_cfg, test_dl_ue_procedure_tsan) mac_expert_config{.configs = {{10000, 10000, 10000}}}, pcap, scheduler_expert_config{}, - metrics_notif}; - rnti_manager rnti_mng; + metrics_notif, + timers}; + rnti_manager rnti_mng; srsran_scheduler_adapter sched_cfg_adapter{maccfg, rnti_mng}; mac_dl_processor mac_dl(mac_dl_cfg, sched_cfg_adapter, rnti_mng); diff --git a/tests/unittests/mac/mac_ul_processor_test.cpp b/tests/unittests/mac/mac_ul_processor_test.cpp index 901eda72bd..fed0550885 100644 --- a/tests/unittests/mac/mac_ul_processor_test.cpp +++ b/tests/unittests/mac/mac_ul_processor_test.cpp @@ -216,7 +216,8 @@ struct test_bench { rnti_manager rnti_mng; dummy_sched_ce_info_handler sched_ce_handler; null_mac_pcap pcap; - mac_ul_config cfg{task_exec, ul_exec_mapper, du_mng_notifier, sched_ce_handler, rnti_mng, pcap}; + timer_manager timers; + mac_ul_config cfg{task_exec, ul_exec_mapper, du_mng_notifier, sched_ce_handler, rnti_mng, pcap, timers}; // This is the RNTI of the UE that appears in the mac_rx_pdu created by send_rx_indication_msg() du_cell_index_t cell_idx; mac_ul_processor mac_ul{cfg}; diff --git a/tests/unittests/scheduler/common_scheduling/ra_scheduler_test.cpp b/tests/unittests/scheduler/common_scheduling/ra_scheduler_test.cpp index 9059667d71..4dd1238237 100644 --- a/tests/unittests/scheduler/common_scheduling/ra_scheduler_test.cpp +++ b/tests/unittests/scheduler/common_scheduling/ra_scheduler_test.cpp @@ -22,6 +22,7 @@ #include "lib/scheduler/common_scheduling/ra_scheduler.h" #include "lib/scheduler/logging/scheduler_event_logger.h" +#include "lib/scheduler/logging/scheduler_metrics_handler.h" #include "lib/scheduler/logging/scheduler_result_logger.h" #include "tests/unittests/scheduler/test_utils/config_generators.h" #include "tests/unittests/scheduler/test_utils/dummy_test_components.h" @@ -57,7 +58,10 @@ class base_ra_scheduler_test static constexpr unsigned tx_rx_delay = 2U; base_ra_scheduler_test(duplex_mode dplx_mode, const test_params& params_) : - params(params_), cell_cfg(sched_cfg, get_sched_req(dplx_mode, params)), ev_logger(to_du_cell_index(0), cell_cfg.pci) + params(params_), + cell_cfg(sched_cfg, get_sched_req(dplx_mode, params)), + ev_logger(to_du_cell_index(0), cell_cfg.pci), + metrics_hdlr(std::chrono::milliseconds{0}, metrics_notifier, cell_cfg) { mac_logger.set_level(srslog::basic_levels::debug); test_logger.set_level(srslog::basic_levels::info); @@ -444,13 +448,15 @@ class base_ra_scheduler_test srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("SCHED", true); srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); - scheduler_expert_config sched_cfg{config_helpers::make_default_scheduler_expert_config()}; - cell_configuration cell_cfg; - scheduler_event_logger ev_logger; - cell_resource_allocator res_grid{cell_cfg}; - dummy_pdcch_resource_allocator pdcch_sch; - ra_scheduler ra_sch{sched_cfg.ra, cell_cfg, pdcch_sch, ev_logger}; - scheduler_result_logger result_logger{false, cell_cfg.pci}; + scheduler_expert_config sched_cfg{config_helpers::make_default_scheduler_expert_config()}; + cell_configuration cell_cfg; + scheduler_event_logger ev_logger; + scheduler_ue_metrics_dummy_notifier metrics_notifier; + cell_metrics_handler metrics_hdlr; + cell_resource_allocator res_grid{cell_cfg}; + dummy_pdcch_resource_allocator pdcch_sch; + ra_scheduler ra_sch{sched_cfg.ra, cell_cfg, pdcch_sch, ev_logger, metrics_hdlr}; + scheduler_result_logger result_logger{false, cell_cfg.pci}; slot_point next_slot{to_numerology_value(params.scs), test_rgen::uniform_int(0, (10240 << to_numerology_value(params.scs)) - 1)};